aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMukilan Thiyagarajan <mukilan@igalia.com>2024-01-22 18:30:15 +0530
committerGitHub <noreply@github.com>2024-01-22 13:00:15 +0000
commitd7de206dbd459e8c8bf121f73755d12569c6cc55 (patch)
tree34af7250352bd0b5c00aa56bfac6b086d30713a4
parent8e6bdb69b1b5110ac7fce5801d8ee3e9fd7c6354 (diff)
downloadservo-d7de206dbd459e8c8bf121f73755d12569c6cc55.tar.gz
servo-d7de206dbd459e8c8bf121f73755d12569c6cc55.zip
Preliminary Android build support (#31086)
* Android build * Fixes * More fixes - Still failing in the linking step * More work on getting linking working Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * android: use mozjs with ndk r25c. loads servo.org more android build fixes. * fix ./mach run for android and make it follow logs Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * add experimental logic for compositor pause/resume Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * pass DPI from android to simpleservo Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * ci: add android workflow Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * switch to ANDROID_SDK_ROOT and ANDROID_NDK_ROOT vars Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * upgrade gradle to 4.10.1 Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * upgrade to gradle 5.1.1 Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * upgrade to gradle 8 and agp 8 Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * make compositing work again with external present Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * android: improve mach support for non-NixOS and CI Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * fix sampler compilation bug introduced in #30490 Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * ci: add android build to main workflow Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * gradle: set MinSdk = targetSdk = 30 NDK requires we compile against the minSdk API level which is 30 in our case. Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * add instructions for android in README.md Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * apk: move servosurface to servoview Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * apk: uncomment the mediasession callbacks on MainActivity Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * apk: fix crash on MainAtivity.onDestroy Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * apk: drop VR, arm 5 and unused code This commit drops: * support for google, oculusvr * support for arm5 architecture and also removes * fakeld scripts * unused java code Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * cleanup shell.nix Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * android: add FIXMEs for gstreamer code Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * apk: remove commented code and debug logs Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * cleanup ServoView.java Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * mach: comment call to download gstreamer deps for android Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * disable bluetooth for jniapi as blurdroid is broken Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * fixup! README.md * fixup! remove change in Cargo.toml * fixup! move shell variables together * fixup! cleanup jniapi/Cargo.toml comments * delete commented gstreamer related android code Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * remove unused config variable in servbuild Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * android: more cleanup Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * force no_static_freetype only for android * use actions to manage sdk, ndk and java Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * rename embedder event names to be more clear. Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * link to startup crash issue Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * fix lint issues Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * upgrade env_logger to 0.10 with duplicate exception libservo and android_logger can use env_logger 0.10 but quickcheck is still stuck on 0.8 and has not seen any activity in the last 2 years. This commit adds a duplicate exception until the quickcheck dependency can be upgraded (or replaced) Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * android: fix comments Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * disable jemalloc on android Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> * fixup! replace linux with android in cfg --------- Signed-off-by: Mukilan Thiyagarajan <mukilan@igalia.com> Co-authored-by: Martin Robinson <mrobinson@igalia.com>
-rw-r--r--.cargo/config.toml25
-rw-r--r--.github/workflows/android.yml107
-rw-r--r--.github/workflows/main.yml13
-rw-r--r--Cargo.lock48
-rw-r--r--Cargo.toml2
-rw-r--r--README.md27
-rw-r--r--components/allocator/Cargo.toml5
-rw-r--r--components/allocator/lib.rs17
-rw-r--r--components/background_hang_monitor/background_hang_monitor.rs6
-rw-r--r--components/bluetooth/Cargo.toml1
-rw-r--r--components/compositing/compositor.rs27
-rw-r--r--components/compositing/windowing.rs11
-rw-r--r--components/gfx/platform/freetype/android/font_list.rs3
-rw-r--r--components/profile/Cargo.toml2
-rw-r--r--components/profile/mem.rs14
-rw-r--r--components/servo/lib.rs12
-rw-r--r--components/webrender_surfman/lib.rs24
-rwxr-xr-xetc/run_in_headless_android_emulator.py4
-rw-r--r--etc/shell.nix36
-rw-r--r--ports/libsimpleservo/api/src/lib.rs30
-rw-r--r--ports/libsimpleservo/jniapi/Cargo.toml12
-rw-r--r--ports/libsimpleservo/jniapi/build.rs33
-rw-r--r--ports/libsimpleservo/jniapi/src/lib.rs180
-rw-r--r--python/servo/bootstrap_commands.py147
-rw-r--r--python/servo/build_commands.py1
-rw-r--r--python/servo/command_base.py193
-rw-r--r--python/servo/package_commands.py5
-rw-r--r--python/servo/post_build_commands.py3
-rw-r--r--servo-tidy.toml4
-rw-r--r--servobuild.example4
-rw-r--r--support/android/apk/build.gradle66
-rw-r--r--support/android/apk/gradle.properties21
-rw-r--r--support/android/apk/gradle/wrapper/gradle-wrapper.jarbin53636 -> 55190 bytes
-rw-r--r--support/android/apk/gradle/wrapper/gradle-wrapper.properties3
-rwxr-xr-xsupport/android/apk/gradlew72
-rw-r--r--support/android/apk/gradlew.bat14
-rw-r--r--support/android/apk/jni/Android.mk8
-rw-r--r--support/android/apk/jni/Application.mk8
-rw-r--r--support/android/apk/servoapp/build.gradle34
-rw-r--r--support/android/apk/servoapp/src/googlevr/AndroidManifest.xml19
-rw-r--r--support/android/apk/servoapp/src/main/AndroidManifest.xml3
-rw-r--r--support/android/apk/servoapp/src/main/java/org/mozilla/servo/MainActivity.java51
-rw-r--r--support/android/apk/servoapp/src/main/res/layout/activity_main.xml4
-rw-r--r--support/android/apk/servoview/build.gradle162
-rw-r--r--support/android/apk/servoview/src/googlevr/AndroidManifest.xml19
-rw-r--r--support/android/apk/servoview/src/main/AndroidManifest.xml3
-rw-r--r--support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java8
-rw-r--r--support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java19
-rw-r--r--support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java302
-rw-r--r--support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java334
-rw-r--r--support/android/apk/servoview/src/oculusvr/AndroidManifest.xml10
-rw-r--r--support/android/apk/settings.gradle16
-rwxr-xr-xsupport/android/fakeld/fake-ld-arm.sh14
-rwxr-xr-xsupport/android/fakeld/fake-ld-arm64.sh14
-rwxr-xr-xsupport/android/fakeld/fake-ld-armv7.sh14
-rwxr-xr-xsupport/android/fakeld/fake-ld-x86.sh14
-rw-r--r--support/android/fakeld/fake-ld.cmd2
-rwxr-xr-xsupport/android/fakeld/fake-ld.sh39
58 files changed, 905 insertions, 1364 deletions
diff --git a/.cargo/config.toml b/.cargo/config.toml
index 836726e6d8e..e1bdd061199 100644
--- a/.cargo/config.toml
+++ b/.cargo/config.toml
@@ -1,26 +1,17 @@
-[target.arm-linux-androideabi]
-linker = "./support/android/fakeld/fake-ld-arm.sh"
-ar = "arm-linux-androideabi-ar"
+[target.aarch64-linux-android]
+linker = "aarch64-linux-android30-clang"
[target.armv7-linux-androideabi]
-linker = "./support/android/fakeld/fake-ld-armv7.sh"
-ar = "arm-linux-androideabi-ar"
+linker = "armv7a-linux-androideabi30-clang"
-[target.aarch64-linux-android]
-linker = "./support/android/fakeld/fake-ld-arm64.sh"
-ar = "aarch64-linux-android-ar"
+[target.armv-linux-androideabi]
+linker = "armv7a-linux-androideabi30-clang"
[target.i686-linux-android]
-linker = "./support/android/fakeld/fake-ld-x86.sh"
-ar = "i686-linux-android-ar"
-
-[target.arm-unknown-linux-gnueabihf]
-linker = "arm-linux-gnueabihf-gcc"
-ar = "arm-linux-gnueabihf-ar"
+linker = "i686-linux-android30-clang"
-[target.aarch64-unknown-linux-gnu]
-linker = "aarch64-linux-gnu-gcc"
-ar = "aarch64-linux-gnu-ar"
+[target.x86_64-linux-android]
+linker = "x86_64-linux-android30-clang"
[target.x86_64-pc-windows-msvc]
linker = "lld-link.exe"
diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml
new file mode 100644
index 00000000000..db4cbde755d
--- /dev/null
+++ b/.github/workflows/android.yml
@@ -0,0 +1,107 @@
+name: Android
+on:
+ workflow_call:
+ inputs:
+ profile:
+ required: false
+ default: "release"
+ type: string
+ workflow_dispatch:
+ inputs:
+ profile:
+ required: false
+ default: "release"
+ type: string
+ options: ["release", "debug", "production"]
+ push:
+ branches: ["try-android"]
+
+env:
+ RUST_BACKTRACE: 1
+ SHELL: /bin/bash
+ SCCACHE_GHA_ENABLED: "true"
+ CCACHE: "sccache"
+ CARGO_INCREMENTAL: 0
+
+jobs:
+ build:
+ name: Android Build
+ runs-on: ubuntu-22.04
+ strategy:
+ matrix:
+ arch: ['armv7-linux-androideabi', 'i686-linux-android']
+ steps:
+ - uses: actions/checkout@v3
+ if: github.event_name != 'issue_comment' && github.event_name != 'pull_request_target'
+ with:
+ fetch-depth: 2
+ # This is necessary to checkout the pull request if this run was triggered
+ # via an `issue_comment` action on a pull request.
+ - uses: actions/checkout@v3
+ if: github.event_name == 'issue_comment' || github.event_name == 'pull_request_target'
+ with:
+ ref: refs/pull/${{ github.event.issue.number || github.event.number }}/head
+ fetch-depth: 2
+ - name: Run sccache-cache
+ uses: mozilla-actions/sccache-action@v0.0.3
+ - name: Install taplo
+ uses: baptiste0928/cargo-install@v2
+ with:
+ crate: taplo-cli
+ locked: true
+ - name: Bootstrap Python
+ run: python3 -m pip install --upgrade pip virtualenv
+ - name: Bootstrap dependencies
+ run: sudo apt update && python3 ./mach bootstrap
+ - name: Set up JDK 17
+ uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ - name: Setup Android SDK
+ uses: android-actions/setup-android@v3
+ with:
+ packages: 'tools platform-tools platforms;android-33'
+ - name: Install Android NDK
+ uses: nttld/setup-ndk@v1
+ id: setup-ndk
+ with:
+ ndk-version: r25c
+ - name: Build (arch ${{ matrix.arch }} profile ${{ inputs.profile }})
+ env:
+ ANDROID_NDK_ROOT: ${{ steps.setup-ndk.outputs.ndk-path }}
+ run: |
+ python3 ./mach build --android --target ${{ matrix.arch }} --${{ inputs.profile }}
+ # TODO: This is disabled since APK crashes during startup.
+ # See https://github.com/servo/servo/issues/31134
+ # - name: Script tests
+ # run: ./mach test-android-startup
+ - name: Rename build timing
+ run: cp -r target/cargo-timings target/cargo-timings-android-${{ matrix.arch }}
+ - name: Archive build timing
+ uses: actions/upload-artifact@v3
+ with:
+ name: cargo-timings
+ # Using a wildcard here ensures that the archive includes the path.
+ path: target/cargo-timings-*
+ - name: Upload APK artifact for mach package
+ uses: actions/upload-artifact@v3
+ with:
+ name: android-${{ matrix.arch }}-${{ inputs.profile }}
+ path: target/android/${{ matrix.arch }}/${{ inputs.profile }}/servoapp.apk
+
+ result:
+ name: Result
+ runs-on: ubuntu-latest
+ if: always()
+ # `needs: 'build'` is necessary to detect cancellation
+ needs:
+ - "build"
+ steps:
+ - name: Mark the job as successful
+ run: exit 0
+ if: ${{ !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
+ - name: Mark the job as unsuccessful
+ run: exit 1
+ if: contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled')
+
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index 82defcc2f6c..649f66a4d82 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -76,7 +76,7 @@ jobs:
let platforms = [];
if (platform == "all") {
- platforms = [ "linux", "windows", "macos" ];
+ platforms = [ "linux", "windows", "macos", "android" ];
} else {
platforms = [ platform ];
}
@@ -125,6 +125,15 @@ jobs:
unit-tests: ${{ fromJson(needs.decision.outputs.configuration).unit_tests }}
secrets: inherit
+ build-android:
+ name: Android
+ needs: ["decision"]
+ if: ${{ contains(fromJson(needs.decision.outputs.configuration).platforms, 'android') }}
+ uses: ./.github/workflows/linux.yml
+ with:
+ profile: "release"
+ secrets: inherit
+
build-result:
name: Result
runs-on: ubuntu-latest
@@ -135,7 +144,7 @@ jobs:
- "build-win"
- "build-mac"
- "build-linux"
-
+ - "build-android"
steps:
- name: Mark skipped jobs as successful
if: ${{ fromJson(needs.decision.outputs.configuration).platforms[0] != null }}
diff --git a/Cargo.lock b/Cargo.lock
index 18a1040e12b..0a787cd600a 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -128,20 +128,20 @@ checksum = "80b9e34fcbf29c0563547cb2ecce9b49504597cad6166769b1e4efb45c6c2951"
[[package]]
name = "android_log-sys"
-version = "0.2.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e"
+checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937"
[[package]]
name = "android_logger"
-version = "0.10.1"
+version = "0.13.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9ed09b18365ed295d722d0b5ed59c01b79a826ff2d2a8f73d5ecca8e6fb2f66"
+checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f"
dependencies = [
"android_log-sys",
- "env_logger",
- "lazy_static",
+ "env_logger 0.10.1",
"log",
+ "once_cell",
]
[[package]]
@@ -1604,8 +1604,18 @@ version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
dependencies = [
- "atty",
+ "log",
+ "regex",
+]
+
+[[package]]
+name = "env_logger"
+version = "0.10.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece"
+dependencies = [
"humantime",
+ "is-terminal",
"log",
"regex",
"termcolor",
@@ -2941,6 +2951,17 @@ dependencies = [
]
[[package]]
+name = "is-terminal"
+version = "0.4.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b"
+dependencies = [
+ "hermit-abi 0.3.2",
+ "rustix",
+ "windows-sys 0.48.0",
+]
+
+[[package]]
name = "itertools"
version = "0.10.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3379,7 +3400,7 @@ dependencies = [
"devtools",
"devtools_traits",
"embedder_traits",
- "env_logger",
+ "env_logger 0.10.1",
"euclid",
"gaol",
"gfx",
@@ -4568,7 +4589,7 @@ version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
dependencies = [
- "env_logger",
+ "env_logger 0.8.4",
"log",
"rand",
]
@@ -5379,6 +5400,7 @@ version = "0.0.1"
dependencies = [
"jemalloc-sys",
"jemallocator",
+ "libc",
"winapi",
]
@@ -5592,7 +5614,7 @@ version = "0.0.1"
dependencies = [
"backtrace",
"cbindgen",
- "env_logger",
+ "env_logger 0.10.1",
"keyboard-types",
"lazy_static",
"libc",
@@ -5606,10 +5628,8 @@ dependencies = [
name = "simpleservo_jniapi"
version = "0.0.1"
dependencies = [
- "android_injected_glue",
"android_logger",
"cc",
- "gstreamer",
"jni",
"libc",
"log",
@@ -5906,9 +5926,9 @@ dependencies = [
[[package]]
name = "surfman"
-version = "0.8.0"
+version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca39befaf946247c5d3323465a9ec86c4a05523bb87a0d3eb07e71c15181a338"
+checksum = "db2e4280229411d6eb8a8f873152dece1904df2682003bdc748adc181e003568"
dependencies = [
"bitflags 1.3.2",
"cfg_aliases",
diff --git a/Cargo.toml b/Cargo.toml
index 5495afa005a..c5f7aa60a9d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -33,7 +33,7 @@ data-url = "0.1.0"
devtools_traits = { path = "components/shared/devtools" }
embedder_traits = { path = "components/shared/embedder" }
encoding_rs = "0.8"
-env_logger = "0.8"
+env_logger = "0.10"
euclid = "0.22"
fnv = "1.0"
fxhash = "0.2"
diff --git a/README.md b/README.md
index f935df82b4a..2c3a56144f6 100644
--- a/README.md
+++ b/README.md
@@ -117,6 +117,27 @@ though of course it doesn’t produce a binary you can run.
### Building for Android target
+Prerequisites:
+Servo's build system assumes that both the Android SDK & NDK are
+already installed and expects the paths to be specified via the
+environment variables `ANDROID_SDK_ROOT` and `ANDROID_NDK_ROOT`.
+
+Servo also expects the following components are installed via
+sdkmanager:
+
+For building:
+
+``` sh
+sdkmanager install platform-tools platforms;android-33
+```
+
+To run in emulator, also install the related components:
+
+``` sh
+sdkmanager install emulator system-images;android-33;google_apis;x86
+```
+
+Build commands:
For ARM (`armv7-linux-androideabi`, most phones):
``` sh
@@ -131,6 +152,12 @@ For x86 (typically for the emulator):
./mach package --release --target i686-linux-android
```
+Install the APK to the device or emulator:
+
+``` sh
+./mach install --release --android
+```
+
## Running
Run Servo with the command:
diff --git a/components/allocator/Cargo.toml b/components/allocator/Cargo.toml
index 3d29fca5cf8..7a017e4cf92 100644
--- a/components/allocator/Cargo.toml
+++ b/components/allocator/Cargo.toml
@@ -9,9 +9,12 @@ publish = false
[lib]
path = "lib.rs"
-[target.'cfg(not(windows))'.dependencies]
+[target.'cfg(not(any(windows, target_os = "android")))'.dependencies]
jemallocator = { workspace = true }
jemalloc-sys = { workspace = true }
[target.'cfg(windows)'.dependencies]
winapi = { workspace = true, features = ["heapapi"] }
+
+[target.'cfg(target_os = "android")'.dependencies]
+libc = { workspace = true }
diff --git a/components/allocator/lib.rs b/components/allocator/lib.rs
index d4e8c73b318..9d7c0b466f0 100644
--- a/components/allocator/lib.rs
+++ b/components/allocator/lib.rs
@@ -9,7 +9,7 @@ static ALLOC: Allocator = Allocator;
pub use crate::platform::*;
-#[cfg(not(windows))]
+#[cfg(not(any(windows, target_os = "android")))]
mod platform {
use std::os::raw::c_void;
@@ -28,6 +28,21 @@ mod platform {
}
}
+#[cfg(target_os = "android")]
+mod platform {
+ pub use std::alloc::System as Allocator;
+ use std::os::raw::c_void;
+
+ /// Get the size of a heap block.
+ pub unsafe extern "C" fn usable_size(ptr: *const c_void) -> usize {
+ libc::malloc_usable_size(ptr)
+ }
+
+ pub mod libc_compat {
+ pub use libc::{free, malloc, realloc};
+ }
+}
+
#[cfg(windows)]
mod platform {
pub use std::alloc::System as Allocator;
diff --git a/components/background_hang_monitor/background_hang_monitor.rs b/components/background_hang_monitor/background_hang_monitor.rs
index f8e26972a0f..1aacadfa19a 100644
--- a/components/background_hang_monitor/background_hang_monitor.rs
+++ b/components/background_hang_monitor/background_hang_monitor.rs
@@ -100,9 +100,9 @@ impl BackgroundHangMonitorRegister for HangMonitorRegister {
not(any(target_arch = "arm", target_arch = "aarch64"))
))]
let sampler = crate::sampler_linux::LinuxSampler::new();
- #[cfg(all(
- any(target_os = "android", target_os = "linux"),
- any(target_arch = "arm", target_arch = "aarch64")
+ #[cfg(any(
+ target_os = "android",
+ all(target_os = "linux", any(target_arch = "arm", target_arch = "aarch64"))
))]
let sampler = crate::sampler::DummySampler::new();
diff --git a/components/bluetooth/Cargo.toml b/components/bluetooth/Cargo.toml
index 4046b256a1b..536a29e583f 100644
--- a/components/bluetooth/Cargo.toml
+++ b/components/bluetooth/Cargo.toml
@@ -22,6 +22,7 @@ servo_rand = { path = "../rand" }
uuid = { workspace = true }
[features]
+default = ["bluetooth-test"]
native-bluetooth = ["blurz", "blurdroid", "blurmac", "bluetooth-test"]
bluetooth-test = ["blurmock"]
diff --git a/components/compositing/compositor.rs b/components/compositing/compositor.rs
index d0af82067fc..5ef8ffc20a6 100644
--- a/components/compositing/compositor.rs
+++ b/components/compositing/compositor.rs
@@ -501,6 +501,33 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
self.shutdown_state = ShutdownState::FinishedShuttingDown;
}
+ /// The underlying native surface can be lost during servo's lifetime.
+ /// On Android, for example, this happens when the app is sent to background.
+ /// We need to unbind the surface so that we don't try to use it again.
+ pub fn invalidate_native_surface(&mut self) {
+ debug!("Invalidating native surface in compositor");
+ if let Err(e) = self.webrender_surfman.unbind_native_surface_from_context() {
+ warn!("Unbinding native surface from context failed ({:?})", e);
+ }
+ }
+
+ /// On Android, this function will be called when the app moves to foreground
+ /// and the system creates a new native surface that needs to bound to the current
+ /// context.
+ #[allow(unsafe_code)]
+ pub fn replace_native_surface(&mut self, native_widget: *mut c_void, coords: DeviceIntSize) {
+ debug!("Replacing native surface in compositor: {native_widget:?}");
+ let connection = self.webrender_surfman.connection();
+ let native_widget =
+ unsafe { connection.create_native_widget_from_ptr(native_widget, coords.to_untyped()) };
+ if let Err(e) = self
+ .webrender_surfman
+ .bind_native_surface_to_context(native_widget)
+ {
+ warn!("Binding native surface to context failed ({:?})", e);
+ }
+ }
+
fn handle_browser_message(&mut self, msg: CompositorMsg) -> bool {
match (msg, self.shutdown_state) {
(_, ShutdownState::FinishedShuttingDown) => {
diff --git a/components/compositing/windowing.rs b/components/compositing/windowing.rs
index 3aebe8d874c..c78ddb6ba85 100644
--- a/components/compositing/windowing.rs
+++ b/components/compositing/windowing.rs
@@ -10,6 +10,7 @@ use std::time::Duration;
use embedder_traits::{EmbedderProxy, EventLoopWaker};
use euclid::Scale;
use keyboard_types::KeyboardEvent;
+use libc::c_void;
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId, TraversalDirection};
use script_traits::{MediaSessionActionType, MouseButton, TouchEventType, TouchId, WheelDelta};
use servo_geometry::DeviceIndependentPixel;
@@ -105,6 +106,14 @@ pub enum EmbedderEvent {
ChangeBrowserVisibility(TopLevelBrowsingContextId, bool),
/// Virtual keyboard was dismissed
IMEDismissed,
+ /// Sent on platforms like Android where the native widget surface can be
+ /// automatically destroyed by the system, for example when the app
+ /// is sent to background.
+ InvalidateNativeSurface,
+ /// Sent on platforms like Android where system recreates a new surface for
+ /// the native widget when it is brough back to foreground. This event
+ /// carries the pointer to the native widget and its new size.
+ ReplaceNativeSurface(*mut c_void, DeviceIntSize),
}
impl Debug for EmbedderEvent {
@@ -139,6 +148,8 @@ impl Debug for EmbedderEvent {
EmbedderEvent::ChangeBrowserVisibility(..) => write!(f, "ChangeBrowserVisibility"),
EmbedderEvent::IMEDismissed => write!(f, "IMEDismissed"),
EmbedderEvent::ClearCache => write!(f, "ClearCache"),
+ EmbedderEvent::InvalidateNativeSurface => write!(f, "InvalidateNativeSurface"),
+ EmbedderEvent::ReplaceNativeSurface(..) => write!(f, "ReplaceNativeSurface"),
}
}
}
diff --git a/components/gfx/platform/freetype/android/font_list.rs b/components/gfx/platform/freetype/android/font_list.rs
index 8c4b2e38a17..44c6640468c 100644
--- a/components/gfx/platform/freetype/android/font_list.rs
+++ b/components/gfx/platform/freetype/android/font_list.rs
@@ -4,12 +4,13 @@
use std::path::Path;
+use log::warn;
use ucd::{Codepoint, UnicodeBlock};
use super::xml::{Attribute, Node};
use crate::text::util::is_cjk;
-lazy_static! {
+lazy_static::lazy_static! {
static ref FONT_LIST: FontList = FontList::new();
}
diff --git a/components/profile/Cargo.toml b/components/profile/Cargo.toml
index 173fdbcbc2b..da55faa6a00 100644
--- a/components/profile/Cargo.toml
+++ b/components/profile/Cargo.toml
@@ -23,6 +23,6 @@ task_info = { path = "../../support/rust-task_info" }
[target.'cfg(target_os = "linux")'.dependencies]
regex = { workspace = true }
-[target.'cfg(not(target_os = "windows"))'.dependencies]
+[target.'cfg(not(any(target_os = "windows", target_os = "android")))'.dependencies]
libc = { workspace = true }
jemalloc-sys = { workspace = true }
diff --git a/components/profile/mem.rs b/components/profile/mem.rs
index 11542045f67..53990d7f05f 100644
--- a/components/profile/mem.rs
+++ b/components/profile/mem.rs
@@ -387,16 +387,16 @@ impl ReportsForest {
//---------------------------------------------------------------------------
mod system_reporter {
- #[cfg(not(target_os = "windows"))]
+ #[cfg(not(any(target_os = "windows", target_os = "android")))]
use std::ffi::CString;
- #[cfg(not(target_os = "windows"))]
+ #[cfg(not(any(target_os = "windows", target_os = "android")))]
use std::mem::size_of;
- #[cfg(not(target_os = "windows"))]
+ #[cfg(not(any(target_os = "windows", target_os = "android")))]
use std::ptr::null_mut;
#[cfg(target_os = "linux")]
use libc::c_int;
- #[cfg(not(target_os = "windows"))]
+ #[cfg(not(any(target_os = "windows", target_os = "android")))]
use libc::{c_void, size_t};
use profile_traits::mem::{Report, ReportKind, ReporterRequest};
use profile_traits::path;
@@ -499,10 +499,10 @@ mod system_reporter {
None
}
- #[cfg(not(target_os = "windows"))]
+ #[cfg(not(any(target_os = "windows", target_os = "android")))]
use jemalloc_sys::mallctl;
- #[cfg(not(target_os = "windows"))]
+ #[cfg(not(any(target_os = "windows", target_os = "android")))]
fn jemalloc_stat(value_name: &str) -> Option<usize> {
// Before we request the measurement of interest, we first send an "epoch"
// request. Without that jemalloc gives cached statistics(!) which can be
@@ -549,7 +549,7 @@ mod system_reporter {
Some(value as usize)
}
- #[cfg(target_os = "windows")]
+ #[cfg(any(target_os = "windows", target_os = "android"))]
fn jemalloc_stat(_value_name: &str) -> Option<usize> {
None
}
diff --git a/components/servo/lib.rs b/components/servo/lib.rs
index 424f3fc647e..662a958460c 100644
--- a/components/servo/lib.rs
+++ b/components/servo/lib.rs
@@ -503,7 +503,14 @@ where
EmbedderEvent::Resize => {
return self.compositor.on_resize_window_event();
},
-
+ EmbedderEvent::InvalidateNativeSurface => {
+ self.compositor.invalidate_native_surface();
+ },
+ EmbedderEvent::ReplaceNativeSurface(native_widget, coords) => {
+ self.compositor
+ .replace_native_surface(native_widget, coords);
+ self.compositor.composite();
+ },
EmbedderEvent::AllowNavigationResponse(pipeline_id, allowed) => {
let msg = ConstellationMsg::AllowNavigationResponse(pipeline_id, allowed);
if let Err(e) = self.constellation_chan.send(msg) {
@@ -1091,6 +1098,9 @@ fn default_user_agent_string_for(agent: UserAgent) -> &'static str {
const DESKTOP_UA_STRING: &'static str =
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:109.0) Servo/1.0 Firefox/111.0";
+ #[cfg(target_os = "android")]
+ const DESKTOP_UA_STRING: &'static str = "";
+
match agent {
UserAgent::Desktop => DESKTOP_UA_STRING,
UserAgent::Android => "Mozilla/5.0 (Android; Mobile; rv:109.0) Servo/1.0 Firefox/111.0",
diff --git a/components/webrender_surfman/lib.rs b/components/webrender_surfman/lib.rs
index 4d2d4346d2c..8e4dc75cb79 100644
--- a/components/webrender_surfman/lib.rs
+++ b/components/webrender_surfman/lib.rs
@@ -216,4 +216,28 @@ impl WebrenderSurfman {
let ref context = self.0.context.borrow();
device.get_proc_address(context, name)
}
+
+ pub fn unbind_native_surface_from_context(&self) -> Result<(), Error> {
+ let device = self.0.device.borrow_mut();
+ let mut context = self.0.context.borrow_mut();
+ let mut surface = device.unbind_surface_from_context(&mut context)?.unwrap();
+ let _ = device.destroy_surface(&mut context, &mut surface)?;
+ Ok(())
+ }
+
+ pub fn bind_native_surface_to_context(&self, native_widget: NativeWidget) -> Result<(), Error> {
+ let mut device = self.0.device.borrow_mut();
+ let mut context = self.0.context.borrow_mut();
+ let surface_access = SurfaceAccess::GPUOnly;
+ let surface_type = SurfaceType::Widget { native_widget };
+ let surface = device.create_surface(&context, surface_access, surface_type)?;
+ device
+ .bind_surface_to_context(&mut context, surface)
+ .map_err(|(err, mut surface)| {
+ let _ = device.destroy_surface(&mut context, &mut surface);
+ err
+ })?;
+ device.make_context_current(&context)?;
+ Ok(())
+ }
}
diff --git a/etc/run_in_headless_android_emulator.py b/etc/run_in_headless_android_emulator.py
index a3b5d573ef9..758af9b5a5d 100755
--- a/etc/run_in_headless_android_emulator.py
+++ b/etc/run_in_headless_android_emulator.py
@@ -79,8 +79,8 @@ def main(avd_name, apk_path, *args):
def tool_path(directory, bin_name):
- if "ANDROID_SDK" in os.environ:
- path = os.path.join(os.environ["ANDROID_SDK"], directory, bin_name)
+ if "ANDROID_SDK_ROOT" in os.environ:
+ path = os.path.join(os.environ["ANDROID_SDK_ROOT"], directory, bin_name)
if os.path.exists(path):
return path
diff --git a/etc/shell.nix b/etc/shell.nix
index 39c8ff2eea9..3c55c1ab491 100644
--- a/etc/shell.nix
+++ b/etc/shell.nix
@@ -10,6 +10,10 @@ with import (builtins.fetchTarball {
url = "https://github.com/oxalica/rust-overlay/archive/a0df72e106322b67e9c6e591fe870380bd0da0d5.tar.gz";
}))
];
+ config = {
+ android_sdk.accept_license = true;
+ allowUnfree = true;
+ };
};
let
rustToolchain = rust-bin.fromRustupToolchainFile ../rust-toolchain.toml;
@@ -27,6 +31,25 @@ let
# - glibc 2.38 (#31054)
llvmPackages = llvmPackages_14;
stdenv = llvmPackages.stdenv;
+
+ buildToolsVersion = "33.0.2";
+ androidComposition = androidenv.composeAndroidPackages {
+ buildToolsVersions = [ buildToolsVersion ];
+ includeEmulator = true;
+ platformVersions = [ "33" ];
+ includeSources = false;
+ includeSystemImages = true;
+ systemImageTypes = [ "google_apis" ];
+ abiVersions = [ "x86" "armeabi-v7a" ];
+ includeNDK = true;
+ ndkVersion = "25.2.9519653";
+ useGoogleAPIs = false;
+ useGoogleTVAddOns = false;
+ includeExtras = [
+ "extras;google;gcm"
+ ];
+ };
+ androidSdk = androidComposition.androidsdk;
in
stdenv.mkDerivation rec {
name = "servo-env";
@@ -111,22 +134,33 @@ stdenv.mkDerivation rec {
RUSTC_BOOTSTRAP = "crown";
}))
+
+ # for android builds
+ # TODO: make this optional
+ openjdk17_headless
+ androidSdk
] ++ (lib.optionals stdenv.isDarwin [
darwin.apple_sdk.frameworks.AppKit
]);
LIBCLANG_PATH = llvmPackages.clang-unwrapped.lib + "/lib/";
+ # Required by ./mach build --android
+ ANDROID_SDK_ROOT = "${androidSdk}/libexec/android-sdk";
+ ANDROID_NDK_ROOT = "${ANDROID_SDK_ROOT}/ndk-bundle";
+ GRADLE_OPTS = "-Dorg.gradle.project.android.aapt2FromMavenOverride=${ANDROID_SDK_ROOT}/build-tools/${buildToolsVersion}/aapt2";
+
# Allow cargo to download crates
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
# Enable colored cargo and rustc output
TERMINFO = "${ncurses.out}/share/terminfo";
+
# Provide libraries that aren’t linked against but somehow required
LD_LIBRARY_PATH = lib.makeLibraryPath [
# Fixes missing library errors
- xorg.libXcursor xorg.libXrandr xorg.libXi libxkbcommon
+ zlib xorg.libXcursor xorg.libXrandr xorg.libXi libxkbcommon
# [WARN script::dom::gpu] Could not get GPUAdapter ("NotFound")
# TLA Err: Error: Couldn't request WebGPU adapter.
diff --git a/ports/libsimpleservo/api/src/lib.rs b/ports/libsimpleservo/api/src/lib.rs
index cd9abc9b511..5a3d1e4cd74 100644
--- a/ports/libsimpleservo/api/src/lib.rs
+++ b/ports/libsimpleservo/api/src/lib.rs
@@ -18,6 +18,7 @@ use servo::compositing::windowing::{
AnimationState, EmbedderCoordinates, EmbedderEvent, EmbedderMethods, MouseWindowEvent,
WindowMethods,
};
+use servo::compositing::CompositeTarget;
use servo::config::prefs::pref_map;
pub use servo::config::prefs::{add_user_prefs, PrefValue};
use servo::embedder_traits::resources::{self, Resource, ResourceReaderMethods};
@@ -298,7 +299,12 @@ pub fn init(
gl: gl.clone(),
});
- let servo = Servo::new(embedder_callbacks, window_callbacks.clone(), None);
+ let servo = Servo::new(
+ embedder_callbacks,
+ window_callbacks.clone(),
+ None,
+ CompositeTarget::Window,
+ );
SERVO.with(|s| {
let mut servo_glue = ServoGlue {
@@ -569,6 +575,24 @@ impl ServoGlue {
self.process_event(EmbedderEvent::Keyboard(key_event))
}
+ pub fn pause_compositor(&mut self) -> Result<(), &'static str> {
+ self.process_event(EmbedderEvent::InvalidateNativeSurface)
+ }
+
+ pub fn resume_compositor(
+ &mut self,
+ native_surface: *mut c_void,
+ coords: Coordinates,
+ ) -> Result<(), &'static str> {
+ if native_surface.is_null() {
+ panic!("null passed for native_surface");
+ }
+ self.process_event(EmbedderEvent::ReplaceNativeSurface(
+ native_surface,
+ coords.framebuffer,
+ ))
+ }
+
pub fn media_session_action(
&mut self,
action: MediaSessionActionType,
@@ -789,6 +813,9 @@ impl ServoGlue {
EmbedderMsg::Panic(reason, backtrace) => {
self.callbacks.host_callbacks.on_panic(reason, backtrace);
},
+ EmbedderMsg::ReadyToPresent => {
+ self.servo.present();
+ },
EmbedderMsg::Status(..) |
EmbedderMsg::SelectFiles(..) |
EmbedderMsg::MoveTo(..) |
@@ -798,7 +825,6 @@ impl ServoGlue {
EmbedderMsg::NewFavicon(..) |
EmbedderMsg::HeadParsed |
EmbedderMsg::SetFullscreenState(..) |
- EmbedderMsg::ReadyToPresent |
EmbedderMsg::ReportProfile(..) |
EmbedderMsg::EventDelivered(..) => {},
}
diff --git a/ports/libsimpleservo/jniapi/Cargo.toml b/ports/libsimpleservo/jniapi/Cargo.toml
index 020767c41be..b74591ff7bf 100644
--- a/ports/libsimpleservo/jniapi/Cargo.toml
+++ b/ports/libsimpleservo/jniapi/Cargo.toml
@@ -1,7 +1,6 @@
[package]
name = "simpleservo_jniapi"
version = "0.0.1"
-build = "build.rs"
authors = ["The Servo Project Developers"]
license = "MPL-2.0"
edition = "2018"
@@ -14,21 +13,21 @@ test = false
bench = false
[dependencies]
-android_injected_glue = "0.2"
-android_logger = "0.10"
-gstreamer = { workspace = true }
+android_logger = "0.13"
jni = "0.18.0"
libc = { workspace = true }
log = { workspace = true }
serde_json = { workspace = true }
-simpleservo = { path = "../api" }
+# TODO: Once the native-bluetooth feature works for
+# Android, remove the explicit feature list here.
+simpleservo = { path = "../api", default-features = false, features = ["max_log_level", "webdriver"] }
[build-dependencies]
cc = "1.0"
[features]
debugmozjs = ["simpleservo/debugmozjs"]
-default = ["max_log_level", "native-bluetooth", "webdriver"]
+default = ["max_log_level", "webdriver", "no_static_freetype"]
googlevr = ["simpleservo/googlevr"]
js_backtrace = ["simpleservo/js_backtrace"]
max_log_level = ["simpleservo/max_log_level"]
@@ -36,3 +35,4 @@ media-gstreamer = ["simpleservo/media-gstreamer"]
native-bluetooth = ["simpleservo/native-bluetooth"]
webdriver = ["simpleservo/webdriver"]
webgl_backtrace = ["simpleservo/webgl_backtrace"]
+no_static_freetype = ["simpleservo/no_static_freetype"]
diff --git a/ports/libsimpleservo/jniapi/build.rs b/ports/libsimpleservo/jniapi/build.rs
deleted file mode 100644
index e97cb310111..00000000000
--- a/ports/libsimpleservo/jniapi/build.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-use std::env;
-use std::path::Path;
-
-fn main() {
- // Get the NDK path from NDK_HOME env.
- let ndk_path =
- env::var_os("ANDROID_NDK").expect("Please set the ANDROID_NDK environment variable");
- let ndk_path = Path::new(&ndk_path);
-
- // compiling android_native_app_glue.c
- let c_file = ndk_path
- .join("sources")
- .join("android")
- .join("native_app_glue")
- .join("android_native_app_glue.c");
- cc::Build::new()
- .file(c_file)
- .warnings(false)
- .compile("android_native_app_glue");
-
- // Get the output directory.
- let out_dir =
- env::var("OUT_DIR").expect("Cargo should have set the OUT_DIR environment variable");
-
- println!("cargo:rustc-link-lib=static=android_native_app_glue");
- println!("cargo:rustc-link-search=native={}", out_dir);
- println!("cargo:rustc-link-lib=log");
- println!("cargo:rustc-link-lib=android");
-}
diff --git a/ports/libsimpleservo/jniapi/src/lib.rs b/ports/libsimpleservo/jniapi/src/lib.rs
index 53dc59047eb..0293a8332e4 100644
--- a/ports/libsimpleservo/jniapi/src/lib.rs
+++ b/ports/libsimpleservo/jniapi/src/lib.rs
@@ -5,21 +5,18 @@
#![allow(non_snake_case)]
use std::os::raw::{c_char, c_int, c_void};
-use std::ptr::{null, null_mut};
use std::sync::Arc;
use std::thread;
-use android_logger::{self, Filter};
-use gstreamer::debug_set_threshold_from_string;
+use android_logger::{self, Config, FilterBuilder};
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE};
-use jni::{errors, JNIEnv, JavaVM};
+use jni::{JNIEnv, JavaVM};
use libc::{dup2, pipe, read};
-use log::Level;
+use log::{debug, error, info, warn};
use simpleservo::{
- self, self, deinit, gl_glue, gl_glue, Coordinates, DeviceIntRect, EventLoopWaker, HostTrait,
- InitOptions, InputMethodType, MediaSessionPlaybackState, MouseButton, PromptResult, ServoGlue,
- ServoGlue, VRInitOptions, SERVO, SERVO,
+ self, gl_glue, Coordinates, DeviceIntRect, EventLoopWaker, HostTrait, InitOptions,
+ InputMethodType, MediaSessionPlaybackState, PromptResult, ServoGlue, SERVO,
};
struct HostCallbacks {
@@ -27,6 +24,19 @@ struct HostCallbacks {
jvm: JavaVM,
}
+extern "C" {
+ fn ANativeWindow_fromSurface(env: *mut jni::sys::JNIEnv, surface: JObject) -> *mut c_void;
+}
+
+#[no_mangle]
+pub fn android_main() {
+ // FIXME(mukilan): this android_main is only present to stop
+ // the java side 'System.loadLibrary('simpleservo') call from
+ // failing due to undefined reference to android_main introduced
+ // by winit's android-activity crate. There is no way to disable
+ // this currently.
+}
+
fn call<F>(env: &JNIEnv, f: F)
where
F: Fn(&mut ServoGlue) -> Result<(), &str>,
@@ -51,11 +61,12 @@ pub fn Java_org_mozilla_servoview_JNIServo_version(env: JNIEnv, _class: JClass)
pub fn Java_org_mozilla_servoview_JNIServo_init(
env: JNIEnv,
_: JClass,
- activity: JObject,
+ _activity: JObject,
opts: JObject,
callbacks_obj: JObject,
+ surface: JObject,
) {
- let (mut opts, log, log_str, gst_debug_str) = match get_options(&env, opts) {
+ let (mut opts, log, log_str, _gst_debug_str) = match get_options(&env, opts, surface) {
Ok((opts, log, log_str, gst_debug_str)) => (opts, log, log_str, gst_debug_str),
Err(err) => {
throw(&env, &err);
@@ -79,26 +90,26 @@ pub fn Java_org_mozilla_servoview_JNIServo_init(
"compositing::compositor",
"constellation::constellation",
];
- let mut filter = Filter::default().with_min_level(Level::Debug);
+ let mut filter_builder = FilterBuilder::new();
for &module in &filters {
- filter = filter.with_allowed_module_path(module);
+ filter_builder.filter_module(module, log::LevelFilter::Debug);
}
if let Some(log_str) = log_str {
for module in log_str.split(',') {
- filter = filter.with_allowed_module_path(module);
+ filter_builder.filter_module(module, log::LevelFilter::Debug);
}
}
- if let Some(gst_debug_str) = gst_debug_str {
- debug_set_threshold_from_string(&gst_debug_str, true);
- }
-
- android_logger::init_once(filter, Some("simpleservo"));
+ android_logger::init_once(
+ Config::default()
+ .with_max_level(log::LevelFilter::Debug)
+ .with_filter(filter_builder.build())
+ .with_tag("simpleservo"),
+ )
}
info!("init");
- initialize_android_glue(&env, activity);
redirect_stdout_to_logcat();
let callbacks_ref = match env.new_global_ref(callbacks_obj) {
@@ -329,12 +340,34 @@ pub fn Java_org_mozilla_servoview_JNIServo_pinchZoomEnd(
}
#[no_mangle]
-pub fn Java_org_mozilla_servoview_JNIServo_click(env: JNIEnv, _: JClass, x: jint, y: jint) {
+pub fn Java_org_mozilla_servoview_JNIServo_click(env: JNIEnv, _: JClass, x: jfloat, y: jfloat) {
debug!("click");
call(&env, |s| s.click(x as f32, y as f32));
}
#[no_mangle]
+pub fn Java_org_mozilla_servoview_JNIServo_pauseCompositor(env: JNIEnv, _: JClass) {
+ debug!("pauseCompositor");
+ call(&env, |s| s.pause_compositor());
+}
+
+#[no_mangle]
+pub fn Java_org_mozilla_servoview_JNIServo_resumeCompositor(
+ env: JNIEnv,
+ _: JClass,
+ surface: JObject,
+ coordinates: JObject,
+) {
+ debug!("resumeCompositor");
+ let widget = unsafe { ANativeWindow_fromSurface(env.get_native_interface(), surface) };
+ let coords = jni_coords_to_rust_coords(&env, coordinates);
+ match coords {
+ Ok(coords) => call(&env, |s| s.resume_compositor(widget, coords.clone())),
+ Err(error) => throw(&env, &error),
+ }
+}
+
+#[no_mangle]
pub fn Java_org_mozilla_servoview_JNIServo_mediaSessionAction(
env: JNIEnv,
_: JClass,
@@ -379,20 +412,6 @@ impl HostCallbacks {
}
impl HostTrait for HostCallbacks {
- fn flush(&self) {
- debug!("flush");
- let env = self.jvm.get_env().unwrap();
- env.call_method(self.callbacks.as_obj(), "flush", "()V", &[])
- .unwrap();
- }
-
- fn make_current(&self) {
- debug!("make_current");
- let env = self.jvm.get_env().unwrap();
- env.call_method(self.callbacks.as_obj(), "makeCurrent", "()V", &[])
- .unwrap();
- }
-
fn prompt_alert(&self, message: String, _trusted: bool) {
debug!("prompt_alert");
let env = self.jvm.get_env().unwrap();
@@ -446,9 +465,10 @@ impl HostTrait for HostCallbacks {
.unwrap();
}
- fn on_title_changed(&self, title: String) {
+ fn on_title_changed(&self, title: Option<String>) {
debug!("on_title_changed");
let env = self.jvm.get_env().unwrap();
+ let title = title.unwrap_or_else(String::new);
let s = match new_string(&env, &title) {
Ok(s) => s,
Err(_) => return,
@@ -529,7 +549,7 @@ impl HostTrait for HostCallbacks {
fn on_ime_show(
&self,
- _type: InputEncoding,
+ _input_type: InputMethodType,
_text: Option<(String, i32)>,
_multiline: bool,
_rect: DeviceIntRect,
@@ -610,65 +630,16 @@ impl HostTrait for HostCallbacks {
.unwrap();
}
- fn on_devtools_started(&self, port: Result<u16, ()>) {
+ fn on_devtools_started(&self, port: Result<u16, ()>, _token: String) {
match port {
Ok(p) => info!("Devtools Server running on port {}", p),
Err(()) => error!("Error running devtools server"),
}
}
-}
-
-fn initialize_android_glue(env: &JNIEnv, activity: JObject) {
- use android_injected_glue::{ffi, ANDROID_APP};
-
- // From jni-rs to android_injected_glue
- let clazz = Box::leak(Box::new(env.new_global_ref(activity).unwrap()));
+ fn show_context_menu(&self, _title: Option<String>, _items: Vec<String>) {}
- let activity = Box::into_raw(Box::new(ffi::ANativeActivity {
- clazz: clazz.as_obj().into_inner() as *mut c_void,
- vm: env.get_java_vm().unwrap().get_java_vm_pointer() as *mut ffi::_JavaVM,
-
- callbacks: null_mut(),
- env: null_mut(),
- internalDataPath: null(),
- externalDataPath: null(),
- sdkVersion: 0,
- instance: null_mut(),
- assetManager: null_mut(),
- obbPath: null(),
- }));
-
- extern "C" fn on_app_cmd(_: *mut ffi::android_app, _: i32) {}
- extern "C" fn on_input_event(_: *mut ffi::android_app, _: *const c_void) -> i32 {
- 0
- }
-
- let app = Box::into_raw(Box::new(ffi::android_app {
- activity,
- onAppCmd: on_app_cmd,
- onInputEvent: on_input_event,
-
- userData: null_mut(),
- config: null(),
- savedState: null_mut(),
- savedStateSize: 0,
- looper: null_mut(),
- inputQueue: null(),
- window: null_mut(),
- contentRect: ffi::ARect {
- left: 0,
- top: 0,
- right: 0,
- bottom: 0,
- },
- activityState: 0,
- destroyRequested: 0,
- }));
-
- unsafe {
- ANDROID_APP = app;
- }
+ fn on_panic(&self, _reason: String, _backtrace: Option<String>) {}
}
extern "C" {
@@ -803,28 +774,21 @@ fn jni_coords_to_rust_coords(env: &JNIEnv, obj: JObject) -> Result<Coordinates,
fn get_field<'a>(
env: &'a JNIEnv,
- obj: JObject,
+ obj: JObject<'a>,
field: &str,
type_: &str,
) -> Result<Option<JValue<'a>>, String> {
if env.get_field_id(obj, field, type_).is_err() {
- return Err(format!("Can't find `{}` field", &field));
+ return Err(format!("Can't find `{}` field", field));
}
env.get_field(obj, field, type_)
.map(|value| Some(value))
- .or_else(|e| match *e.kind() {
- errors::ErrorKind::NullPtr(_) => Ok(None),
- _ => Err(format!(
- "Can't find `{}` field: {}",
- &field,
- e.description()
- )),
- })
+ .or_else(|_| Err(format!("Can't find `{}` field", field)))
}
fn get_non_null_field<'a>(
env: &'a JNIEnv,
- obj: JObject,
+ obj: JObject<'a>,
field: &str,
type_: &str,
) -> Result<JValue<'a>, String> {
@@ -851,6 +815,7 @@ fn get_string(env: &JNIEnv, obj: JObject, field: &str) -> Result<Option<String>,
fn get_options(
env: &JNIEnv,
opts: JObject,
+ surface: JObject,
) -> Result<(InitOptions, bool, Option<String>, Option<String>), String> {
let args = get_string(env, opts, "args")?;
let url = get_string(env, opts, "url")?;
@@ -862,13 +827,6 @@ fn get_options(
let log = get_non_null_field(env, opts, "enableLogs", "Z")?
.z()
.map_err(|_| "enableLogs not a boolean")?;
- let enable_subpixel_text_antialiasing =
- get_non_null_field(env, opts, "enableSubpixelTextAntialiasing", "Z")?
- .z()
- .map_err(|_| "enableSubpixelTextAntialiasing not a boolean")?;
- let vr_pointer = get_non_null_field(env, opts, "VRExternalContext", "J")?
- .j()
- .map_err(|_| "VRExternalContext is not a long")? as *mut c_void;
let coordinates = get_non_null_field(
env,
opts,
@@ -885,20 +843,16 @@ fn get_options(
None => None,
};
+ let native_window = unsafe { ANativeWindow_fromSurface(env.get_native_interface(), surface) };
let opts = InitOptions {
args: args.unwrap_or(vec![]),
- url,
coordinates,
density,
- enable_subpixel_text_antialiasing,
- vr_init: if vr_pointer.is_null() {
- VRInitOptions::None
- } else {
- VRInitOptions::VRExternal(vr_pointer)
- },
xr_discovery: None,
gl_context_pointer: None,
native_display_pointer: None,
+ surfman_integration: simpleservo::SurfmanIntegration::Widget(native_window),
+ prefs: None,
};
Ok((opts, log, log_str, gst_debug_str))
}
diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py
index 1c7afc957d8..33d3b20aa2f 100644
--- a/python/servo/bootstrap_commands.py
+++ b/python/servo/bootstrap_commands.py
@@ -12,7 +12,6 @@ import glob
import json
import os
import os.path as path
-import platform
import re
import subprocess
import sys
@@ -30,7 +29,7 @@ from mach.decorators import (
import servo.platform
from servo.command_base import CommandBase, cd, check_call
-from servo.util import delete, download_bytes, download_file, extract, check_hash
+from servo.util import delete, download_bytes
@CommandProvider
@@ -66,150 +65,6 @@ class MachCommands(CommandBase):
return 1
return 0
- @Command('bootstrap-android',
- description='Install the Android SDK and NDK.',
- category='bootstrap')
- @CommandArgument('--build',
- action='store_true',
- help='Install Android-specific dependencies for building')
- @CommandArgument('--emulator-x86',
- action='store_true',
- help='Install Android x86 emulator and system image')
- @CommandArgument('--accept-all-licences',
- action='store_true',
- help='For non-interactive use')
- def bootstrap_android(self, build=False, emulator_x86=False, accept_all_licences=False):
- if not (build or emulator_x86):
- print("Must specify `--build` or `--emulator-x86` or both.")
-
- ndk = "android-ndk-r15c-{system}-{arch}"
- tools = "sdk-tools-{system}-4333796"
-
- emulator_platform = "android-28"
- emulator_image = "system-images;%s;google_apis;x86" % emulator_platform
-
- known_sha1 = {
- # https://dl.google.com/android/repository/repository2-1.xml
- "sdk-tools-darwin-4333796.zip": "ed85ea7b59bc3483ce0af4c198523ba044e083ad",
- "sdk-tools-linux-4333796.zip": "8c7c28554a32318461802c1291d76fccfafde054",
- "sdk-tools-windows-4333796.zip": "aa298b5346ee0d63940d13609fe6bec621384510",
-
- # https://developer.android.com/ndk/downloads/older_releases
- "android-ndk-r15c-windows-x86.zip": "f2e47121feb73ec34ced5e947cbf1adc6b56246e",
- "android-ndk-r15c-windows-x86_64.zip": "970bb2496de0eada74674bb1b06d79165f725696",
- "android-ndk-r15c-darwin-x86_64.zip": "ea4b5d76475db84745aa8828000d009625fc1f98",
- "android-ndk-r15c-linux-x86_64.zip": "0bf02d4e8b85fd770fd7b9b2cdec57f9441f27a2",
- }
-
- toolchains = path.join(self.context.topdir, "android-toolchains")
- if not path.isdir(toolchains):
- os.makedirs(toolchains)
-
- def download(target_dir, name, flatten=False):
- final = path.join(toolchains, target_dir)
- if path.isdir(final):
- return
-
- base_url = "https://dl.google.com/android/repository/"
- filename = name + ".zip"
- url = base_url + filename
- archive = path.join(toolchains, filename)
-
- if not path.isfile(archive):
- download_file(filename, url, archive)
- check_hash(archive, known_sha1[filename], "sha1")
- print("Extracting " + filename)
- remove = True # Set to False to avoid repeated downloads while debugging this script
- if flatten:
- extracted = final + "_"
- extract(archive, extracted, remove=remove)
- contents = os.listdir(extracted)
- assert len(contents) == 1
- os.rename(path.join(extracted, contents[0]), final)
- os.rmdir(extracted)
- else:
- extract(archive, final, remove=remove)
-
- system = platform.system().lower()
- machine = platform.machine().lower()
- arch = {"i386": "x86"}.get(machine, machine)
- if build:
- download("ndk", ndk.format(system=system, arch=arch), flatten=True)
- download("sdk", tools.format(system=system))
-
- components = []
- if emulator_x86:
- components += [
- "platform-tools",
- "emulator",
- "platforms;" + emulator_platform,
- emulator_image,
- ]
- if build:
- components += [
- "platform-tools",
- "platforms;android-18",
- ]
-
- sdkmanager = [path.join(toolchains, "sdk", "tools", "bin", "sdkmanager")] + components
- if accept_all_licences:
- yes = subprocess.Popen(["yes"], stdout=subprocess.PIPE)
- process = subprocess.Popen(
- sdkmanager, stdin=yes.stdout, stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
- )
- # Reduce progress bar spam by removing duplicate lines.
- # Printing the same line again with \r is a no-op in a real terminal,
- # but each line is shown individually in Taskcluster's log viewer.
- previous_line = None
- line = b""
- while 1:
- # Read one byte at a time because in Python:
- # * readline() blocks until "\n", which doesn't come before the prompt
- # * read() blocks until EOF, which doesn't come before the prompt
- # * read(n) keeps reading until it gets n bytes or EOF,
- # but we don't know reliably how many bytes to read until the prompt
- byte = process.stdout.read(1)
- if len(byte) == 0:
- print(line)
- break
- line += byte
- if byte == b'\n' or byte == b'\r':
- if line != previous_line:
- print(line.decode("utf-8", "replace"), end="")
- sys.stdout.flush()
- previous_line = line
- line = b""
- exit_code = process.wait()
- yes.terminate()
- if exit_code:
- return exit_code
- else:
- subprocess.check_call(sdkmanager)
-
- if emulator_x86:
- avd_path = path.join(toolchains, "avd", "servo-x86")
- process = subprocess.Popen(stdin=subprocess.PIPE, stdout=subprocess.PIPE, args=[
- path.join(toolchains, "sdk", "tools", "bin", "avdmanager"),
- "create", "avd",
- "--path", avd_path,
- "--name", "servo-x86",
- "--package", emulator_image,
- "--force",
- ])
- output = b""
- while 1:
- # Read one byte at a time, see comment above.
- byte = process.stdout.read(1)
- if len(byte) == 0:
- break
- output += byte
- # There seems to be no way to disable this prompt:
- if output.endswith(b"Do you wish to create a custom hardware profile? [no]"):
- process.stdin.write("no\n")
- assert process.wait() == 0
- with open(path.join(avd_path, "config.ini"), "a") as f:
- f.write("disk.dataPartition.size=2G\n")
-
@Command('update-hsts-preload',
description='Download the HSTS preload list',
category='bootstrap')
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index f61c82fe5b3..dd63aff54f3 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -98,7 +98,6 @@ class MachCommands(CommandBase):
for key in env:
print((key, env[key]))
- self.download_and_build_android_dependencies_if_needed(env)
status = self.run_cargo_build_like_command(
"build", opts, env=env, verbose=verbose,
libsimpleservo=libsimpleservo, **kwargs
diff --git a/python/servo/command_base.py b/python/servo/command_base.py
index f6d105e7837..833f0bac417 100644
--- a/python/servo/command_base.py
+++ b/python/servo/command_base.py
@@ -334,7 +334,7 @@ class CommandBase(object):
def get_binary_path(self, build_type: BuildType, target=None, android=False, simpleservo=False):
base_path = util.get_target_dir()
if android:
- base_path = path.join(base_path, "android", self.config["android"]["target"])
+ base_path = path.join(base_path, self.config["android"]["target"])
simpleservo = True
elif target:
base_path = path.join(base_path, target)
@@ -529,58 +529,38 @@ class CommandBase(object):
# Paths to Android build tools:
if self.config["android"]["sdk"]:
- env["ANDROID_SDK"] = self.config["android"]["sdk"]
+ env["ANDROID_SDK_ROOT"] = self.config["android"]["sdk"]
if self.config["android"]["ndk"]:
- env["ANDROID_NDK"] = self.config["android"]["ndk"]
- if self.config["android"]["toolchain"]:
- env["ANDROID_TOOLCHAIN"] = self.config["android"]["toolchain"]
- if self.config["android"]["platform"]:
- env["ANDROID_PLATFORM"] = self.config["android"]["platform"]
-
- # These are set because they are the variable names that build-apk
- # expects. However, other submodules have makefiles that reference
- # the env var names above. Once winit is enabled and set as the
- # default, we could modify the subproject makefiles to use the names
- # below and remove the vars above, to avoid duplication.
- if "ANDROID_SDK" in env:
- env["ANDROID_HOME"] = env["ANDROID_SDK"]
- if "ANDROID_NDK" in env:
- env["NDK_HOME"] = env["ANDROID_NDK"]
- if "ANDROID_TOOLCHAIN" in env:
- env["NDK_STANDALONE"] = env["ANDROID_TOOLCHAIN"]
+ env["ANDROID_NDK_ROOT"] = self.config["android"]["ndk"]
toolchains = path.join(self.context.topdir, "android-toolchains")
for kind in ["sdk", "ndk"]:
default = os.path.join(toolchains, kind)
if os.path.isdir(default):
- env.setdefault("ANDROID_" + kind.upper(), default)
+ env.setdefault(f"ANDROID_{kind.upper()}_ROOT", default)
- tools = os.path.join(toolchains, "sdk", "platform-tools")
- if os.path.isdir(tools):
- env["PATH"] = "%s%s%s" % (tools, os.pathsep, env["PATH"])
-
- if "ANDROID_NDK" not in env:
- print("Please set the ANDROID_NDK environment variable.")
+ if "ANDROID_NDK_ROOT" not in env:
+ print("Please set the ANDROID_NDK_ROOT environment variable.")
sys.exit(1)
- if "ANDROID_SDK" not in env:
- print("Please set the ANDROID_SDK environment variable.")
+ if "ANDROID_SDK_ROOT" not in env:
+ print("Please set the ANDROID_SDK_ROOT environment variable.")
sys.exit(1)
android_platform = self.config["android"]["platform"]
android_toolchain_name = self.config["android"]["toolchain_name"]
- android_toolchain_prefix = self.config["android"]["toolchain_prefix"]
android_lib = self.config["android"]["lib"]
- android_arch = self.config["android"]["arch"]
- # Check if the NDK version is 15
- if not os.path.isfile(path.join(env["ANDROID_NDK"], 'source.properties')):
+ android_api = android_platform.replace('android-', '')
+
+ # Check if the NDK version is 25
+ if not os.path.isfile(path.join(env["ANDROID_NDK_ROOT"], 'source.properties')):
print("ANDROID_NDK should have file `source.properties`.")
- print("The environment variable ANDROID_NDK may be set at a wrong path.")
+ print("The environment variable ANDROID_NDK_ROOT may be set at a wrong path.")
sys.exit(1)
- with open(path.join(env["ANDROID_NDK"], 'source.properties'), encoding="utf8") as ndk_properties:
+ with open(path.join(env["ANDROID_NDK_ROOT"], 'source.properties'), encoding="utf8") as ndk_properties:
lines = ndk_properties.readlines()
- if lines[1].split(' = ')[1].split('.')[0] != '15':
- print("Currently only support NDK 15. Please re-run `./mach bootstrap-android`.")
+ if lines[1].split(' = ')[1].split('.')[0] != '25':
+ print("Servo currently only supports NDK r25c.")
sys.exit(1)
# Android builds also require having the gcc bits on the PATH and various INCLUDE
@@ -598,48 +578,33 @@ class CommandBase(object):
host_suffix = "x86_64"
host = os_type + "-" + host_suffix
- host_cc = env.get('HOST_CC') or shutil.which(["clang"]) or util.whichget_exec_path(["gcc"])
- host_cxx = env.get('HOST_CXX') or util.whichget_exec_path(["clang++"]) or util.whichget_exec_path(["g++"])
-
- llvm_toolchain = path.join(env['ANDROID_NDK'], "toolchains", "llvm", "prebuilt", host)
- gcc_toolchain = path.join(env['ANDROID_NDK'], "toolchains",
- android_toolchain_prefix + "-4.9", "prebuilt", host)
- gcc_libs = path.join(gcc_toolchain, "lib", "gcc", android_toolchain_name, "4.9.x")
+ host_cc = env.get('HOST_CC') or shutil.which("clang")
+ host_cxx = env.get('HOST_CXX') or shutil.which("clang++")
+ llvm_toolchain = path.join(env['ANDROID_NDK_ROOT'], "toolchains", "llvm", "prebuilt", host)
env['PATH'] = (path.join(llvm_toolchain, "bin") + ':' + env['PATH'])
- env['ANDROID_SYSROOT'] = path.join(env['ANDROID_NDK'], "sysroot")
- support_include = path.join(env['ANDROID_NDK'], "sources", "android", "support", "include")
- cpufeatures_include = path.join(env['ANDROID_NDK'], "sources", "android", "cpufeatures")
- cxx_include = path.join(env['ANDROID_NDK'], "sources", "cxx-stl",
- "llvm-libc++", "include")
- clang_include = path.join(llvm_toolchain, "lib64", "clang", "3.8", "include")
- cxxabi_include = path.join(env['ANDROID_NDK'], "sources", "cxx-stl",
- "llvm-libc++abi", "include")
- sysroot_include = path.join(env['ANDROID_SYSROOT'], "usr", "include")
- arch_include = path.join(sysroot_include, android_toolchain_name)
- android_platform_dir = path.join(env['ANDROID_NDK'], "platforms", android_platform, "arch-" + android_arch)
- arch_libs = path.join(android_platform_dir, "usr", "lib")
- clang_include = path.join(llvm_toolchain, "lib64", "clang", "5.0", "include")
- android_api = android_platform.replace('android-', '')
+
+ def to_ndk_bin(prog):
+ return path.join(llvm_toolchain, "bin", prog)
env["RUST_TARGET"] = self.cross_compile_target
env['HOST_CC'] = host_cc
env['HOST_CXX'] = host_cxx
env['HOST_CFLAGS'] = ''
env['HOST_CXXFLAGS'] = ''
- env['CC'] = path.join(llvm_toolchain, "bin", "clang")
- env['CPP'] = path.join(llvm_toolchain, "bin", "clang") + " -E"
- env['CXX'] = path.join(llvm_toolchain, "bin", "clang++")
- env['ANDROID_TOOLCHAIN'] = gcc_toolchain
- env['ANDROID_TOOLCHAIN_DIR'] = gcc_toolchain
- env['ANDROID_VERSION'] = android_api
- env['ANDROID_PLATFORM_DIR'] = android_platform_dir
- env['GCC_TOOLCHAIN'] = gcc_toolchain
- gcc_toolchain_bin = path.join(gcc_toolchain, android_toolchain_name, "bin")
- env['AR'] = path.join(gcc_toolchain_bin, "ar")
- env['RANLIB'] = path.join(gcc_toolchain_bin, "ranlib")
- env['OBJCOPY'] = path.join(gcc_toolchain_bin, "objcopy")
- env['YASM'] = path.join(env['ANDROID_NDK'], 'prebuilt', host, 'bin', 'yasm')
+ env['CC'] = to_ndk_bin("clang")
+ env['CPP'] = to_ndk_bin("clang") + " -E"
+ env['CXX'] = to_ndk_bin("clang++")
+
+ env['AR'] = to_ndk_bin("llvm-ar")
+ env['RANLIB'] = to_ndk_bin("llvm-ranlib")
+ env['OBJCOPY'] = to_ndk_bin("llvm-objcopy")
+ env['YASM'] = to_ndk_bin("yasm")
+ env['STRIP'] = to_ndk_bin("llvm-strip")
+ env['HARFBUZZ_SYS_NO_PKG_CONFIG'] = "true"
+ env['RUST_FONTCONFIG_DLOPEN'] = "on"
+
+ env["LIBCLANG_PATH"] = path.join(llvm_toolchain, "lib64")
# A cheat-sheet for some of the build errors caused by getting the search path wrong...
#
# fatal error: 'limits' file not found
@@ -651,52 +616,28 @@ class CommandBase(object):
#
# Also worth remembering: autoconf uses C for its configuration,
# even for C++ builds, so the C flags need to line up with the C++ flags.
- env['CFLAGS'] = ' '.join([
- "--target=" + self.cross_compile_target,
- "--sysroot=" + env['ANDROID_SYSROOT'],
- "--gcc-toolchain=" + gcc_toolchain,
- "-isystem", sysroot_include,
- "-I" + arch_include,
- "-B" + arch_libs,
- "-L" + arch_libs,
- "-D__ANDROID_API__=" + android_api,
- ])
- env['CXXFLAGS'] = ' '.join([
- "--target=" + self.cross_compile_target,
- "--sysroot=" + env['ANDROID_SYSROOT'],
- "--gcc-toolchain=" + gcc_toolchain,
- "-I" + cpufeatures_include,
- "-I" + cxx_include,
- "-I" + clang_include,
- "-isystem", sysroot_include,
- "-I" + cxxabi_include,
- "-I" + clang_include,
- "-I" + arch_include,
- "-I" + support_include,
- "-L" + gcc_libs,
- "-B" + arch_libs,
- "-L" + arch_libs,
- "-D__ANDROID_API__=" + android_api,
- "-D__STDC_CONSTANT_MACROS",
- "-D__NDK_FPABI__=",
- ])
- env['CPPFLAGS'] = ' '.join([
- "--target=" + self.cross_compile_target,
- "--sysroot=" + env['ANDROID_SYSROOT'],
- "-I" + arch_include,
- ])
- env["NDK_ANDROID_VERSION"] = android_api
+ env['CFLAGS'] = "--target=" + android_toolchain_name
+ env['CXXFLAGS'] = "--target=" + android_toolchain_name
+
+ # These two variables are needed for the mozjs compilation.
+ env['ANDROID_API_LEVEL'] = android_api
+ env["ANDROID_NDK_HOME"] = env["ANDROID_NDK_ROOT"]
+
+ # The two variables set below are passed by our custom
+ # support/android/toolchain.cmake to the NDK's CMake toolchain file
env["ANDROID_ABI"] = android_lib
env["ANDROID_PLATFORM"] = android_platform
- env["NDK_CMAKE_TOOLCHAIN_FILE"] = path.join(env['ANDROID_NDK'], "build", "cmake", "android.toolchain.cmake")
- env["CMAKE_TOOLCHAIN_FILE"] = path.join(self.android_support_dir(), "toolchain.cmake")
+ env["NDK_CMAKE_TOOLCHAIN_FILE"] = path.join(
+ env['ANDROID_NDK_ROOT'], "build", "cmake", "android.toolchain.cmake")
+ env["CMAKE_TOOLCHAIN_FILE"] = path.join(
+ self.context.topdir, "support", "android", "toolchain.cmake")
# Set output dir for gradle aar files
- env["AAR_OUT_DIR"] = self.android_aar_dir()
+ env["AAR_OUT_DIR"] = path.join(self.context.topdir, "target", "android", "aar")
if not os.path.exists(env['AAR_OUT_DIR']):
os.makedirs(env['AAR_OUT_DIR'])
- env['PKG_CONFIG_ALLOW_CROSS'] = "1"
+ env['PKG_CONFIG_SYSROOT_DIR'] = path.join(llvm_toolchain, 'sysroot')
@staticmethod
def common_command_arguments(build_configuration=False, build_type=False):
@@ -863,11 +804,7 @@ class CommandBase(object):
if self.config["build"]["media-stack"] != "auto":
media_stack = self.config["build"]["media-stack"]
assert media_stack
- elif (
- not self.cross_compile_target
- or ("armv7" in self.cross_compile_target and self.is_android_build)
- or "x86_64" in self.cross_compile_target
- ):
+ elif not self.cross_compile_target:
media_stack = "gstreamer"
else:
media_stack = "dummy"
@@ -943,22 +880,16 @@ class CommandBase(object):
return call(["cargo", command] + args + cargo_args, env=env, verbose=verbose)
- def android_support_dir(self):
- return path.join(self.context.topdir, "support", "android")
-
- def android_aar_dir(self):
- return path.join(self.context.topdir, "target", "android", "aar")
-
def android_adb_path(self, env):
- if "ANDROID_SDK" in env:
- sdk_adb = path.join(env["ANDROID_SDK"], "platform-tools", "adb")
+ if "ANDROID_SDK_ROOT" in env:
+ sdk_adb = path.join(env["ANDROID_SDK_ROOT"], "platform-tools", "adb")
if path.exists(sdk_adb):
return sdk_adb
return "adb"
def android_emulator_path(self, env):
- if "ANDROID_SDK" in env:
- sdk_adb = path.join(env["ANDROID_SDK"], "emulator", "emulator")
+ if "ANDROID_SDK_ROOT" in env:
+ sdk_adb = path.join(env["ANDROID_SDK_ROOT"], "emulator", "emulator")
if path.exists(sdk_adb):
return sdk_adb
return "emulator"
@@ -968,29 +899,29 @@ class CommandBase(object):
build by writing the appropriate toolchain configuration values
into the stored configuration."""
if target == "armv7-linux-androideabi":
- self.config["android"]["platform"] = "android-21"
+ self.config["android"]["platform"] = "android-30"
self.config["android"]["target"] = target
self.config["android"]["toolchain_prefix"] = "arm-linux-androideabi"
self.config["android"]["arch"] = "arm"
self.config["android"]["lib"] = "armeabi-v7a"
- self.config["android"]["toolchain_name"] = "arm-linux-androideabi"
+ self.config["android"]["toolchain_name"] = "armv7a-linux-androideabi30"
return True
elif target == "aarch64-linux-android":
- self.config["android"]["platform"] = "android-21"
+ self.config["android"]["platform"] = "android-30"
self.config["android"]["target"] = target
self.config["android"]["toolchain_prefix"] = target
self.config["android"]["arch"] = "arm64"
self.config["android"]["lib"] = "arm64-v8a"
- self.config["android"]["toolchain_name"] = target
+ self.config["android"]["toolchain_name"] = "aarch64-linux-androideabi30"
return True
elif target == "i686-linux-android":
# https://github.com/jemalloc/jemalloc/issues/1279
- self.config["android"]["platform"] = "android-21"
+ self.config["android"]["platform"] = "android-30"
self.config["android"]["target"] = target
- self.config["android"]["toolchain_prefix"] = "x86"
+ self.config["android"]["toolchain_prefix"] = target
self.config["android"]["arch"] = "x86"
self.config["android"]["lib"] = "x86"
- self.config["android"]["toolchain_name"] = target
+ self.config["android"]["toolchain_name"] = "i686-linux-android30"
return True
return False
diff --git a/python/servo/package_commands.py b/python/servo/package_commands.py
index 62ae60f5fa6..ab8cbacb2cd 100644
--- a/python/servo/package_commands.py
+++ b/python/servo/package_commands.py
@@ -160,7 +160,7 @@ class PackageCommands(CommandBase):
else:
raise Exception("TODO what should this be?")
- flavor_name = "Main"
+ flavor_name = "Basic"
if flavor is not None:
flavor_name = flavor.title()
@@ -176,10 +176,7 @@ class PackageCommands(CommandBase):
variant = ":assemble" + flavor_name + arch_string + build_type_string
apk_task_name = ":servoapp" + variant
aar_task_name = ":servoview" + variant
- maven_task_name = ":servoview:uploadArchive"
argv = ["./gradlew", "--no-daemon", apk_task_name, aar_task_name]
- if maven:
- argv.append(maven_task_name)
try:
with cd(path.join("support", "android", "apk")):
subprocess.check_call(argv, env=env)
diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py
index bd9382b55a1..ebaf5a5e983 100644
--- a/python/servo/post_build_commands.py
+++ b/python/servo/post_build_commands.py
@@ -118,6 +118,7 @@ class PostBuildCommands(CommandBase):
"am start " + extra + " org.mozilla.servo/org.mozilla.servo.MainActivity",
"sleep 0.5",
"echo Servo PID: $(pidof org.mozilla.servo)",
+ "logcat --pid=$(pidof org.mozilla.servo)",
"exit"
]
args = [self.android_adb_path(env)]
@@ -129,7 +130,7 @@ class PostBuildCommands(CommandBase):
if usb:
args += ["-d"]
shell = subprocess.Popen(args + ["shell"], stdin=subprocess.PIPE)
- shell.communicate("\n".join(script) + "\n")
+ shell.communicate(bytes("\n".join(script) + "\n", "utf8"))
return shell.wait()
args = [bin or self.get_nightly_binary_path(nightly) or self.get_binary_path(build_type)]
diff --git a/servo-tidy.toml b/servo-tidy.toml
index 6e295cac954..bc235ae68c9 100644
--- a/servo-tidy.toml
+++ b/servo-tidy.toml
@@ -65,6 +65,10 @@ packages = [
# style (0.64) vs. webxr (0.66) vs. mozjs_sys (0.68).
"bindgen",
+
+ # quickcheck (required by layout_2020 for tests) is
+ # stuck on 0.8.4 with no new releases.
+ "env_logger",
]
# Files that are ignored for all tidy and lint checks.
files = [
diff --git a/servobuild.example b/servobuild.example
index 1c63d91d4b0..d0d930ec202 100644
--- a/servobuild.example
+++ b/servobuild.example
@@ -56,8 +56,6 @@ media-stack = "auto"
# Android information
[android]
-# Defaults to the value of $ANDROID_SDK, $ANDROID_NDK, $ANDROID_TOOLCHAIN, $ANDROID_PLATFORM respectively
+# Defaults to the value of $ANDROID_SDK_ROOT, $ANDROID_NDK_ROOT respectively
#sdk = "/opt/android-sdk"
#ndk = "/opt/android-ndk"
-#toolchain = "/opt/android-toolchain"
-#platform = "android-18"
diff --git a/support/android/apk/build.gradle b/support/android/apk/build.gradle
index aa429b3da22..c2619efb978 100644
--- a/support/android/apk/build.gradle
+++ b/support/android/apk/build.gradle
@@ -1,42 +1,30 @@
-import org.apache.tools.ant.taskdefs.condition.Os
-
-buildscript {
- repositories {
- jcenter()
- google()
- }
- dependencies {
- classpath 'com.android.tools.build:gradle:3.1.3'
- }
-}
-
-allprojects {
- repositories {
- jcenter()
- flatDir {
- dirs rootDir.absolutePath + "/../../../target/android/aar"
- }
- google()
- }
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '8.0.1' apply false
+ id 'com.android.library' version '8.0.1' apply false
}
// Utility methods
-String getTargetDir(boolean debug, String arch) {
+ext.getTargetDir = { boolean debug, String arch ->
def basePath = project.rootDir.getParentFile().getParentFile().getParentFile().absolutePath
return basePath + '/target/android/' + getSubTargetDir(debug, arch)
}
-String getSubTargetDir(boolean debug, String arch) {
+ext.getNativeTargetDir = { boolean debug, String arch ->
+ def basePath = project.rootDir.getParentFile().getParentFile().getParentFile().absolutePath
+ return basePath + '/target/' + getSubTargetDir(debug, arch)
+}
+
+ext.getSubTargetDir = { boolean debug, String arch ->
return getRustTarget(arch) + '/' + (debug ? 'debug' : 'release')
}
-String getJniLibsPath(boolean debug, String arch) {
- return getTargetDir(debug, arch) + '/apk/jniLibs'
+ext.getJniLibsPath = { boolean debug, String arch ->
+ return getTargetDir(debug, arch) + '/jniLibs'
}
-static String getRustTarget(String arch) {
+ext.getRustTarget = { String arch ->
switch (arch.toLowerCase()) {
- case 'arm' : return 'arm-linux-androideabi'
case 'armv7' : return 'armv7-linux-androideabi'
case 'arm64' : return 'aarch64-linux-android'
case 'x86' : return 'i686-linux-android'
@@ -44,9 +32,8 @@ static String getRustTarget(String arch) {
}
}
-static String getNDKAbi(String arch) {
+ext.getNDKAbi = { String arch ->
switch (arch.toLowerCase()) {
- case 'arm' : return 'armeabi'
case 'armv7' : return 'armeabi-v7a'
case 'arm64' : return 'arm64-v8a'
case 'x86' : return 'x86'
@@ -54,16 +41,10 @@ static String getNDKAbi(String arch) {
}
}
-String getNdkDir() {
+ext.getNdkDir = { ->
// Read environment variable used in rust build system
- String ndkDir = System.getenv('ANDROID_NDK')
- if (ndkDir == null) {
- ndkDir = System.getenv('ANDROID_NDK_HOME')
- }
- if (ndkDir == null) {
- ndkDir = System.getenv('ANDROID_NDK_ROOT')
- }
- if (ndkDir == null) {
+ String ndkRoot = System.getenv('ANDROID_NDK_ROOT')
+ if (ndkRoot == null) {
// Fallback to ndkDir in local.properties
def rootDir = project.rootDir
def localProperties = new File(rootDir, "local.properties")
@@ -72,14 +53,13 @@ String getNdkDir() {
properties.load(instr)
}
- ndkDir = properties.getProperty('ndk.dir')
+ ndkRoot = properties.getProperty('ndk.dir')
}
- def cmd = Os.isFamily(Os.FAMILY_WINDOWS) ? 'ndk-build.cmd' : 'ndk-build'
- def ndkbuild = new File(ndkDir + '/' + cmd)
- if (!ndkbuild.exists()) {
- throw new GradleException("Please set a valid NDK_HOME environment variable" +
+ def ndkDir = ndkRoot != null ? new File(ndkRoot) : null
+ if (!ndkDir || !ndkDir.exists()) {
+ throw new GradleException("Please set a valid ANDROID_NDK_ROOT environment variable" +
"or ndk.dir path in local.properties file");
}
- return ndkbuild.absolutePath
+ return ndkDir.absolutePath
}
diff --git a/support/android/apk/gradle.properties b/support/android/apk/gradle.properties
new file mode 100644
index 00000000000..a03b3548962
--- /dev/null
+++ b/support/android/apk/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
diff --git a/support/android/apk/gradle/wrapper/gradle-wrapper.jar b/support/android/apk/gradle/wrapper/gradle-wrapper.jar
index 13372aef5e2..87b738cbd05 100644
--- a/support/android/apk/gradle/wrapper/gradle-wrapper.jar
+++ b/support/android/apk/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/support/android/apk/gradle/wrapper/gradle-wrapper.properties b/support/android/apk/gradle/wrapper/gradle-wrapper.properties
index 915f189a922..da1db5f04e8 100644
--- a/support/android/apk/gradle/wrapper/gradle-wrapper.properties
+++ b/support/android/apk/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,5 @@
-#Wed Jul 11 13:23:08 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
diff --git a/support/android/apk/gradlew b/support/android/apk/gradlew
index 9d82f789151..af6708ff229 100755
--- a/support/android/apk/gradlew
+++ b/support/android/apk/gradlew
@@ -1,4 +1,4 @@
-#!/usr/bin/env bash
+#!/usr/bin/env sh
##############################################################################
##
@@ -6,20 +6,38 @@
##
##############################################################################
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS=""
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m"'
+
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
-warn ( ) {
+warn () {
echo "$*"
}
-die ( ) {
+die () {
echo
echo "$*"
echo
@@ -30,6 +48,7 @@ die ( ) {
cygwin=false
msys=false
darwin=false
+nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
@@ -40,26 +59,11 @@ case "`uname`" in
MINGW* )
msys=true
;;
+ NONSTOP* )
+ nonstop=true
+ ;;
esac
-# Attempt to set APP_HOME
-# Resolve links: $0 may be a link
-PRG="$0"
-# Need this for relative symlinks.
-while [ -h "$PRG" ] ; do
- ls=`ls -ld "$PRG"`
- link=`expr "$ls" : '.*-> \(.*\)$'`
- if expr "$link" : '/.*' > /dev/null; then
- PRG="$link"
- else
- PRG=`dirname "$PRG"`"/$link"
- fi
-done
-SAVED="`pwd`"
-cd "`dirname \"$PRG\"`/" >/dev/null
-APP_HOME="`pwd -P`"
-cd "$SAVED" >/dev/null
-
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
@@ -85,7 +89,7 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
-if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
@@ -150,11 +154,19 @@ if $cygwin ; then
esac
fi
-# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
-function splitJvmOpts() {
- JVM_OPTS=("$@")
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
}
-eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
-JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
-exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
+exec "$JAVACMD" "$@"
diff --git a/support/android/apk/gradlew.bat b/support/android/apk/gradlew.bat
index aec99730b4e..0f8d5937c4a 100644
--- a/support/android/apk/gradlew.bat
+++ b/support/android/apk/gradlew.bat
@@ -8,14 +8,14 @@
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
-@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-set DEFAULT_JVM_OPTS=
-
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m"
+
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
@@ -46,10 +46,9 @@ echo location of your Java installation.
goto fail
:init
-@rem Get command-line arguments, handling Windowz variants
+@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
-if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
@@ -60,11 +59,6 @@ set _SKIP=2
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
-goto execute
-
-:4NT_args
-@rem Get arguments from the 4NT Shell from JP Software
-set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
diff --git a/support/android/apk/jni/Android.mk b/support/android/apk/jni/Android.mk
index 20a4de2d4b2..7ee4ffe58d8 100644
--- a/support/android/apk/jni/Android.mk
+++ b/support/android/apk/jni/Android.mk
@@ -16,13 +16,7 @@
MY_LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-LOCAL_PATH:= $(SERVO_TARGET_DIR)
+LOCAL_PATH := $(SERVO_TARGET_DIR)
LOCAL_MODULE := servojni
LOCAL_SRC_FILES := libsimpleservo.so
include $(PREBUILT_SHARED_LIBRARY)
-
-include $(CLEAR_VARS)
-LOCAL_PATH:= $(SERVO_TARGET_DIR)/../../gstreamer/gst-build-$(APP_ABI)
-LOCAL_MODULE := gstreamer
-LOCAL_SRC_FILES := libgstreamer_android.so
-include $(PREBUILT_SHARED_LIBRARY)
diff --git a/support/android/apk/jni/Application.mk b/support/android/apk/jni/Application.mk
index 9944120aebe..5b349f06d44 100644
--- a/support/android/apk/jni/Application.mk
+++ b/support/android/apk/jni/Application.mk
@@ -1,5 +1,5 @@
NDK_TOOLCHAIN_VERSION := clang
-APP_MODULES := c++_shared servojni gstreamer
-APP_PLATFORM := android-21
-APP_STL:= c++_shared
-APP_ABI:= armeabi-v7a x86
+APP_MODULES := c++_shared servojni
+APP_PLATFORM := android-30
+APP_STL := c++_shared
+APP_ABI := armeabi-v7a x86
diff --git a/support/android/apk/servoapp/build.gradle b/support/android/apk/servoapp/build.gradle
index 6b440e7b2c7..6e1cb514d26 100644
--- a/support/android/apk/servoapp/build.gradle
+++ b/support/android/apk/servoapp/build.gradle
@@ -1,18 +1,22 @@
-apply plugin: 'com.android.application'
+plugins {
+ id 'com.android.application'
+}
import java.util.regex.Matcher
import java.util.regex.Pattern
android {
- compileSdkVersion 27
- buildToolsVersion '27.0.3'
+ compileSdk 33
+ buildToolsVersion "33.0.2"
+
+ namespace 'org.mozilla.servo'
buildDir = rootDir.absolutePath + "/../../../target/android/gradle/servoapp"
defaultConfig {
applicationId "org.mozilla.servo"
- minSdkVersion 21
- targetSdkVersion 27
+ minSdk 30
+ targetSdk 30
versionCode 1
versionName "1.0.0"
}
@@ -26,11 +30,7 @@ android {
flavorDimensions "default"
productFlavors {
- main {
- }
- googlevr {
- }
- oculusvr {
+ basic {
}
}
@@ -61,19 +61,6 @@ android {
}
// Custom build types
- armDebug {
- initWith(debug)
- ndk {
- abiFilters getNDKAbi('arm')
- }
- }
-
- armRelease {
- initWith(release)
- ndk {
- abiFilters getNDKAbi('arm')
- }
- }
armv7Debug {
initWith(debug)
ndk {
@@ -144,7 +131,6 @@ android {
}
dependencies {
- implementation 'com.android.support.constraint:constraint-layout:1.1.2'
if (findProject(':servoview-local')) {
implementation project(':servoview-local')
} else {
diff --git a/support/android/apk/servoapp/src/googlevr/AndroidManifest.xml b/support/android/apk/servoapp/src/googlevr/AndroidManifest.xml
deleted file mode 100644
index a7df4ac14a9..00000000000
--- a/support/android/apk/servoapp/src/googlevr/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- BEGIN_INCLUDE(manifest) -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto"
- package="org.mozilla.servo">
- <application android:label="Servo">
- <activity android:name=".MainActivity"
- android:label="Servo">
- <meta-data android:name="android.app.lib_name" android:value="servo" />
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="com.google.intent.category.LAUNCHER"/>
- <category android:name="com.google.intent.category.DAYDREAM"/>
- <category android:name="com.google.intent.category.CARDBOARD"/>
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
-<!-- END_INCLUDE(manifest) -->
diff --git a/support/android/apk/servoapp/src/main/AndroidManifest.xml b/support/android/apk/servoapp/src/main/AndroidManifest.xml
index 71db56c53a1..3bedf50ffbf 100644
--- a/support/android/apk/servoapp/src/main/AndroidManifest.xml
+++ b/support/android/apk/servoapp/src/main/AndroidManifest.xml
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- BEGIN_INCLUDE(manifest) -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto"
- package="org.mozilla.servo">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
<uses-feature android:glEsVersion="0x00030000" android:required="true" />
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
diff --git a/support/android/apk/servoapp/src/main/java/org/mozilla/servo/MainActivity.java b/support/android/apk/servoapp/src/main/java/org/mozilla/servo/MainActivity.java
index 1e1c9dbabeb..a366e8037d2 100644
--- a/support/android/apk/servoapp/src/main/java/org/mozilla/servo/MainActivity.java
+++ b/support/android/apk/servoapp/src/main/java/org/mozilla/servo/MainActivity.java
@@ -78,8 +78,7 @@ public class MainActivity extends Activity implements Servo.Client {
Intent intent = getIntent();
String args = intent.getStringExtra("servoargs");
String log = intent.getStringExtra("servolog");
- String gstdebug = intent.getStringExtra("gstdebug");
- mServoView.setServoArgs(args, log, gstdebug);
+ mServoView.setServoArgs(args, log);
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
mServoView.loadUri(intent.getData());
@@ -89,8 +88,10 @@ public class MainActivity extends Activity implements Servo.Client {
@Override
protected void onDestroy() {
- super.onDestroy();
- mMediaSession.hideMediaSessionControls();
+ super.onDestroy();
+ if (mMediaSession != null) {
+ mMediaSession.hideMediaSessionControls();
+ }
}
private void setupUrlField() {
@@ -229,31 +230,31 @@ public class MainActivity extends Activity implements Servo.Client {
@Override
public void onMediaSessionMetadata(String title, String artist, String album) {
- if (mMediaSession == null) {
- mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
- }
- Log.d("onMediaSessionMetadata", title + " " + artist + " " + album);
- mMediaSession.updateMetadata(title, artist, album);
+ if (mMediaSession == null) {
+ mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
+ }
+ Log.d("onMediaSessionMetadata", title + " " + artist + " " + album);
+ mMediaSession.updateMetadata(title, artist, album);
}
@Override
public void onMediaSessionPlaybackStateChange(int state) {
- Log.d("onMediaSessionPlaybackStateChange", String.valueOf(state));
- if (mMediaSession == null) {
- mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
- }
-
- mMediaSession.setPlaybackState(state);
-
- if (state == MediaSession.PLAYBACK_STATE_NONE) {
- mMediaSession.hideMediaSessionControls();
- return;
- }
- if (state == MediaSession.PLAYBACK_STATE_PLAYING ||
- state == MediaSession.PLAYBACK_STATE_PAUSED) {
- mMediaSession.showMediaSessionControls();
- return;
- }
+ Log.d("onMediaSessionPlaybackStateChange", String.valueOf(state));
+ if (mMediaSession == null) {
+ mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
+ }
+
+ mMediaSession.setPlaybackState(state);
+
+ if (state == MediaSession.PLAYBACK_STATE_NONE) {
+ mMediaSession.hideMediaSessionControls();
+ return;
+ }
+ if (state == MediaSession.PLAYBACK_STATE_PLAYING ||
+ state == MediaSession.PLAYBACK_STATE_PAUSED) {
+ mMediaSession.showMediaSessionControls();
+ return;
+ }
}
@Override
diff --git a/support/android/apk/servoapp/src/main/res/layout/activity_main.xml b/support/android/apk/servoapp/src/main/res/layout/activity_main.xml
index 2cfb3357a01..42cf7a1a4b9 100644
--- a/support/android/apk/servoapp/src/main/res/layout/activity_main.xml
+++ b/support/android/apk/servoapp/src/main/res/layout/activity_main.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
@@ -102,4 +102,4 @@
android:focusable="true"/>
</LinearLayout>
-</android.support.constraint.ConstraintLayout>
+</androidx.constraintlayout.widget.ConstraintLayout>
diff --git a/support/android/apk/servoview/build.gradle b/support/android/apk/servoview/build.gradle
index 51bab4b45e2..5898bb7bca2 100644
--- a/support/android/apk/servoview/build.gradle
+++ b/support/android/apk/servoview/build.gradle
@@ -1,18 +1,23 @@
-apply plugin: 'com.android.library'
+plugins {
+ id 'com.android.library'
+}
import groovy.io.FileType
import java.util.regex.Matcher
import java.util.regex.Pattern
android {
- compileSdkVersion 27
- buildToolsVersion '27.0.3'
+ compileSdk 33
+ buildToolsVersion "33.0.2"
+
+ namespace 'org.mozilla.servoview'
buildDir = rootDir.absolutePath + "/../../../target/android/gradle/servoview"
+ ndkPath = getNdkDir()
defaultConfig {
- minSdkVersion 18
- targetSdkVersion 27
+ minSdk 30
+ targetSdk 30
versionCode 1
versionName "1.0"
}
@@ -26,25 +31,19 @@ android {
flavorDimensions "default"
productFlavors {
- main {
+ basic {
}
- googlevr {
- minSdkVersion 21
+ }
+
+ splits {
+ density {
+ enable false
}
- oculusvr {
- minSdkVersion 21
+ abi {
+ enable false
}
}
- splits {
- density {
- enable false
- }
- abi {
- enable false
- }
- }
-
buildTypes {
// Default debug and release build types are used as templates
@@ -59,65 +58,29 @@ android {
}
// Custom build types
- armDebug {
- initWith(debug)
- ndk {
- abiFilters getNDKAbi('arm')
- }
- }
- armRelease {
- initWith(release)
- ndk {
- abiFilters getNDKAbi('arm')
- }
- }
armv7Debug {
initWith(debug)
- ndk {
- abiFilters getNDKAbi('armv7')
- }
}
armv7Release {
initWith(release)
- ndk {
- abiFilters getNDKAbi('armv7')
- }
}
arm64Debug {
initWith(debug)
- ndk {
- abiFilters getNDKAbi('arm64')
- }
}
arm64Release {
initWith(release)
- ndk {
- abiFilters getNDKAbi('arm64')
- }
}
x86Debug {
initWith(debug)
- ndk {
- abiFilters getNDKAbi('x86')
- }
}
x86Release {
initWith(release)
- ndk {
- abiFilters getNDKAbi('x86')
- }
}
}
sourceSets {
main {
}
- armDebug {
- jniLibs.srcDirs = [getJniLibsPath(true, 'arm')]
- }
- armRelease {
- jniLibs.srcDirs = [getJniLibsPath(false, 'arm')]
- }
armv7Debug {
jniLibs.srcDirs = [getJniLibsPath(true, 'armv7')]
}
@@ -145,34 +108,49 @@ android {
}
}
-
- // Call our custom NDK Build task using flavor parameters
+ // Call our custom NDK Build task using flavor parameters.
+ // This step is needed because the Android Gradle Plugin system's
+ // integration with native C/C++ shared objects (based on the
+ // `android.externalNativeBuild` dsl object) assumes that we
+ // actually execute compiler commands to produced the shared
+ // objects. We already have the libsimpleservo.so produced by rustc.
+ // We could simply copy the .so to the `sourceSet.jniLibs` folder
+ // to make AGP bundle it with the APK, but this doesn't copy the STL
+ // (libc++_shared.so) as well. So we use ndk-build as a glorified
+ // `cp` command to copy the libsimpleservo.so from target/<arch>
+ // to target/android and crucially also include libc++_shared.so
+ // as well.
+ //
+ // FIXME(mukilan): According to the AGP docs, we should not be
+ // relying on task names used by the plugin system to hook into
+ // the build process, but instead we should use officially supported
+ // extension points such as `androidComponents.beforeVariants`
tasks.all {
compileTask ->
- Pattern pattern = Pattern.compile(/^compile[A-Z][\w\d]+([A-Z][\w\d]+)(Debug|Release)Ndk/)
+ // This matches the task `mergeBasicArmv7DebugJniLibFolders`.
+ Pattern pattern = Pattern.compile(/^merge[A-Z][\w\d]+([A-Z][\w\d]+)(Debug|Release)JniLibFolders/)
Matcher matcher = pattern.matcher(compileTask.name)
if (!matcher.find()) {
- return
+ return
}
def taskName = "ndkbuild" + compileTask.name
tasks.create(name: taskName, type: Exec) {
def debug = compileTask.name.contains("Debug")
def arch = matcher.group(1)
- commandLine getNdkDir(),
- 'APP_BUILD_SCRIPT=../jni/Android.mk',
- 'NDK_APPLICATION_MK=../jni/Application.mk',
- 'NDK_LIBS_OUT=' + getJniLibsPath(debug, arch),
- 'NDK_OUT=' + getTargetDir(debug, arch) + '/apk/obj',
- 'NDK_DEBUG=' + (debug ? '1' : '0'),
- 'APP_ABI=' + getNDKAbi(arch),
- 'SERVO_TARGET_DIR=' + getTargetDir(debug, arch)
+ commandLine getNdkDir() + "/ndk-build",
+ 'APP_BUILD_SCRIPT=../jni/Android.mk',
+ 'NDK_APPLICATION_MK=../jni/Application.mk',
+ 'NDK_LIBS_OUT=' + getJniLibsPath(debug, arch),
+ 'NDK_DEBUG=' + (debug ? '1' : '0'),
+ 'APP_ABI=' + getNDKAbi(arch),
+ 'NDK_LOG=1',
+ 'SERVO_TARGET_DIR=' + getNativeTargetDir(debug, arch)
}
compileTask.dependsOn taskName
}
-
project.afterEvaluate {
android.libraryVariants.all { variant ->
Pattern pattern = Pattern.compile(/^[\w\d]+([A-Z][\w\d]+)(Debug|Release)/)
@@ -205,7 +183,7 @@ dependencies {
]
// Iterate all build types and dependencies
// For each dependency call the proper implementation command and set the correct dependency path
- def list = ['arm', 'armv7', 'arm64', 'x86']
+ def list = ['armv7', 'arm64', 'x86']
for (arch in list) {
for (debug in [true, false]) {
String basePath = getTargetDir(debug, arch) + "/build"
@@ -220,10 +198,9 @@ dependencies {
}
}
- googlevrImplementation 'com.google.vr:sdk-base:1.140.0'
- googlevrImplementation(name: 'GVRService', ext: 'aar')
- oculusvrImplementation(name: 'OVRService', ext: 'aar')
- implementation 'com.android.support.constraint:constraint-layout:1.1.2'
+ implementation 'androidx.appcompat:appcompat:1.6.1'
+ implementation 'com.google.android.material:material:1.9.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
}
// folderFilter can be used to improve search performance
@@ -258,42 +235,3 @@ class ServoDependency {
public String fileName;
public String folderFilter;
}
-
-apply plugin: 'maven'
-import org.gradle.api.internal.artifacts.publish.DefaultPublishArtifact
-
-uploadArchives {
- doFirst {
- for ( arch in ["arm", "armv7", "arm64", "x86"] ) {
- def target = getTargetDir(false, arch)
- def aar = new File(target, "servoview.aar")
- if (aar.exists()) {
- def art = new DefaultPublishArtifact("servoview-" + arch, "aar", "aar", null, new Date(), aar);
- project.artifacts.add('archives', art)
- }
- }
- }
- repositories.mavenDeployer {
- repository(url: "file://localhost/${buildDir}/maven")
- def cmd = "git rev-parse --short HEAD"
- def proc = cmd.execute()
- def commit = proc.text.trim()
- def version = "0.0.1." + new Date().format('yyyyMMdd') + "." + commit
- for ( arch_ in ["arm", "armv7", "arm64", "x86"] ) {
- def arch = arch_
- addFilter(arch) {artifact, file -> artifact.name == "servoview-" + arch}
- pom(arch).artifactId = "servoview-" + arch
- pom(arch).groupId = 'org.mozilla.servoview'
- pom(arch).version = version
- pom(arch).project {
- licenses {
- license {
- name 'The Mozilla Public License, v. 2.0'
- url 'https://mozilla.org/MPL/2.0/'
- distribution 'repo'
- }
- }
- }
- }
- }
-}
diff --git a/support/android/apk/servoview/src/googlevr/AndroidManifest.xml b/support/android/apk/servoview/src/googlevr/AndroidManifest.xml
deleted file mode 100644
index 7e1c7048634..00000000000
--- a/support/android/apk/servoview/src/googlevr/AndroidManifest.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- BEGIN_INCLUDE(manifest) -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.mozilla.servoview">
- <application>
- <activity android:name=".MainActivity"
- android:screenOrientation="landscape"
- android:enableVrMode="@string/gvr_vr_mode_component"
- android:resizeableActivity="false">
- <!-- Intent filter that enables this app to be launched from the
-Daydream Home menu. -->
- <intent-filter>
- <action android:name="android.intent.action.MAIN" />
- <category android:name="com.google.intent.category.DAYDREAM"/>
- </intent-filter>
- </activity>
- </application>
-
-</manifest>
- <!-- END_INCLUDE(manifest) -->
diff --git a/support/android/apk/servoview/src/main/AndroidManifest.xml b/support/android/apk/servoview/src/main/AndroidManifest.xml
index 1e916f18c97..94cbbcfc396 100644
--- a/support/android/apk/servoview/src/main/AndroidManifest.xml
+++ b/support/android/apk/servoview/src/main/AndroidManifest.xml
@@ -1,2 +1 @@
-<manifest xmlns:android="http://schemas.android.com/apk/res/android"
- package="org.mozilla.servoview" />
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java
index 5fa91fa34f6..29dce9f01b1 100644
--- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java
+++ b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/JNIServo.java
@@ -6,7 +6,7 @@
package org.mozilla.servoview;
import android.app.Activity;
-
+import android.view.Surface;
/**
* Maps /ports/libsimpleservo API
*/
@@ -14,13 +14,12 @@ import android.app.Activity;
public class JNIServo {
JNIServo() {
System.loadLibrary("c++_shared");
- System.loadLibrary("gstreamer_android");
System.loadLibrary("simpleservo");
}
public native String version();
- public native void init(Activity activity, ServoOptions options, Callbacks callbacks);
+ public native void init(Activity activity, ServoOptions options, Callbacks callbacks, Surface surface);
public native void deinit();
@@ -66,6 +65,9 @@ public class JNIServo {
public native void click(float x, float y);
+ public native void pauseCompositor();
+ public native void resumeCompositor(Surface surface, ServoCoordinates coords);
+
public native void mediaSessionAction(int action);
public static class ServoOptions {
diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java
index 7f8bd3fc211..e8dfd332a11 100644
--- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java
+++ b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/Servo.java
@@ -8,6 +8,7 @@ package org.mozilla.servoview;
import android.app.Activity;
import android.content.Context;
import android.util.Log;
+import android.view.Surface;
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
@@ -30,21 +31,16 @@ public class Servo {
RunCallback runCallback,
GfxCallbacks gfxcb,
Client client,
- Activity activity) {
+ Activity activity,
+ Surface surface) {
mRunCallback = runCallback;
mServoCallbacks = new Callbacks(client, gfxcb);
mRunCallback.inGLThread(() -> {
- mJNI.init(activity, options, mServoCallbacks);
+ mJNI.init(activity, options, mServoCallbacks, surface);
});
-
- try {
- GStreamer.init((Context) activity);
- } catch (Exception e) {
- e.printStackTrace();
- }
}
public void resetGfxCallbacks(GfxCallbacks gfxcb) {
@@ -164,6 +160,13 @@ public class Servo {
mRunCallback.inGLThread(() -> mJNI.click(x, y));
}
+ public void pauseCompositor() {
+ mRunCallback.inGLThread(() -> mJNI.pauseCompositor());
+ }
+ public void resumeCompositor(Surface surface, ServoCoordinates coords) {
+ mRunCallback.inGLThread(() -> mJNI.resumeCompositor(surface, coords));
+ }
+
public void suspend(boolean suspended) {
mSuspended = suspended;
}
diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java
deleted file mode 100644
index 80f897fa4b9..00000000000
--- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoSurface.java
+++ /dev/null
@@ -1,302 +0,0 @@
-/* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-package org.mozilla.servoview;
-
-import android.app.Activity;
-import android.net.Uri;
-import android.opengl.EGL14;
-import android.opengl.EGLConfig;
-import android.opengl.EGLContext;
-import android.opengl.EGLDisplay;
-import android.opengl.EGLSurface;
-import android.opengl.GLUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.util.Log;
-import android.view.Surface;
-
-import org.mozilla.servoview.JNIServo.ServoCoordinates;
-import org.mozilla.servoview.JNIServo.ServoOptions;
-import org.mozilla.servoview.Servo.Client;
-import org.mozilla.servoview.Servo.GfxCallbacks;
-import org.mozilla.servoview.Servo.RunCallback;
-
-import static android.opengl.EGL14.EGL_CONTEXT_CLIENT_VERSION;
-import static android.opengl.EGL14.EGL_NO_CONTEXT;
-import static android.opengl.EGL14.EGL_NO_SURFACE;
-import static android.opengl.EGL14.EGL_OPENGL_ES2_BIT;
-
-public class ServoSurface {
- private static final String LOGTAG = "ServoSurface";
- private final GLThread mGLThread;
- private final Handler mMainLooperHandler;
- private Handler mGLLooperHandler;
- private Surface mASurface;
- private int mPadding;
- private int mWidth;
- private int mHeight;
- private long mVRExternalContext;
- private Servo mServo;
- private Client mClient = null;
- private String mServoArgs;
- private String mServoLog;
- private String mInitialUri;
- private Activity mActivity;
-
- public ServoSurface(Surface surface, int width, int height, int padding) {
- mPadding = padding;
- mWidth = width;
- mHeight = height;
- mASurface = surface;
- mMainLooperHandler = new Handler(Looper.getMainLooper());
- mGLThread = new GLThread();
- }
-
- public void onSurfaceChanged(Surface surface) {
- mASurface = surface;
- mGLThread.onSurfaceChanged();
- }
-
- public void setClient(Client client) {
- mClient = client;
- }
-
- public void setServoArgs(String args, String log) {
- mServoArgs = args;
- mServoLog = log;
- }
-
- public void setActivity(Activity activity) {
- mActivity = activity;
- }
-
- public void setVRExternalContext(long context) {
- mVRExternalContext = context;
- }
-
- public void runLoop() {
- mGLThread.start();
- }
-
- public void shutdown() {
- Log.d(LOGTAG, "shutdown");
- mServo.shutdown();
- mServo = null;
- mGLThread.shutdown();
- try {
- Log.d(LOGTAG, "Waiting for GL thread to shutdown");
- mGLThread.join();
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- public void reload() {
- mServo.reload();
- }
-
- public void goBack() {
- mServo.goBack();
- }
-
- public void goForward() {
- mServo.goForward();
- }
-
- public void stop() {
- mServo.stop();
- }
-
- public void loadUri(String uri) {
- if (mServo != null) {
- mServo.loadUri(uri);
- } else {
- mInitialUri = uri;
- }
- }
-
- public void loadUri(Uri uri) {
- loadUri(uri.toString());
- }
-
- public void scrollStart(int dx, int dy, int x, int y) {
- mServo.scrollStart(dx, dy, x, y);
- }
-
- public void scroll(int dx, int dy, int x, int y) {
- mServo.scroll(dx, dy, x, y);
- }
-
- public void scrollEnd(int dx, int dy, int x, int y) {
- mServo.scrollEnd(dx, dy, x, y);
- }
-
- public void click(float x, float y) {
- mServo.click(x, y);
- }
-
- public void onSurfaceResized(int width, int height) {
- mWidth = width;
- mHeight = height;
-
- ServoCoordinates coords = new ServoCoordinates();
- coords.x = mPadding;
- coords.y = mPadding;
- coords.width = width - 2 * mPadding;
- coords.height = height - 2 * mPadding;
- coords.fb_width = width;
- coords.fb_height = height;
-
- mServo.resize(coords);
- }
-
- static class GLSurface implements GfxCallbacks {
- private EGLConfig[] mEGLConfigs;
- private EGLDisplay mEglDisplay;
- private EGLContext mEglContext;
- private EGLSurface mEglSurface;
-
- void throwGLError(String function) {
- throwGLError(function, EGL14.eglGetError());
- }
-
- void throwGLError(String function, int error) {
- throw new RuntimeException("Error: " + function + "() Failed " + GLUtils.getEGLErrorString(error));
- }
-
- GLSurface(Surface surface) {
- mEglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- int[] version = new int[2];
- if (!EGL14.eglInitialize(mEglDisplay, version, 0, version, 1)) {
- throwGLError("eglInitialize");
- }
- mEGLConfigs = new EGLConfig[1];
- int[] configsCount = new int[1];
- int[] configSpec = new int[]{
- EGL14.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
- EGL14.EGL_RED_SIZE, 8,
- EGL14.EGL_GREEN_SIZE, 8,
- EGL14.EGL_BLUE_SIZE, 8,
- EGL14.EGL_ALPHA_SIZE, 8,
- EGL14.EGL_DEPTH_SIZE, 24,
- EGL14.EGL_STENCIL_SIZE, 0,
- EGL14.EGL_NONE
- };
- if ((!EGL14.eglChooseConfig(mEglDisplay, configSpec, 0, mEGLConfigs, 0, 1, configsCount, 0)) || (configsCount[0] == 0)) {
- throwGLError("eglChooseConfig");
- }
- if (mEGLConfigs[0] == null) {
- throw new RuntimeException("Error: eglConfig() not Initialized");
- }
- int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL14.EGL_NONE};
- mEglContext = EGL14.eglCreateContext(mEglDisplay, mEGLConfigs[0], EGL14.EGL_NO_CONTEXT, attrib_list, 0);
- int glError = EGL14.eglGetError();
- if (glError != EGL14.EGL_SUCCESS) {
- throwGLError("eglCreateContext", glError);
- }
- mEglSurface = EGL14.eglCreateWindowSurface(mEglDisplay, mEGLConfigs[0], surface, new int[]{EGL14.EGL_NONE}, 0);
- if (mEglSurface == null || mEglSurface == EGL14.EGL_NO_SURFACE) {
- glError = EGL14.eglGetError();
- if (glError == EGL14.EGL_BAD_NATIVE_WINDOW) {
- Log.e(LOGTAG, "Error: createWindowSurface() Returned EGL_BAD_NATIVE_WINDOW.");
- return;
- }
- throwGLError("createWindowSurface", glError);
- }
-
- makeCurrent();
- }
-
-
- public void makeCurrent() {
- if (!EGL14.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- throwGLError("eglMakeCurrent");
- }
- }
-
- public void flushGLBuffers() {
- EGL14.eglSwapBuffers(mEglDisplay, mEglSurface);
- }
-
- public void animationStateChanged(boolean animating) {
- // FIXME
- }
-
- void destroy() {
- Log.d(LOGTAG, "Destroying surface");
- if (!EGL14.eglMakeCurrent(mEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)) {
- throwGLError("eglMakeCurrent");
- }
- if (!EGL14.eglDestroyContext(mEglDisplay, mEglContext)) {
- throwGLError("eglDestroyContext");
- }
- if (!EGL14.eglDestroySurface(mEglDisplay, mEglSurface)) {
- throwGLError("eglDestroySurface");
- }
- if (!EGL14.eglTerminate(mEglDisplay)) {
- throwGLError("eglTerminate");
- }
- }
-
- }
-
- class GLThread extends Thread implements RunCallback {
- private GLSurface mSurface;
-
- public void inGLThread(Runnable r) {
- mGLLooperHandler.post(r);
- }
-
- public void inUIThread(Runnable r) {
- mMainLooperHandler.post(r);
- }
-
- public void onSurfaceChanged() {
- Log.d(LOGTAG, "GLThread::onSurfaceChanged");
- mSurface.destroy();
- mSurface = new GLSurface(mASurface);
- mServo.resetGfxCallbacks(mSurface);
- }
-
- public void shutdown() {
- Log.d(LOGTAG, "GLThread::shutdown");
- mSurface.destroy();
- mGLLooperHandler.getLooper().quitSafely();
- }
-
- public void run() {
- Looper.prepare();
-
- mSurface = new GLSurface(mASurface);
-
- mGLLooperHandler = new Handler();
-
- inUIThread(() -> {
- ServoCoordinates coords = new ServoCoordinates();
- coords.x = mPadding;
- coords.y = mPadding;
- coords.width = mWidth - 2 * mPadding;
- coords.height = mHeight - 2 * mPadding;
- coords.fb_width = mWidth;
- coords.fb_height = mHeight;
-
- ServoOptions options = new ServoOptions();
- options.coordinates = coords;
- options.args = mServoArgs;
- options.density = 1;
- options.url = mInitialUri;
- options.logStr = mServoLog;
- options.enableLogs = true;
- options.enableSubpixelTextAntialiasing = false;
- options.VRExternalContext = mVRExternalContext;
-
- mServo = new Servo(options, this, mSurface, mClient, mActivity);
- });
-
- Looper.loop();
- }
- }
-}
diff --git a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java
index 3784bbf58cb..19343d134d7 100644
--- a/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java
+++ b/support/android/apk/servoview/src/main/java/org/mozilla/servoview/ServoView.java
@@ -7,17 +7,15 @@ package org.mozilla.servoview;
import android.app.Activity;
import android.content.Context;
-import android.net.Uri;
-import android.opengl.GLES31;
-import android.opengl.GLSurfaceView;
import android.util.AttributeSet;
+import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
import android.util.DisplayMetrics;
import android.util.Log;
-import android.view.Choreographer;
-import android.view.GestureDetector;
-import android.view.MotionEvent;
-import android.view.ScaleGestureDetector;
-import android.widget.OverScroller;
+import android.view.Surface;
+import android.view.SurfaceView;
+import android.view.SurfaceHolder;
import org.mozilla.servoview.JNIServo.ServoCoordinates;
import org.mozilla.servoview.JNIServo.ServoOptions;
@@ -25,41 +23,45 @@ import org.mozilla.servoview.Servo.Client;
import org.mozilla.servoview.Servo.GfxCallbacks;
import org.mozilla.servoview.Servo.RunCallback;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.opengles.GL10;
+import android.view.Choreographer;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.ScaleGestureDetector;
+import android.widget.OverScroller;
-public class ServoView extends GLSurfaceView
- implements
- GestureDetector.OnGestureListener,
- ScaleGestureDetector.OnScaleGestureListener,
- Choreographer.FrameCallback,
- GfxCallbacks,
- RunCallback {
+import java.util.ArrayList;
+public class ServoView extends SurfaceView
+ implements
+ GfxCallbacks,
+ RunCallback,
+ Choreographer.FrameCallback,
+ GestureDetector.OnGestureListener,
+ ScaleGestureDetector.OnScaleGestureListener {
private static final String LOGTAG = "ServoView";
-
- private Activity mActivity;
- private Servo mServo;
+ private GLThread mGLThread;
+ private Handler mGLLooperHandler;
+ private Surface mASurface;
+ protected Servo mServo = null;
private Client mClient = null;
- private Uri mInitialUri = null;
- private boolean mAnimating;
private String mServoArgs;
private String mServoLog;
- private String mGstDebug;
+ private String mInitialUri;
+ private Activity mActivity;
private GestureDetector mGestureDetector;
- private ScaleGestureDetector mScaleGestureDetector;
-
- private OverScroller mScroller;
private int mLastX = 0;
private int mCurX = 0;
private int mLastY = 0;
private int mCurY = 0;
private boolean mFlinging;
+ private ScaleGestureDetector mScaleGestureDetector;
+ private OverScroller mScroller;
private boolean mZooming;
private float mZoomFactor = 1;
-
private boolean mRedrawing;
+ private boolean mAnimating;
+ private boolean mPaused = false;
public ServoView(Context context) {
super(context);
@@ -71,79 +73,49 @@ public class ServoView extends GLSurfaceView
init(context);
}
- public void onDetachedFromWindow() {
- mServo.shutdown();
- mServo = null;
- super.onDetachedFromWindow();
- }
-
private void init(Context context) {
mActivity = (Activity) context;
setFocusable(true);
setFocusableInTouchMode(true);
+ setClickable(true);
+ ArrayList view = new ArrayList();
+ view.add(this);
+ addTouchables(view);
setWillNotCacheDrawing(false);
- setEGLContextClientVersion(3);
- setEGLConfigChooser(8, 8, 8, 8, 24, 0);
- setPreserveEGLContextOnPause(true);
- ServoGLRenderer mRenderer = new ServoGLRenderer(this);
- setRenderer(mRenderer);
- setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
initGestures(context);
- }
- public void setServoArgs(String args, String log, String gstdebug) {
- mServoArgs = args;
- mServoLog = log;
- mGstDebug = gstdebug;
+ mGLThread = new GLThread(mActivity, this);
+ getHolder().addCallback(mGLThread);
+ mGLThread.start();
}
- public void reload() {
- mServo.reload();
- }
- public void goBack() {
- mServo.goBack();
- }
-
- public void goForward() {
- mServo.goForward();
+ public void setClient(Client client) {
+ mClient = client;
}
- public void stop() {
- mServo.stop();
+ public void setServoArgs(String args, String log) {
+ mServoArgs = args;
+ mServoLog = log;
}
- public void onSurfaceInvalidated(int width, int height) {
- if (mServo != null) {
- ServoCoordinates coords = new ServoCoordinates();
- coords.width = width;
- coords.height = height;
- coords.fb_width = width;
- coords.fb_height = height;
- mServo.resize(coords);
- mServo.refresh();
- }
+ // RunCallback
+ public void inGLThread(Runnable r) {
+ mGLLooperHandler.post(r);
}
- public void loadUri(Uri uri) {
- if (mServo != null) {
- mServo.loadUri(uri.toString());
- } else {
- mInitialUri = uri;
- }
+ public void inUIThread(Runnable r) {
+ post(r);
}
- public void mediaSessionAction(int action) {
- mServo.mediaSessionAction(action);
- }
+ // GfxCallbacks
public void flushGLBuffers() {
- requestRender();
}
- // Scroll and click
+ // Scroll and click
public void animationStateChanged(boolean animating) {
if (!mAnimating && animating) {
post(() -> startLooping());
@@ -154,48 +126,6 @@ public class ServoView extends GLSurfaceView
public void makeCurrent() {
}
- public void inGLThread(Runnable f) {
- queueEvent(f);
- }
-
- public void inUIThread(Runnable f) {
- post(f);
- }
-
- public void onGLReady() {
- ServoCoordinates coords = new ServoCoordinates();
- coords.width = getWidth();
- coords.height = getHeight();
- coords.fb_width = getWidth();
- coords.fb_height = getHeight();
-
- ServoOptions options = new ServoOptions();
- options.args = mServoArgs;
- options.coordinates = coords;
- options.enableLogs = true;
- options.enableSubpixelTextAntialiasing = true;
-
- DisplayMetrics metrics = new DisplayMetrics();
- mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
- options.density = metrics.density;
- inGLThread(() -> {
- String uri = mInitialUri == null ? null : mInitialUri.toString();
- options.url = uri;
- options.logStr = mServoLog;
- options.gstDebugStr = mGstDebug;
- mServo = new Servo(options, this, this, mClient, mActivity);
- });
- }
-
- public void setClient(Client client) {
- mClient = client;
- }
-
- private void initGestures(Context context) {
- mGestureDetector = new GestureDetector(context, this);
- mScaleGestureDetector = new ScaleGestureDetector(context, this);
- mScroller = new OverScroller(context);
- }
private void startLooping() {
// In case we were already drawing.
@@ -253,6 +183,63 @@ public class ServoView extends GLSurfaceView
}
}
+ // Calls from Activity
+ public void onPause() {
+ if (mServo != null) {
+ mServo.suspend(true);
+ }
+ }
+
+ public void onResume() {
+ if (mServo != null) {
+ mServo.suspend(false);
+ }
+ }
+
+ public void reload() {
+ mServo.reload();
+ }
+
+ public void goBack() {
+ mServo.goBack();
+ }
+
+ public void goForward() {
+ mServo.goForward();
+ }
+
+ public void stop() {
+ mServo.stop();
+ }
+
+ public void loadUri(String uri) {
+ if (mServo != null) {
+ mServo.loadUri(uri);
+ } else {
+ mInitialUri = uri;
+ }
+ }
+
+ public void loadUri(Uri uri) {
+ loadUri(uri.toString());
+ }
+
+ public void scrollStart(int dx, int dy, int x, int y) {
+ mServo.scrollStart(dx, dy, x, y);
+ }
+
+ public void scroll(int dx, int dy, int x, int y) {
+ mServo.scroll(dx, dy, x, y);
+ }
+
+ public void scrollEnd(int dx, int dy, int x, int y) {
+ mServo.scrollEnd(dx, dy, x, y);
+ }
+
+ public void click(float x, float y) {
+ mServo.click(x, y);
+ }
+
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
mFlinging = true;
@@ -275,20 +262,22 @@ public class ServoView extends GLSurfaceView
return true;
}
+ @Override
public boolean onTouchEvent(final MotionEvent e) {
mGestureDetector.onTouchEvent(e);
mScaleGestureDetector.onTouchEvent(e);
int action = e.getActionMasked();
+
float x = e.getX();
-
float y = e.getY();
-
+
int pointerIndex = e.getActionIndex();
int pointerId = e.getPointerId(pointerIndex);
+
switch (action) {
case (MotionEvent.ACTION_DOWN):
- mServo.touchDown(x, y, pointerId);
+ case (MotionEvent.ACTION_POINTER_DOWN):
mFlinging = false;
mScroller.forceFinished(true);
mCurX = (int) x;
@@ -299,32 +288,35 @@ public class ServoView extends GLSurfaceView
case (MotionEvent.ACTION_MOVE):
mCurX = (int) x;
mCurY = (int) y;
- mServo.touchMove(x, y, pointerId);
return true;
case (MotionEvent.ACTION_UP):
- mServo.touchUp(x, y, pointerId);
+ case (MotionEvent.ACTION_POINTER_UP):
+ return true;
case (MotionEvent.ACTION_CANCEL):
- mServo.touchCancel(x, y, pointerId);
return true;
default:
return true;
}
}
- public boolean onSingleTapUp(MotionEvent e) {
- return false;
- }
-
+ // OnGestureListener
public void onLongPress(MotionEvent e) {
}
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
+ mServo.scroll((int) -distanceX, (int) -distanceY, (int) e1.getX(), (int) e1.getY());
return true;
}
+ public boolean onSingleTapUp(MotionEvent e) {
+ click(e.getX(), e.getY());
+ return false;
+ }
+
public void onShowPress(MotionEvent e) {
}
+ // OnScaleGestureListener
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
if (mScroller.isFinished()) {
@@ -351,41 +343,81 @@ public class ServoView extends GLSurfaceView
mServo.pinchZoomEnd(mZoomFactor, 0, 0);
}
-
- @Override
- public void onPause() {
- super.onPause();
- if (mServo != null) {
- mServo.suspend(true);
- }
+ private void initGestures(Context context) {
+ mGestureDetector = new GestureDetector(context, this);
+ mScaleGestureDetector = new ScaleGestureDetector(context, this);
+ mScroller = new OverScroller(context);
}
- @Override
- public void onResume() {
- super.onResume();
- if (mServo != null) {
- mServo.suspend(false);
- }
+ public void mediaSessionAction(int action) {
+ mServo.mediaSessionAction(action);
}
- static class ServoGLRenderer implements Renderer {
+ class GLThread extends Thread implements SurfaceHolder.Callback {
+ private Activity mActivity;
+ private ServoView mServoView;
+ GLThread(Activity activity, ServoView servoView) {
+ mActivity = activity;
+ mServoView = servoView;
+ }
- private final ServoView mView;
+ public void surfaceCreated(SurfaceHolder holder) {
+ Log.d(LOGTAG, "GLThread::surfaceCreated");
+
+ ServoCoordinates coords = new ServoCoordinates();
+ coords.width = mServoView.getWidth();
+ coords.height = mServoView.getHeight();
+ coords.fb_width = mServoView.getWidth();
+ coords.fb_height = mServoView.getHeight();
+
+ Surface surface = holder.getSurface();
+ ServoOptions options = new ServoOptions();
+ options.args = mServoView.mServoArgs;
+ options.coordinates = coords;
+ options.enableLogs = true;
+ options.enableSubpixelTextAntialiasing = true;
+
+ DisplayMetrics metrics = new DisplayMetrics();
+ mActivity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
+ options.density = metrics.density;
+ if (mServoView.mServo == null && !mPaused) {
+ mServoView.mServo = new Servo(
+ options, mServoView, mServoView, mClient, mActivity, surface);
+ } else {
+ mPaused = false;
+ mServoView.mServo.resumeCompositor(surface, coords);
+ }
- ServoGLRenderer(ServoView view) {
- mView = view;
}
- public void onSurfaceCreated(GL10 unused, EGLConfig config) {
- mView.onGLReady();
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ Log.d(LOGTAG, "GLThread::surfaceChanged");
+ ServoCoordinates coords = new ServoCoordinates();
+ coords.width = width;
+ coords.height = height;
+ coords.fb_width = width;
+ coords.fb_height = height;
+
+ mServoView.mServo.resize(coords);
}
- public void onDrawFrame(GL10 unused) {
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ Log.d(LOGTAG, "GLThread::surfaceDestroyed");
+ mPaused = true;
+ mServoView.mServo.pauseCompositor();
}
- public void onSurfaceChanged(GL10 gl, int width, int height) {
- GLES31.glViewport(0, 0, width, height);
- mView.onSurfaceInvalidated(width, height);
+ public void shutdown() {
+ Log.d(LOGTAG, "GLThread::shutdown");
+ mGLLooperHandler.getLooper().quitSafely();
+ }
+
+ public void run() {
+ Looper.prepare();
+
+ mGLLooperHandler = new Handler();
+
+ Looper.loop();
}
}
}
diff --git a/support/android/apk/servoview/src/oculusvr/AndroidManifest.xml b/support/android/apk/servoview/src/oculusvr/AndroidManifest.xml
deleted file mode 100644
index 076c3dfa688..00000000000
--- a/support/android/apk/servoview/src/oculusvr/AndroidManifest.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- BEGIN_INCLUDE(manifest) -->
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.mozilla.servoview">>
- <application>
- <meta-data android:name="com.samsung.android.vr.application.mode" android:value="vr_only"/>
- <activity android:name=".MainActivity" android:screenOrientation="landscape">
- </activity>
- </application>
-</manifest>
-<!-- END_INCLUDE(manifest) -->
diff --git a/support/android/apk/settings.gradle b/support/android/apk/settings.gradle
index 3d36551554c..d8826861853 100644
--- a/support/android/apk/settings.gradle
+++ b/support/android/apk/settings.gradle
@@ -1,3 +1,19 @@
+pluginManagement {
+ repositories {
+ google()
+ mavenCentral()
+ gradlePluginPortal()
+ }
+}
+
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
include ':servoapp'
def userPropertiesFile = new File('user.properties')
diff --git a/support/android/fakeld/fake-ld-arm.sh b/support/android/fakeld/fake-ld-arm.sh
deleted file mode 100755
index 0e81b85fb14..00000000000
--- a/support/android/fakeld/fake-ld-arm.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-source ./support/android/fakeld/fake-ld.sh
-
-export _GCC_PARAMS="${@}"
-call_gcc "arch-arm" "armeabi" "arm-linux-androideabi"
diff --git a/support/android/fakeld/fake-ld-arm64.sh b/support/android/fakeld/fake-ld-arm64.sh
deleted file mode 100755
index eb7b0ada9a2..00000000000
--- a/support/android/fakeld/fake-ld-arm64.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-source ./support/android/fakeld/fake-ld.sh
-
-export _GCC_PARAMS="${@}"
-call_gcc "arch-arm64" "arm64-v8a" "aarch64-linux-android"
diff --git a/support/android/fakeld/fake-ld-armv7.sh b/support/android/fakeld/fake-ld-armv7.sh
deleted file mode 100755
index b1758a9b07a..00000000000
--- a/support/android/fakeld/fake-ld-armv7.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-source ./support/android/fakeld/fake-ld.sh
-
-export _GCC_PARAMS="${@}"
-call_gcc "arch-arm" "armeabi-v7a" "armv7-linux-androideabi"
diff --git a/support/android/fakeld/fake-ld-x86.sh b/support/android/fakeld/fake-ld-x86.sh
deleted file mode 100755
index 2df1d5e49e9..00000000000
--- a/support/android/fakeld/fake-ld-x86.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/usr/bin/env bash
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-source ./support/android/fakeld/fake-ld.sh
-
-export _GCC_PARAMS="${@}"
-call_gcc "arch-x86" "x86" "i686-linux-android"
diff --git a/support/android/fakeld/fake-ld.cmd b/support/android/fakeld/fake-ld.cmd
deleted file mode 100644
index b13c7e818ab..00000000000
--- a/support/android/fakeld/fake-ld.cmd
+++ /dev/null
@@ -1,2 +0,0 @@
-@echo off
-gcc -mwindows %*
diff --git a/support/android/fakeld/fake-ld.sh b/support/android/fakeld/fake-ld.sh
deleted file mode 100755
index 29eef1326ba..00000000000
--- a/support/android/fakeld/fake-ld.sh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/usr/bin/env bash
-
-# This Source Code Form is subject to the terms of the Mozilla Public
-# License, v. 2.0. If a copy of the MPL was not distributed with this
-# file, You can obtain one at https://mozilla.org/MPL/2.0/.
-
-set -o errexit
-set -o nounset
-set -o pipefail
-
-call_gcc()
-{
- TARGET_DIR="${OUT_DIR}/../../.."
-
- export _ANDROID_ARCH=$1
- export _ANDROID_TARGET=$3
- export ANDROID_SYSROOT="${ANDROID_NDK}/platforms/${ANDROID_PLATFORM}/${_ANDROID_ARCH}"
- ANDROID_TOOLCHAIN=""
- for host in "linux-x86_64" "linux-x86" "darwin-x86_64" "darwin-x86"; do
- if [[ -d "${ANDROID_NDK}/toolchains/llvm/prebuilt/${host}/bin" ]]; then
- ANDROID_TOOLCHAIN="${ANDROID_NDK}/toolchains/llvm/prebuilt/${host}/bin"
- break
- fi
- done
-
- ANDROID_CPU_ARCH_DIR=$2
- ANDROID_CXX_LIBS="${ANDROID_NDK}/sources/cxx-stl/llvm-libc++/libs/${ANDROID_CPU_ARCH_DIR}"
-
- echo "toolchain: ${ANDROID_TOOLCHAIN}"
- echo "libs dir: ${ANDROID_CXX_LIBS}"
- echo "sysroot: ${ANDROID_SYSROOT}"
- echo "targetdir: ${TARGET_DIR}"
-
- "${ANDROID_TOOLCHAIN}/clang" \
- --sysroot="${ANDROID_SYSROOT}" \
- --gcc-toolchain="${GCC_TOOLCHAIN}" \
- --target="${_ANDROID_TARGET}" \
- -L "${ANDROID_CXX_LIBS}" ${_GCC_PARAMS} -lc++
-}