mirror of
https://github.com/servo/servo.git
synced 2025-07-24 15:50:21 +01:00
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>
This commit is contained in:
parent
8e6bdb69b1
commit
d7de206dbd
58 changed files with 923 additions and 1382 deletions
|
@ -1,26 +1,17 @@
|
||||||
[target.arm-linux-androideabi]
|
[target.aarch64-linux-android]
|
||||||
linker = "./support/android/fakeld/fake-ld-arm.sh"
|
linker = "aarch64-linux-android30-clang"
|
||||||
ar = "arm-linux-androideabi-ar"
|
|
||||||
|
|
||||||
[target.armv7-linux-androideabi]
|
[target.armv7-linux-androideabi]
|
||||||
linker = "./support/android/fakeld/fake-ld-armv7.sh"
|
linker = "armv7a-linux-androideabi30-clang"
|
||||||
ar = "arm-linux-androideabi-ar"
|
|
||||||
|
|
||||||
[target.aarch64-linux-android]
|
[target.armv-linux-androideabi]
|
||||||
linker = "./support/android/fakeld/fake-ld-arm64.sh"
|
linker = "armv7a-linux-androideabi30-clang"
|
||||||
ar = "aarch64-linux-android-ar"
|
|
||||||
|
|
||||||
[target.i686-linux-android]
|
[target.i686-linux-android]
|
||||||
linker = "./support/android/fakeld/fake-ld-x86.sh"
|
linker = "i686-linux-android30-clang"
|
||||||
ar = "i686-linux-android-ar"
|
|
||||||
|
|
||||||
[target.arm-unknown-linux-gnueabihf]
|
[target.x86_64-linux-android]
|
||||||
linker = "arm-linux-gnueabihf-gcc"
|
linker = "x86_64-linux-android30-clang"
|
||||||
ar = "arm-linux-gnueabihf-ar"
|
|
||||||
|
|
||||||
[target.aarch64-unknown-linux-gnu]
|
|
||||||
linker = "aarch64-linux-gnu-gcc"
|
|
||||||
ar = "aarch64-linux-gnu-ar"
|
|
||||||
|
|
||||||
[target.x86_64-pc-windows-msvc]
|
[target.x86_64-pc-windows-msvc]
|
||||||
linker = "lld-link.exe"
|
linker = "lld-link.exe"
|
||||||
|
|
107
.github/workflows/android.yml
vendored
Normal file
107
.github/workflows/android.yml
vendored
Normal file
|
@ -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')
|
||||||
|
|
13
.github/workflows/main.yml
vendored
13
.github/workflows/main.yml
vendored
|
@ -76,7 +76,7 @@ jobs:
|
||||||
|
|
||||||
let platforms = [];
|
let platforms = [];
|
||||||
if (platform == "all") {
|
if (platform == "all") {
|
||||||
platforms = [ "linux", "windows", "macos" ];
|
platforms = [ "linux", "windows", "macos", "android" ];
|
||||||
} else {
|
} else {
|
||||||
platforms = [ platform ];
|
platforms = [ platform ];
|
||||||
}
|
}
|
||||||
|
@ -125,6 +125,15 @@ jobs:
|
||||||
unit-tests: ${{ fromJson(needs.decision.outputs.configuration).unit_tests }}
|
unit-tests: ${{ fromJson(needs.decision.outputs.configuration).unit_tests }}
|
||||||
secrets: inherit
|
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:
|
build-result:
|
||||||
name: Result
|
name: Result
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
@ -135,7 +144,7 @@ jobs:
|
||||||
- "build-win"
|
- "build-win"
|
||||||
- "build-mac"
|
- "build-mac"
|
||||||
- "build-linux"
|
- "build-linux"
|
||||||
|
- "build-android"
|
||||||
steps:
|
steps:
|
||||||
- name: Mark skipped jobs as successful
|
- name: Mark skipped jobs as successful
|
||||||
if: ${{ fromJson(needs.decision.outputs.configuration).platforms[0] != null }}
|
if: ${{ fromJson(needs.decision.outputs.configuration).platforms[0] != null }}
|
||||||
|
|
48
Cargo.lock
generated
48
Cargo.lock
generated
|
@ -128,20 +128,20 @@ checksum = "80b9e34fcbf29c0563547cb2ecce9b49504597cad6166769b1e4efb45c6c2951"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android_log-sys"
|
name = "android_log-sys"
|
||||||
version = "0.2.0"
|
version = "0.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "85965b6739a430150bdd138e2374a98af0c3ee0d030b3bb7fc3bddff58d0102e"
|
checksum = "5ecc8056bf6ab9892dcd53216c83d1597487d7dacac16c8df6b877d127df9937"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "android_logger"
|
name = "android_logger"
|
||||||
version = "0.10.1"
|
version = "0.13.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9ed09b18365ed295d722d0b5ed59c01b79a826ff2d2a8f73d5ecca8e6fb2f66"
|
checksum = "c494134f746c14dc653a35a4ea5aca24ac368529da5370ecf41fe0341c35772f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_log-sys",
|
"android_log-sys",
|
||||||
"env_logger",
|
"env_logger 0.10.1",
|
||||||
"lazy_static",
|
|
||||||
"log",
|
"log",
|
||||||
|
"once_cell",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1604,8 +1604,18 @@ version = "0.8.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
|
checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3"
|
||||||
dependencies = [
|
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",
|
"humantime",
|
||||||
|
"is-terminal",
|
||||||
"log",
|
"log",
|
||||||
"regex",
|
"regex",
|
||||||
"termcolor",
|
"termcolor",
|
||||||
|
@ -2940,6 +2950,17 @@ dependencies = [
|
||||||
"windows",
|
"windows",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[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]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.5"
|
version = "0.10.5"
|
||||||
|
@ -3379,7 +3400,7 @@ dependencies = [
|
||||||
"devtools",
|
"devtools",
|
||||||
"devtools_traits",
|
"devtools_traits",
|
||||||
"embedder_traits",
|
"embedder_traits",
|
||||||
"env_logger",
|
"env_logger 0.10.1",
|
||||||
"euclid",
|
"euclid",
|
||||||
"gaol",
|
"gaol",
|
||||||
"gfx",
|
"gfx",
|
||||||
|
@ -4568,7 +4589,7 @@ version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
|
checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"env_logger",
|
"env_logger 0.8.4",
|
||||||
"log",
|
"log",
|
||||||
"rand",
|
"rand",
|
||||||
]
|
]
|
||||||
|
@ -5379,6 +5400,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"jemalloc-sys",
|
"jemalloc-sys",
|
||||||
"jemallocator",
|
"jemallocator",
|
||||||
|
"libc",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -5592,7 +5614,7 @@ version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"cbindgen",
|
"cbindgen",
|
||||||
"env_logger",
|
"env_logger 0.10.1",
|
||||||
"keyboard-types",
|
"keyboard-types",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -5606,10 +5628,8 @@ dependencies = [
|
||||||
name = "simpleservo_jniapi"
|
name = "simpleservo_jniapi"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"android_injected_glue",
|
|
||||||
"android_logger",
|
"android_logger",
|
||||||
"cc",
|
"cc",
|
||||||
"gstreamer",
|
|
||||||
"jni",
|
"jni",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
|
@ -5906,9 +5926,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "surfman"
|
name = "surfman"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ca39befaf946247c5d3323465a9ec86c4a05523bb87a0d3eb07e71c15181a338"
|
checksum = "db2e4280229411d6eb8a8f873152dece1904df2682003bdc748adc181e003568"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
|
|
|
@ -33,7 +33,7 @@ data-url = "0.1.0"
|
||||||
devtools_traits = { path = "components/shared/devtools" }
|
devtools_traits = { path = "components/shared/devtools" }
|
||||||
embedder_traits = { path = "components/shared/embedder" }
|
embedder_traits = { path = "components/shared/embedder" }
|
||||||
encoding_rs = "0.8"
|
encoding_rs = "0.8"
|
||||||
env_logger = "0.8"
|
env_logger = "0.10"
|
||||||
euclid = "0.22"
|
euclid = "0.22"
|
||||||
fnv = "1.0"
|
fnv = "1.0"
|
||||||
fxhash = "0.2"
|
fxhash = "0.2"
|
||||||
|
|
27
README.md
27
README.md
|
@ -117,6 +117,27 @@ though of course it doesn’t produce a binary you can run.
|
||||||
|
|
||||||
### Building for Android target
|
### 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):
|
For ARM (`armv7-linux-androideabi`, most phones):
|
||||||
|
|
||||||
``` sh
|
``` sh
|
||||||
|
@ -131,6 +152,12 @@ For x86 (typically for the emulator):
|
||||||
./mach package --release --target i686-linux-android
|
./mach package --release --target i686-linux-android
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Install the APK to the device or emulator:
|
||||||
|
|
||||||
|
``` sh
|
||||||
|
./mach install --release --android
|
||||||
|
```
|
||||||
|
|
||||||
## Running
|
## Running
|
||||||
|
|
||||||
Run Servo with the command:
|
Run Servo with the command:
|
||||||
|
|
|
@ -9,9 +9,12 @@ publish = false
|
||||||
[lib]
|
[lib]
|
||||||
path = "lib.rs"
|
path = "lib.rs"
|
||||||
|
|
||||||
[target.'cfg(not(windows))'.dependencies]
|
[target.'cfg(not(any(windows, target_os = "android")))'.dependencies]
|
||||||
jemallocator = { workspace = true }
|
jemallocator = { workspace = true }
|
||||||
jemalloc-sys = { workspace = true }
|
jemalloc-sys = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winapi = { workspace = true, features = ["heapapi"] }
|
winapi = { workspace = true, features = ["heapapi"] }
|
||||||
|
|
||||||
|
[target.'cfg(target_os = "android")'.dependencies]
|
||||||
|
libc = { workspace = true }
|
||||||
|
|
|
@ -9,7 +9,7 @@ static ALLOC: Allocator = Allocator;
|
||||||
|
|
||||||
pub use crate::platform::*;
|
pub use crate::platform::*;
|
||||||
|
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(any(windows, target_os = "android")))]
|
||||||
mod platform {
|
mod platform {
|
||||||
use std::os::raw::c_void;
|
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)]
|
#[cfg(windows)]
|
||||||
mod platform {
|
mod platform {
|
||||||
pub use std::alloc::System as Allocator;
|
pub use std::alloc::System as Allocator;
|
||||||
|
|
|
@ -100,9 +100,9 @@ impl BackgroundHangMonitorRegister for HangMonitorRegister {
|
||||||
not(any(target_arch = "arm", target_arch = "aarch64"))
|
not(any(target_arch = "arm", target_arch = "aarch64"))
|
||||||
))]
|
))]
|
||||||
let sampler = crate::sampler_linux::LinuxSampler::new();
|
let sampler = crate::sampler_linux::LinuxSampler::new();
|
||||||
#[cfg(all(
|
#[cfg(any(
|
||||||
any(target_os = "android", target_os = "linux"),
|
target_os = "android",
|
||||||
any(target_arch = "arm", target_arch = "aarch64")
|
all(target_os = "linux", any(target_arch = "arm", target_arch = "aarch64"))
|
||||||
))]
|
))]
|
||||||
let sampler = crate::sampler::DummySampler::new();
|
let sampler = crate::sampler::DummySampler::new();
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ servo_rand = { path = "../rand" }
|
||||||
uuid = { workspace = true }
|
uuid = { workspace = true }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
|
default = ["bluetooth-test"]
|
||||||
native-bluetooth = ["blurz", "blurdroid", "blurmac", "bluetooth-test"]
|
native-bluetooth = ["blurz", "blurdroid", "blurmac", "bluetooth-test"]
|
||||||
bluetooth-test = ["blurmock"]
|
bluetooth-test = ["blurmock"]
|
||||||
|
|
||||||
|
|
|
@ -501,6 +501,33 @@ impl<Window: WindowMethods + ?Sized> IOCompositor<Window> {
|
||||||
self.shutdown_state = ShutdownState::FinishedShuttingDown;
|
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 {
|
fn handle_browser_message(&mut self, msg: CompositorMsg) -> bool {
|
||||||
match (msg, self.shutdown_state) {
|
match (msg, self.shutdown_state) {
|
||||||
(_, ShutdownState::FinishedShuttingDown) => {
|
(_, ShutdownState::FinishedShuttingDown) => {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use std::time::Duration;
|
||||||
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
use embedder_traits::{EmbedderProxy, EventLoopWaker};
|
||||||
use euclid::Scale;
|
use euclid::Scale;
|
||||||
use keyboard_types::KeyboardEvent;
|
use keyboard_types::KeyboardEvent;
|
||||||
|
use libc::c_void;
|
||||||
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
use msg::constellation_msg::{PipelineId, TopLevelBrowsingContextId, TraversalDirection};
|
||||||
use script_traits::{MediaSessionActionType, MouseButton, TouchEventType, TouchId, WheelDelta};
|
use script_traits::{MediaSessionActionType, MouseButton, TouchEventType, TouchId, WheelDelta};
|
||||||
use servo_geometry::DeviceIndependentPixel;
|
use servo_geometry::DeviceIndependentPixel;
|
||||||
|
@ -105,6 +106,14 @@ pub enum EmbedderEvent {
|
||||||
ChangeBrowserVisibility(TopLevelBrowsingContextId, bool),
|
ChangeBrowserVisibility(TopLevelBrowsingContextId, bool),
|
||||||
/// Virtual keyboard was dismissed
|
/// Virtual keyboard was dismissed
|
||||||
IMEDismissed,
|
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 {
|
impl Debug for EmbedderEvent {
|
||||||
|
@ -139,6 +148,8 @@ impl Debug for EmbedderEvent {
|
||||||
EmbedderEvent::ChangeBrowserVisibility(..) => write!(f, "ChangeBrowserVisibility"),
|
EmbedderEvent::ChangeBrowserVisibility(..) => write!(f, "ChangeBrowserVisibility"),
|
||||||
EmbedderEvent::IMEDismissed => write!(f, "IMEDismissed"),
|
EmbedderEvent::IMEDismissed => write!(f, "IMEDismissed"),
|
||||||
EmbedderEvent::ClearCache => write!(f, "ClearCache"),
|
EmbedderEvent::ClearCache => write!(f, "ClearCache"),
|
||||||
|
EmbedderEvent::InvalidateNativeSurface => write!(f, "InvalidateNativeSurface"),
|
||||||
|
EmbedderEvent::ReplaceNativeSurface(..) => write!(f, "ReplaceNativeSurface"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,12 +4,13 @@
|
||||||
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use log::warn;
|
||||||
use ucd::{Codepoint, UnicodeBlock};
|
use ucd::{Codepoint, UnicodeBlock};
|
||||||
|
|
||||||
use super::xml::{Attribute, Node};
|
use super::xml::{Attribute, Node};
|
||||||
use crate::text::util::is_cjk;
|
use crate::text::util::is_cjk;
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref FONT_LIST: FontList = FontList::new();
|
static ref FONT_LIST: FontList = FontList::new();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,6 +23,6 @@ task_info = { path = "../../support/rust-task_info" }
|
||||||
[target.'cfg(target_os = "linux")'.dependencies]
|
[target.'cfg(target_os = "linux")'.dependencies]
|
||||||
regex = { workspace = true }
|
regex = { workspace = true }
|
||||||
|
|
||||||
[target.'cfg(not(target_os = "windows"))'.dependencies]
|
[target.'cfg(not(any(target_os = "windows", target_os = "android")))'.dependencies]
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
jemalloc-sys = { workspace = true }
|
jemalloc-sys = { workspace = true }
|
||||||
|
|
|
@ -387,16 +387,16 @@ impl ReportsForest {
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
|
||||||
mod system_reporter {
|
mod system_reporter {
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(any(target_os = "windows", target_os = "android")))]
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(any(target_os = "windows", target_os = "android")))]
|
||||||
use std::mem::size_of;
|
use std::mem::size_of;
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(any(target_os = "windows", target_os = "android")))]
|
||||||
use std::ptr::null_mut;
|
use std::ptr::null_mut;
|
||||||
|
|
||||||
#[cfg(target_os = "linux")]
|
#[cfg(target_os = "linux")]
|
||||||
use libc::c_int;
|
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 libc::{c_void, size_t};
|
||||||
use profile_traits::mem::{Report, ReportKind, ReporterRequest};
|
use profile_traits::mem::{Report, ReportKind, ReporterRequest};
|
||||||
use profile_traits::path;
|
use profile_traits::path;
|
||||||
|
@ -499,10 +499,10 @@ mod system_reporter {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(any(target_os = "windows", target_os = "android")))]
|
||||||
use jemalloc_sys::mallctl;
|
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> {
|
fn jemalloc_stat(value_name: &str) -> Option<usize> {
|
||||||
// Before we request the measurement of interest, we first send an "epoch"
|
// Before we request the measurement of interest, we first send an "epoch"
|
||||||
// request. Without that jemalloc gives cached statistics(!) which can be
|
// request. Without that jemalloc gives cached statistics(!) which can be
|
||||||
|
@ -549,7 +549,7 @@ mod system_reporter {
|
||||||
Some(value as usize)
|
Some(value as usize)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(any(target_os = "windows", target_os = "android"))]
|
||||||
fn jemalloc_stat(_value_name: &str) -> Option<usize> {
|
fn jemalloc_stat(_value_name: &str) -> Option<usize> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -503,7 +503,14 @@ where
|
||||||
EmbedderEvent::Resize => {
|
EmbedderEvent::Resize => {
|
||||||
return self.compositor.on_resize_window_event();
|
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) => {
|
EmbedderEvent::AllowNavigationResponse(pipeline_id, allowed) => {
|
||||||
let msg = ConstellationMsg::AllowNavigationResponse(pipeline_id, allowed);
|
let msg = ConstellationMsg::AllowNavigationResponse(pipeline_id, allowed);
|
||||||
if let Err(e) = self.constellation_chan.send(msg) {
|
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 =
|
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";
|
"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 {
|
match agent {
|
||||||
UserAgent::Desktop => DESKTOP_UA_STRING,
|
UserAgent::Desktop => DESKTOP_UA_STRING,
|
||||||
UserAgent::Android => "Mozilla/5.0 (Android; Mobile; rv:109.0) Servo/1.0 Firefox/111.0",
|
UserAgent::Android => "Mozilla/5.0 (Android; Mobile; rv:109.0) Servo/1.0 Firefox/111.0",
|
||||||
|
|
|
@ -216,4 +216,28 @@ impl WebrenderSurfman {
|
||||||
let ref context = self.0.context.borrow();
|
let ref context = self.0.context.borrow();
|
||||||
device.get_proc_address(context, name)
|
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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,8 +79,8 @@ def main(avd_name, apk_path, *args):
|
||||||
|
|
||||||
|
|
||||||
def tool_path(directory, bin_name):
|
def tool_path(directory, bin_name):
|
||||||
if "ANDROID_SDK" in os.environ:
|
if "ANDROID_SDK_ROOT" in os.environ:
|
||||||
path = os.path.join(os.environ["ANDROID_SDK"], directory, bin_name)
|
path = os.path.join(os.environ["ANDROID_SDK_ROOT"], directory, bin_name)
|
||||||
if os.path.exists(path):
|
if os.path.exists(path):
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,10 @@ with import (builtins.fetchTarball {
|
||||||
url = "https://github.com/oxalica/rust-overlay/archive/a0df72e106322b67e9c6e591fe870380bd0da0d5.tar.gz";
|
url = "https://github.com/oxalica/rust-overlay/archive/a0df72e106322b67e9c6e591fe870380bd0da0d5.tar.gz";
|
||||||
}))
|
}))
|
||||||
];
|
];
|
||||||
|
config = {
|
||||||
|
android_sdk.accept_license = true;
|
||||||
|
allowUnfree = true;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
let
|
let
|
||||||
rustToolchain = rust-bin.fromRustupToolchainFile ../rust-toolchain.toml;
|
rustToolchain = rust-bin.fromRustupToolchainFile ../rust-toolchain.toml;
|
||||||
|
@ -27,6 +31,25 @@ let
|
||||||
# - glibc 2.38 (#31054)
|
# - glibc 2.38 (#31054)
|
||||||
llvmPackages = llvmPackages_14;
|
llvmPackages = llvmPackages_14;
|
||||||
stdenv = llvmPackages.stdenv;
|
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
|
in
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
name = "servo-env";
|
name = "servo-env";
|
||||||
|
@ -111,22 +134,33 @@ stdenv.mkDerivation rec {
|
||||||
|
|
||||||
RUSTC_BOOTSTRAP = "crown";
|
RUSTC_BOOTSTRAP = "crown";
|
||||||
}))
|
}))
|
||||||
|
|
||||||
|
# for android builds
|
||||||
|
# TODO: make this optional
|
||||||
|
openjdk17_headless
|
||||||
|
androidSdk
|
||||||
] ++ (lib.optionals stdenv.isDarwin [
|
] ++ (lib.optionals stdenv.isDarwin [
|
||||||
darwin.apple_sdk.frameworks.AppKit
|
darwin.apple_sdk.frameworks.AppKit
|
||||||
]);
|
]);
|
||||||
|
|
||||||
LIBCLANG_PATH = llvmPackages.clang-unwrapped.lib + "/lib/";
|
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
|
# Allow cargo to download crates
|
||||||
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
|
SSL_CERT_FILE = "${cacert}/etc/ssl/certs/ca-bundle.crt";
|
||||||
|
|
||||||
# Enable colored cargo and rustc output
|
# Enable colored cargo and rustc output
|
||||||
TERMINFO = "${ncurses.out}/share/terminfo";
|
TERMINFO = "${ncurses.out}/share/terminfo";
|
||||||
|
|
||||||
|
|
||||||
# Provide libraries that aren’t linked against but somehow required
|
# Provide libraries that aren’t linked against but somehow required
|
||||||
LD_LIBRARY_PATH = lib.makeLibraryPath [
|
LD_LIBRARY_PATH = lib.makeLibraryPath [
|
||||||
# Fixes missing library errors
|
# 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")
|
# [WARN script::dom::gpu] Could not get GPUAdapter ("NotFound")
|
||||||
# TLA Err: Error: Couldn't request WebGPU adapter.
|
# TLA Err: Error: Couldn't request WebGPU adapter.
|
||||||
|
|
|
@ -18,6 +18,7 @@ use servo::compositing::windowing::{
|
||||||
AnimationState, EmbedderCoordinates, EmbedderEvent, EmbedderMethods, MouseWindowEvent,
|
AnimationState, EmbedderCoordinates, EmbedderEvent, EmbedderMethods, MouseWindowEvent,
|
||||||
WindowMethods,
|
WindowMethods,
|
||||||
};
|
};
|
||||||
|
use servo::compositing::CompositeTarget;
|
||||||
use servo::config::prefs::pref_map;
|
use servo::config::prefs::pref_map;
|
||||||
pub use servo::config::prefs::{add_user_prefs, PrefValue};
|
pub use servo::config::prefs::{add_user_prefs, PrefValue};
|
||||||
use servo::embedder_traits::resources::{self, Resource, ResourceReaderMethods};
|
use servo::embedder_traits::resources::{self, Resource, ResourceReaderMethods};
|
||||||
|
@ -298,7 +299,12 @@ pub fn init(
|
||||||
gl: gl.clone(),
|
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| {
|
SERVO.with(|s| {
|
||||||
let mut servo_glue = ServoGlue {
|
let mut servo_glue = ServoGlue {
|
||||||
|
@ -569,6 +575,24 @@ impl ServoGlue {
|
||||||
self.process_event(EmbedderEvent::Keyboard(key_event))
|
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(
|
pub fn media_session_action(
|
||||||
&mut self,
|
&mut self,
|
||||||
action: MediaSessionActionType,
|
action: MediaSessionActionType,
|
||||||
|
@ -789,6 +813,9 @@ impl ServoGlue {
|
||||||
EmbedderMsg::Panic(reason, backtrace) => {
|
EmbedderMsg::Panic(reason, backtrace) => {
|
||||||
self.callbacks.host_callbacks.on_panic(reason, backtrace);
|
self.callbacks.host_callbacks.on_panic(reason, backtrace);
|
||||||
},
|
},
|
||||||
|
EmbedderMsg::ReadyToPresent => {
|
||||||
|
self.servo.present();
|
||||||
|
},
|
||||||
EmbedderMsg::Status(..) |
|
EmbedderMsg::Status(..) |
|
||||||
EmbedderMsg::SelectFiles(..) |
|
EmbedderMsg::SelectFiles(..) |
|
||||||
EmbedderMsg::MoveTo(..) |
|
EmbedderMsg::MoveTo(..) |
|
||||||
|
@ -798,7 +825,6 @@ impl ServoGlue {
|
||||||
EmbedderMsg::NewFavicon(..) |
|
EmbedderMsg::NewFavicon(..) |
|
||||||
EmbedderMsg::HeadParsed |
|
EmbedderMsg::HeadParsed |
|
||||||
EmbedderMsg::SetFullscreenState(..) |
|
EmbedderMsg::SetFullscreenState(..) |
|
||||||
EmbedderMsg::ReadyToPresent |
|
|
||||||
EmbedderMsg::ReportProfile(..) |
|
EmbedderMsg::ReportProfile(..) |
|
||||||
EmbedderMsg::EventDelivered(..) => {},
|
EmbedderMsg::EventDelivered(..) => {},
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
[package]
|
[package]
|
||||||
name = "simpleservo_jniapi"
|
name = "simpleservo_jniapi"
|
||||||
version = "0.0.1"
|
version = "0.0.1"
|
||||||
build = "build.rs"
|
|
||||||
authors = ["The Servo Project Developers"]
|
authors = ["The Servo Project Developers"]
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
@ -14,21 +13,21 @@ test = false
|
||||||
bench = false
|
bench = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
android_injected_glue = "0.2"
|
android_logger = "0.13"
|
||||||
android_logger = "0.10"
|
|
||||||
gstreamer = { workspace = true }
|
|
||||||
jni = "0.18.0"
|
jni = "0.18.0"
|
||||||
libc = { workspace = true }
|
libc = { workspace = true }
|
||||||
log = { workspace = true }
|
log = { workspace = true }
|
||||||
serde_json = { 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]
|
[build-dependencies]
|
||||||
cc = "1.0"
|
cc = "1.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
debugmozjs = ["simpleservo/debugmozjs"]
|
debugmozjs = ["simpleservo/debugmozjs"]
|
||||||
default = ["max_log_level", "native-bluetooth", "webdriver"]
|
default = ["max_log_level", "webdriver", "no_static_freetype"]
|
||||||
googlevr = ["simpleservo/googlevr"]
|
googlevr = ["simpleservo/googlevr"]
|
||||||
js_backtrace = ["simpleservo/js_backtrace"]
|
js_backtrace = ["simpleservo/js_backtrace"]
|
||||||
max_log_level = ["simpleservo/max_log_level"]
|
max_log_level = ["simpleservo/max_log_level"]
|
||||||
|
@ -36,3 +35,4 @@ media-gstreamer = ["simpleservo/media-gstreamer"]
|
||||||
native-bluetooth = ["simpleservo/native-bluetooth"]
|
native-bluetooth = ["simpleservo/native-bluetooth"]
|
||||||
webdriver = ["simpleservo/webdriver"]
|
webdriver = ["simpleservo/webdriver"]
|
||||||
webgl_backtrace = ["simpleservo/webgl_backtrace"]
|
webgl_backtrace = ["simpleservo/webgl_backtrace"]
|
||||||
|
no_static_freetype = ["simpleservo/no_static_freetype"]
|
||||||
|
|
|
@ -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");
|
|
||||||
}
|
|
|
@ -5,21 +5,18 @@
|
||||||
#![allow(non_snake_case)]
|
#![allow(non_snake_case)]
|
||||||
|
|
||||||
use std::os::raw::{c_char, c_int, c_void};
|
use std::os::raw::{c_char, c_int, c_void};
|
||||||
use std::ptr::{null, null_mut};
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::thread;
|
use std::thread;
|
||||||
|
|
||||||
use android_logger::{self, Filter};
|
use android_logger::{self, Config, FilterBuilder};
|
||||||
use gstreamer::debug_set_threshold_from_string;
|
|
||||||
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
|
use jni::objects::{GlobalRef, JClass, JObject, JString, JValue};
|
||||||
use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE};
|
use jni::sys::{jboolean, jfloat, jint, jstring, JNI_TRUE};
|
||||||
use jni::{errors, JNIEnv, JavaVM};
|
use jni::{JNIEnv, JavaVM};
|
||||||
use libc::{dup2, pipe, read};
|
use libc::{dup2, pipe, read};
|
||||||
use log::Level;
|
use log::{debug, error, info, warn};
|
||||||
use simpleservo::{
|
use simpleservo::{
|
||||||
self, self, deinit, gl_glue, gl_glue, Coordinates, DeviceIntRect, EventLoopWaker, HostTrait,
|
self, gl_glue, Coordinates, DeviceIntRect, EventLoopWaker, HostTrait, InitOptions,
|
||||||
InitOptions, InputMethodType, MediaSessionPlaybackState, MouseButton, PromptResult, ServoGlue,
|
InputMethodType, MediaSessionPlaybackState, PromptResult, ServoGlue, SERVO,
|
||||||
ServoGlue, VRInitOptions, SERVO, SERVO,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct HostCallbacks {
|
struct HostCallbacks {
|
||||||
|
@ -27,6 +24,19 @@ struct HostCallbacks {
|
||||||
jvm: JavaVM,
|
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)
|
fn call<F>(env: &JNIEnv, f: F)
|
||||||
where
|
where
|
||||||
F: Fn(&mut ServoGlue) -> Result<(), &str>,
|
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(
|
pub fn Java_org_mozilla_servoview_JNIServo_init(
|
||||||
env: JNIEnv,
|
env: JNIEnv,
|
||||||
_: JClass,
|
_: JClass,
|
||||||
activity: JObject,
|
_activity: JObject,
|
||||||
opts: JObject,
|
opts: JObject,
|
||||||
callbacks_obj: 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),
|
Ok((opts, log, log_str, gst_debug_str)) => (opts, log, log_str, gst_debug_str),
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
throw(&env, &err);
|
throw(&env, &err);
|
||||||
|
@ -79,26 +90,26 @@ pub fn Java_org_mozilla_servoview_JNIServo_init(
|
||||||
"compositing::compositor",
|
"compositing::compositor",
|
||||||
"constellation::constellation",
|
"constellation::constellation",
|
||||||
];
|
];
|
||||||
let mut filter = Filter::default().with_min_level(Level::Debug);
|
let mut filter_builder = FilterBuilder::new();
|
||||||
for &module in &filters {
|
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 {
|
if let Some(log_str) = log_str {
|
||||||
for module in log_str.split(',') {
|
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 {
|
android_logger::init_once(
|
||||||
debug_set_threshold_from_string(&gst_debug_str, true);
|
Config::default()
|
||||||
}
|
.with_max_level(log::LevelFilter::Debug)
|
||||||
|
.with_filter(filter_builder.build())
|
||||||
android_logger::init_once(filter, Some("simpleservo"));
|
.with_tag("simpleservo"),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
info!("init");
|
info!("init");
|
||||||
|
|
||||||
initialize_android_glue(&env, activity);
|
|
||||||
redirect_stdout_to_logcat();
|
redirect_stdout_to_logcat();
|
||||||
|
|
||||||
let callbacks_ref = match env.new_global_ref(callbacks_obj) {
|
let callbacks_ref = match env.new_global_ref(callbacks_obj) {
|
||||||
|
@ -329,11 +340,33 @@ pub fn Java_org_mozilla_servoview_JNIServo_pinchZoomEnd(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[no_mangle]
|
#[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");
|
debug!("click");
|
||||||
call(&env, |s| s.click(x as f32, y as f32));
|
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]
|
#[no_mangle]
|
||||||
pub fn Java_org_mozilla_servoview_JNIServo_mediaSessionAction(
|
pub fn Java_org_mozilla_servoview_JNIServo_mediaSessionAction(
|
||||||
env: JNIEnv,
|
env: JNIEnv,
|
||||||
|
@ -379,20 +412,6 @@ impl HostCallbacks {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HostTrait for 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) {
|
fn prompt_alert(&self, message: String, _trusted: bool) {
|
||||||
debug!("prompt_alert");
|
debug!("prompt_alert");
|
||||||
let env = self.jvm.get_env().unwrap();
|
let env = self.jvm.get_env().unwrap();
|
||||||
|
@ -446,9 +465,10 @@ impl HostTrait for HostCallbacks {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_title_changed(&self, title: String) {
|
fn on_title_changed(&self, title: Option<String>) {
|
||||||
debug!("on_title_changed");
|
debug!("on_title_changed");
|
||||||
let env = self.jvm.get_env().unwrap();
|
let env = self.jvm.get_env().unwrap();
|
||||||
|
let title = title.unwrap_or_else(String::new);
|
||||||
let s = match new_string(&env, &title) {
|
let s = match new_string(&env, &title) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => return,
|
Err(_) => return,
|
||||||
|
@ -529,7 +549,7 @@ impl HostTrait for HostCallbacks {
|
||||||
|
|
||||||
fn on_ime_show(
|
fn on_ime_show(
|
||||||
&self,
|
&self,
|
||||||
_type: InputEncoding,
|
_input_type: InputMethodType,
|
||||||
_text: Option<(String, i32)>,
|
_text: Option<(String, i32)>,
|
||||||
_multiline: bool,
|
_multiline: bool,
|
||||||
_rect: DeviceIntRect,
|
_rect: DeviceIntRect,
|
||||||
|
@ -610,65 +630,16 @@ impl HostTrait for HostCallbacks {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn on_devtools_started(&self, port: Result<u16, ()>) {
|
fn on_devtools_started(&self, port: Result<u16, ()>, _token: String) {
|
||||||
match port {
|
match port {
|
||||||
Ok(p) => info!("Devtools Server running on port {}", p),
|
Ok(p) => info!("Devtools Server running on port {}", p),
|
||||||
Err(()) => error!("Error running devtools server"),
|
Err(()) => error!("Error running devtools server"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fn initialize_android_glue(env: &JNIEnv, activity: JObject) {
|
fn show_context_menu(&self, _title: Option<String>, _items: Vec<String>) {}
|
||||||
use android_injected_glue::{ffi, ANDROID_APP};
|
|
||||||
|
|
||||||
// From jni-rs to android_injected_glue
|
fn on_panic(&self, _reason: String, _backtrace: Option<String>) {}
|
||||||
|
|
||||||
let clazz = Box::leak(Box::new(env.new_global_ref(activity).unwrap()));
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -803,28 +774,21 @@ fn jni_coords_to_rust_coords(env: &JNIEnv, obj: JObject) -> Result<Coordinates,
|
||||||
|
|
||||||
fn get_field<'a>(
|
fn get_field<'a>(
|
||||||
env: &'a JNIEnv,
|
env: &'a JNIEnv,
|
||||||
obj: JObject,
|
obj: JObject<'a>,
|
||||||
field: &str,
|
field: &str,
|
||||||
type_: &str,
|
type_: &str,
|
||||||
) -> Result<Option<JValue<'a>>, String> {
|
) -> Result<Option<JValue<'a>>, String> {
|
||||||
if env.get_field_id(obj, field, type_).is_err() {
|
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_)
|
env.get_field(obj, field, type_)
|
||||||
.map(|value| Some(value))
|
.map(|value| Some(value))
|
||||||
.or_else(|e| match *e.kind() {
|
.or_else(|_| Err(format!("Can't find `{}` field", field)))
|
||||||
errors::ErrorKind::NullPtr(_) => Ok(None),
|
|
||||||
_ => Err(format!(
|
|
||||||
"Can't find `{}` field: {}",
|
|
||||||
&field,
|
|
||||||
e.description()
|
|
||||||
)),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_non_null_field<'a>(
|
fn get_non_null_field<'a>(
|
||||||
env: &'a JNIEnv,
|
env: &'a JNIEnv,
|
||||||
obj: JObject,
|
obj: JObject<'a>,
|
||||||
field: &str,
|
field: &str,
|
||||||
type_: &str,
|
type_: &str,
|
||||||
) -> Result<JValue<'a>, String> {
|
) -> Result<JValue<'a>, String> {
|
||||||
|
@ -851,6 +815,7 @@ fn get_string(env: &JNIEnv, obj: JObject, field: &str) -> Result<Option<String>,
|
||||||
fn get_options(
|
fn get_options(
|
||||||
env: &JNIEnv,
|
env: &JNIEnv,
|
||||||
opts: JObject,
|
opts: JObject,
|
||||||
|
surface: JObject,
|
||||||
) -> Result<(InitOptions, bool, Option<String>, Option<String>), String> {
|
) -> Result<(InitOptions, bool, Option<String>, Option<String>), String> {
|
||||||
let args = get_string(env, opts, "args")?;
|
let args = get_string(env, opts, "args")?;
|
||||||
let url = get_string(env, opts, "url")?;
|
let url = get_string(env, opts, "url")?;
|
||||||
|
@ -862,13 +827,6 @@ fn get_options(
|
||||||
let log = get_non_null_field(env, opts, "enableLogs", "Z")?
|
let log = get_non_null_field(env, opts, "enableLogs", "Z")?
|
||||||
.z()
|
.z()
|
||||||
.map_err(|_| "enableLogs not a boolean")?;
|
.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(
|
let coordinates = get_non_null_field(
|
||||||
env,
|
env,
|
||||||
opts,
|
opts,
|
||||||
|
@ -885,20 +843,16 @@ fn get_options(
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let native_window = unsafe { ANativeWindow_fromSurface(env.get_native_interface(), surface) };
|
||||||
let opts = InitOptions {
|
let opts = InitOptions {
|
||||||
args: args.unwrap_or(vec![]),
|
args: args.unwrap_or(vec![]),
|
||||||
url,
|
|
||||||
coordinates,
|
coordinates,
|
||||||
density,
|
density,
|
||||||
enable_subpixel_text_antialiasing,
|
|
||||||
vr_init: if vr_pointer.is_null() {
|
|
||||||
VRInitOptions::None
|
|
||||||
} else {
|
|
||||||
VRInitOptions::VRExternal(vr_pointer)
|
|
||||||
},
|
|
||||||
xr_discovery: None,
|
xr_discovery: None,
|
||||||
gl_context_pointer: None,
|
gl_context_pointer: None,
|
||||||
native_display_pointer: None,
|
native_display_pointer: None,
|
||||||
|
surfman_integration: simpleservo::SurfmanIntegration::Widget(native_window),
|
||||||
|
prefs: None,
|
||||||
};
|
};
|
||||||
Ok((opts, log, log_str, gst_debug_str))
|
Ok((opts, log, log_str, gst_debug_str))
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,6 @@ import glob
|
||||||
import json
|
import json
|
||||||
import os
|
import os
|
||||||
import os.path as path
|
import os.path as path
|
||||||
import platform
|
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
|
@ -30,7 +29,7 @@ from mach.decorators import (
|
||||||
import servo.platform
|
import servo.platform
|
||||||
|
|
||||||
from servo.command_base import CommandBase, cd, check_call
|
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
|
@CommandProvider
|
||||||
|
@ -66,150 +65,6 @@ class MachCommands(CommandBase):
|
||||||
return 1
|
return 1
|
||||||
return 0
|
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',
|
@Command('update-hsts-preload',
|
||||||
description='Download the HSTS preload list',
|
description='Download the HSTS preload list',
|
||||||
category='bootstrap')
|
category='bootstrap')
|
||||||
|
|
|
@ -98,7 +98,6 @@ class MachCommands(CommandBase):
|
||||||
for key in env:
|
for key in env:
|
||||||
print((key, env[key]))
|
print((key, env[key]))
|
||||||
|
|
||||||
self.download_and_build_android_dependencies_if_needed(env)
|
|
||||||
status = self.run_cargo_build_like_command(
|
status = self.run_cargo_build_like_command(
|
||||||
"build", opts, env=env, verbose=verbose,
|
"build", opts, env=env, verbose=verbose,
|
||||||
libsimpleservo=libsimpleservo, **kwargs
|
libsimpleservo=libsimpleservo, **kwargs
|
||||||
|
|
|
@ -334,7 +334,7 @@ class CommandBase(object):
|
||||||
def get_binary_path(self, build_type: BuildType, target=None, android=False, simpleservo=False):
|
def get_binary_path(self, build_type: BuildType, target=None, android=False, simpleservo=False):
|
||||||
base_path = util.get_target_dir()
|
base_path = util.get_target_dir()
|
||||||
if android:
|
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
|
simpleservo = True
|
||||||
elif target:
|
elif target:
|
||||||
base_path = path.join(base_path, target)
|
base_path = path.join(base_path, target)
|
||||||
|
@ -529,58 +529,38 @@ class CommandBase(object):
|
||||||
|
|
||||||
# Paths to Android build tools:
|
# Paths to Android build tools:
|
||||||
if self.config["android"]["sdk"]:
|
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"]:
|
if self.config["android"]["ndk"]:
|
||||||
env["ANDROID_NDK"] = self.config["android"]["ndk"]
|
env["ANDROID_NDK_ROOT"] = 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"]
|
|
||||||
|
|
||||||
toolchains = path.join(self.context.topdir, "android-toolchains")
|
toolchains = path.join(self.context.topdir, "android-toolchains")
|
||||||
for kind in ["sdk", "ndk"]:
|
for kind in ["sdk", "ndk"]:
|
||||||
default = os.path.join(toolchains, kind)
|
default = os.path.join(toolchains, kind)
|
||||||
if os.path.isdir(default):
|
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 "ANDROID_NDK_ROOT" not in env:
|
||||||
if os.path.isdir(tools):
|
print("Please set the ANDROID_NDK_ROOT environment variable.")
|
||||||
env["PATH"] = "%s%s%s" % (tools, os.pathsep, env["PATH"])
|
|
||||||
|
|
||||||
if "ANDROID_NDK" not in env:
|
|
||||||
print("Please set the ANDROID_NDK environment variable.")
|
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
if "ANDROID_SDK" not in env:
|
if "ANDROID_SDK_ROOT" not in env:
|
||||||
print("Please set the ANDROID_SDK environment variable.")
|
print("Please set the ANDROID_SDK_ROOT environment variable.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
android_platform = self.config["android"]["platform"]
|
android_platform = self.config["android"]["platform"]
|
||||||
android_toolchain_name = self.config["android"]["toolchain_name"]
|
android_toolchain_name = self.config["android"]["toolchain_name"]
|
||||||
android_toolchain_prefix = self.config["android"]["toolchain_prefix"]
|
|
||||||
android_lib = self.config["android"]["lib"]
|
android_lib = self.config["android"]["lib"]
|
||||||
android_arch = self.config["android"]["arch"]
|
|
||||||
|
|
||||||
# Check if the NDK version is 15
|
android_api = android_platform.replace('android-', '')
|
||||||
if not os.path.isfile(path.join(env["ANDROID_NDK"], 'source.properties')):
|
|
||||||
|
# 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("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)
|
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()
|
lines = ndk_properties.readlines()
|
||||||
if lines[1].split(' = ')[1].split('.')[0] != '15':
|
if lines[1].split(' = ')[1].split('.')[0] != '25':
|
||||||
print("Currently only support NDK 15. Please re-run `./mach bootstrap-android`.")
|
print("Servo currently only supports NDK r25c.")
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# Android builds also require having the gcc bits on the PATH and various INCLUDE
|
# 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_suffix = "x86_64"
|
||||||
host = os_type + "-" + host_suffix
|
host = os_type + "-" + host_suffix
|
||||||
|
|
||||||
host_cc = env.get('HOST_CC') or shutil.which(["clang"]) or util.whichget_exec_path(["gcc"])
|
host_cc = env.get('HOST_CC') or shutil.which("clang")
|
||||||
host_cxx = env.get('HOST_CXX') or util.whichget_exec_path(["clang++"]) or util.whichget_exec_path(["g++"])
|
host_cxx = env.get('HOST_CXX') or shutil.which("clang++")
|
||||||
|
|
||||||
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")
|
|
||||||
|
|
||||||
|
llvm_toolchain = path.join(env['ANDROID_NDK_ROOT'], "toolchains", "llvm", "prebuilt", host)
|
||||||
env['PATH'] = (path.join(llvm_toolchain, "bin") + ':' + env['PATH'])
|
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")
|
def to_ndk_bin(prog):
|
||||||
cpufeatures_include = path.join(env['ANDROID_NDK'], "sources", "android", "cpufeatures")
|
return path.join(llvm_toolchain, "bin", prog)
|
||||||
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-', '')
|
|
||||||
|
|
||||||
env["RUST_TARGET"] = self.cross_compile_target
|
env["RUST_TARGET"] = self.cross_compile_target
|
||||||
env['HOST_CC'] = host_cc
|
env['HOST_CC'] = host_cc
|
||||||
env['HOST_CXX'] = host_cxx
|
env['HOST_CXX'] = host_cxx
|
||||||
env['HOST_CFLAGS'] = ''
|
env['HOST_CFLAGS'] = ''
|
||||||
env['HOST_CXXFLAGS'] = ''
|
env['HOST_CXXFLAGS'] = ''
|
||||||
env['CC'] = path.join(llvm_toolchain, "bin", "clang")
|
env['CC'] = to_ndk_bin("clang")
|
||||||
env['CPP'] = path.join(llvm_toolchain, "bin", "clang") + " -E"
|
env['CPP'] = to_ndk_bin("clang") + " -E"
|
||||||
env['CXX'] = path.join(llvm_toolchain, "bin", "clang++")
|
env['CXX'] = to_ndk_bin("clang++")
|
||||||
env['ANDROID_TOOLCHAIN'] = gcc_toolchain
|
|
||||||
env['ANDROID_TOOLCHAIN_DIR'] = gcc_toolchain
|
env['AR'] = to_ndk_bin("llvm-ar")
|
||||||
env['ANDROID_VERSION'] = android_api
|
env['RANLIB'] = to_ndk_bin("llvm-ranlib")
|
||||||
env['ANDROID_PLATFORM_DIR'] = android_platform_dir
|
env['OBJCOPY'] = to_ndk_bin("llvm-objcopy")
|
||||||
env['GCC_TOOLCHAIN'] = gcc_toolchain
|
env['YASM'] = to_ndk_bin("yasm")
|
||||||
gcc_toolchain_bin = path.join(gcc_toolchain, android_toolchain_name, "bin")
|
env['STRIP'] = to_ndk_bin("llvm-strip")
|
||||||
env['AR'] = path.join(gcc_toolchain_bin, "ar")
|
env['HARFBUZZ_SYS_NO_PKG_CONFIG'] = "true"
|
||||||
env['RANLIB'] = path.join(gcc_toolchain_bin, "ranlib")
|
env['RUST_FONTCONFIG_DLOPEN'] = "on"
|
||||||
env['OBJCOPY'] = path.join(gcc_toolchain_bin, "objcopy")
|
|
||||||
env['YASM'] = path.join(env['ANDROID_NDK'], 'prebuilt', host, 'bin', 'yasm')
|
env["LIBCLANG_PATH"] = path.join(llvm_toolchain, "lib64")
|
||||||
# A cheat-sheet for some of the build errors caused by getting the search path wrong...
|
# A cheat-sheet for some of the build errors caused by getting the search path wrong...
|
||||||
#
|
#
|
||||||
# fatal error: 'limits' file not found
|
# fatal error: 'limits' file not found
|
||||||
|
@ -651,52 +616,28 @@ class CommandBase(object):
|
||||||
#
|
#
|
||||||
# Also worth remembering: autoconf uses C for its configuration,
|
# 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.
|
# even for C++ builds, so the C flags need to line up with the C++ flags.
|
||||||
env['CFLAGS'] = ' '.join([
|
env['CFLAGS'] = "--target=" + android_toolchain_name
|
||||||
"--target=" + self.cross_compile_target,
|
env['CXXFLAGS'] = "--target=" + android_toolchain_name
|
||||||
"--sysroot=" + env['ANDROID_SYSROOT'],
|
|
||||||
"--gcc-toolchain=" + gcc_toolchain,
|
# These two variables are needed for the mozjs compilation.
|
||||||
"-isystem", sysroot_include,
|
env['ANDROID_API_LEVEL'] = android_api
|
||||||
"-I" + arch_include,
|
env["ANDROID_NDK_HOME"] = env["ANDROID_NDK_ROOT"]
|
||||||
"-B" + arch_libs,
|
|
||||||
"-L" + arch_libs,
|
# The two variables set below are passed by our custom
|
||||||
"-D__ANDROID_API__=" + android_api,
|
# support/android/toolchain.cmake to the NDK's CMake toolchain file
|
||||||
])
|
|
||||||
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["ANDROID_ABI"] = android_lib
|
env["ANDROID_ABI"] = android_lib
|
||||||
env["ANDROID_PLATFORM"] = android_platform
|
env["ANDROID_PLATFORM"] = android_platform
|
||||||
env["NDK_CMAKE_TOOLCHAIN_FILE"] = path.join(env['ANDROID_NDK'], "build", "cmake", "android.toolchain.cmake")
|
env["NDK_CMAKE_TOOLCHAIN_FILE"] = path.join(
|
||||||
env["CMAKE_TOOLCHAIN_FILE"] = path.join(self.android_support_dir(), "toolchain.cmake")
|
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
|
# 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']):
|
if not os.path.exists(env['AAR_OUT_DIR']):
|
||||||
os.makedirs(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
|
@staticmethod
|
||||||
def common_command_arguments(build_configuration=False, build_type=False):
|
def common_command_arguments(build_configuration=False, build_type=False):
|
||||||
|
@ -863,11 +804,7 @@ class CommandBase(object):
|
||||||
if self.config["build"]["media-stack"] != "auto":
|
if self.config["build"]["media-stack"] != "auto":
|
||||||
media_stack = self.config["build"]["media-stack"]
|
media_stack = self.config["build"]["media-stack"]
|
||||||
assert media_stack
|
assert media_stack
|
||||||
elif (
|
elif not self.cross_compile_target:
|
||||||
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
|
|
||||||
):
|
|
||||||
media_stack = "gstreamer"
|
media_stack = "gstreamer"
|
||||||
else:
|
else:
|
||||||
media_stack = "dummy"
|
media_stack = "dummy"
|
||||||
|
@ -943,22 +880,16 @@ class CommandBase(object):
|
||||||
|
|
||||||
return call(["cargo", command] + args + cargo_args, env=env, verbose=verbose)
|
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):
|
def android_adb_path(self, env):
|
||||||
if "ANDROID_SDK" in env:
|
if "ANDROID_SDK_ROOT" in env:
|
||||||
sdk_adb = path.join(env["ANDROID_SDK"], "platform-tools", "adb")
|
sdk_adb = path.join(env["ANDROID_SDK_ROOT"], "platform-tools", "adb")
|
||||||
if path.exists(sdk_adb):
|
if path.exists(sdk_adb):
|
||||||
return sdk_adb
|
return sdk_adb
|
||||||
return "adb"
|
return "adb"
|
||||||
|
|
||||||
def android_emulator_path(self, env):
|
def android_emulator_path(self, env):
|
||||||
if "ANDROID_SDK" in env:
|
if "ANDROID_SDK_ROOT" in env:
|
||||||
sdk_adb = path.join(env["ANDROID_SDK"], "emulator", "emulator")
|
sdk_adb = path.join(env["ANDROID_SDK_ROOT"], "emulator", "emulator")
|
||||||
if path.exists(sdk_adb):
|
if path.exists(sdk_adb):
|
||||||
return sdk_adb
|
return sdk_adb
|
||||||
return "emulator"
|
return "emulator"
|
||||||
|
@ -968,29 +899,29 @@ class CommandBase(object):
|
||||||
build by writing the appropriate toolchain configuration values
|
build by writing the appropriate toolchain configuration values
|
||||||
into the stored configuration."""
|
into the stored configuration."""
|
||||||
if target == "armv7-linux-androideabi":
|
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"]["target"] = target
|
||||||
self.config["android"]["toolchain_prefix"] = "arm-linux-androideabi"
|
self.config["android"]["toolchain_prefix"] = "arm-linux-androideabi"
|
||||||
self.config["android"]["arch"] = "arm"
|
self.config["android"]["arch"] = "arm"
|
||||||
self.config["android"]["lib"] = "armeabi-v7a"
|
self.config["android"]["lib"] = "armeabi-v7a"
|
||||||
self.config["android"]["toolchain_name"] = "arm-linux-androideabi"
|
self.config["android"]["toolchain_name"] = "armv7a-linux-androideabi30"
|
||||||
return True
|
return True
|
||||||
elif target == "aarch64-linux-android":
|
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"]["target"] = target
|
||||||
self.config["android"]["toolchain_prefix"] = target
|
self.config["android"]["toolchain_prefix"] = target
|
||||||
self.config["android"]["arch"] = "arm64"
|
self.config["android"]["arch"] = "arm64"
|
||||||
self.config["android"]["lib"] = "arm64-v8a"
|
self.config["android"]["lib"] = "arm64-v8a"
|
||||||
self.config["android"]["toolchain_name"] = target
|
self.config["android"]["toolchain_name"] = "aarch64-linux-androideabi30"
|
||||||
return True
|
return True
|
||||||
elif target == "i686-linux-android":
|
elif target == "i686-linux-android":
|
||||||
# https://github.com/jemalloc/jemalloc/issues/1279
|
# 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"]["target"] = target
|
||||||
self.config["android"]["toolchain_prefix"] = "x86"
|
self.config["android"]["toolchain_prefix"] = target
|
||||||
self.config["android"]["arch"] = "x86"
|
self.config["android"]["arch"] = "x86"
|
||||||
self.config["android"]["lib"] = "x86"
|
self.config["android"]["lib"] = "x86"
|
||||||
self.config["android"]["toolchain_name"] = target
|
self.config["android"]["toolchain_name"] = "i686-linux-android30"
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -160,7 +160,7 @@ class PackageCommands(CommandBase):
|
||||||
else:
|
else:
|
||||||
raise Exception("TODO what should this be?")
|
raise Exception("TODO what should this be?")
|
||||||
|
|
||||||
flavor_name = "Main"
|
flavor_name = "Basic"
|
||||||
if flavor is not None:
|
if flavor is not None:
|
||||||
flavor_name = flavor.title()
|
flavor_name = flavor.title()
|
||||||
|
|
||||||
|
@ -176,10 +176,7 @@ class PackageCommands(CommandBase):
|
||||||
variant = ":assemble" + flavor_name + arch_string + build_type_string
|
variant = ":assemble" + flavor_name + arch_string + build_type_string
|
||||||
apk_task_name = ":servoapp" + variant
|
apk_task_name = ":servoapp" + variant
|
||||||
aar_task_name = ":servoview" + variant
|
aar_task_name = ":servoview" + variant
|
||||||
maven_task_name = ":servoview:uploadArchive"
|
|
||||||
argv = ["./gradlew", "--no-daemon", apk_task_name, aar_task_name]
|
argv = ["./gradlew", "--no-daemon", apk_task_name, aar_task_name]
|
||||||
if maven:
|
|
||||||
argv.append(maven_task_name)
|
|
||||||
try:
|
try:
|
||||||
with cd(path.join("support", "android", "apk")):
|
with cd(path.join("support", "android", "apk")):
|
||||||
subprocess.check_call(argv, env=env)
|
subprocess.check_call(argv, env=env)
|
||||||
|
|
|
@ -118,6 +118,7 @@ class PostBuildCommands(CommandBase):
|
||||||
"am start " + extra + " org.mozilla.servo/org.mozilla.servo.MainActivity",
|
"am start " + extra + " org.mozilla.servo/org.mozilla.servo.MainActivity",
|
||||||
"sleep 0.5",
|
"sleep 0.5",
|
||||||
"echo Servo PID: $(pidof org.mozilla.servo)",
|
"echo Servo PID: $(pidof org.mozilla.servo)",
|
||||||
|
"logcat --pid=$(pidof org.mozilla.servo)",
|
||||||
"exit"
|
"exit"
|
||||||
]
|
]
|
||||||
args = [self.android_adb_path(env)]
|
args = [self.android_adb_path(env)]
|
||||||
|
@ -129,7 +130,7 @@ class PostBuildCommands(CommandBase):
|
||||||
if usb:
|
if usb:
|
||||||
args += ["-d"]
|
args += ["-d"]
|
||||||
shell = subprocess.Popen(args + ["shell"], stdin=subprocess.PIPE)
|
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()
|
return shell.wait()
|
||||||
|
|
||||||
args = [bin or self.get_nightly_binary_path(nightly) or self.get_binary_path(build_type)]
|
args = [bin or self.get_nightly_binary_path(nightly) or self.get_binary_path(build_type)]
|
||||||
|
|
|
@ -65,6 +65,10 @@ packages = [
|
||||||
|
|
||||||
# style (0.64) vs. webxr (0.66) vs. mozjs_sys (0.68).
|
# style (0.64) vs. webxr (0.66) vs. mozjs_sys (0.68).
|
||||||
"bindgen",
|
"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 that are ignored for all tidy and lint checks.
|
||||||
files = [
|
files = [
|
||||||
|
|
|
@ -56,8 +56,6 @@ media-stack = "auto"
|
||||||
|
|
||||||
# Android information
|
# Android information
|
||||||
[android]
|
[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"
|
#sdk = "/opt/android-sdk"
|
||||||
#ndk = "/opt/android-ndk"
|
#ndk = "/opt/android-ndk"
|
||||||
#toolchain = "/opt/android-toolchain"
|
|
||||||
#platform = "android-18"
|
|
||||||
|
|
|
@ -1,42 +1,30 @@
|
||||||
import org.apache.tools.ant.taskdefs.condition.Os
|
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||||
|
plugins {
|
||||||
buildscript {
|
id 'com.android.application' version '8.0.1' apply false
|
||||||
repositories {
|
id 'com.android.library' version '8.0.1' apply false
|
||||||
jcenter()
|
|
||||||
google()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.android.tools.build:gradle:3.1.3'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
repositories {
|
|
||||||
jcenter()
|
|
||||||
flatDir {
|
|
||||||
dirs rootDir.absolutePath + "/../../../target/android/aar"
|
|
||||||
}
|
|
||||||
google()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Utility methods
|
// Utility methods
|
||||||
String getTargetDir(boolean debug, String arch) {
|
ext.getTargetDir = { boolean debug, String arch ->
|
||||||
def basePath = project.rootDir.getParentFile().getParentFile().getParentFile().absolutePath
|
def basePath = project.rootDir.getParentFile().getParentFile().getParentFile().absolutePath
|
||||||
return basePath + '/target/android/' + getSubTargetDir(debug, arch)
|
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')
|
return getRustTarget(arch) + '/' + (debug ? 'debug' : 'release')
|
||||||
}
|
}
|
||||||
|
|
||||||
String getJniLibsPath(boolean debug, String arch) {
|
ext.getJniLibsPath = { boolean debug, String arch ->
|
||||||
return getTargetDir(debug, arch) + '/apk/jniLibs'
|
return getTargetDir(debug, arch) + '/jniLibs'
|
||||||
}
|
}
|
||||||
|
|
||||||
static String getRustTarget(String arch) {
|
ext.getRustTarget = { String arch ->
|
||||||
switch (arch.toLowerCase()) {
|
switch (arch.toLowerCase()) {
|
||||||
case 'arm' : return 'arm-linux-androideabi'
|
|
||||||
case 'armv7' : return 'armv7-linux-androideabi'
|
case 'armv7' : return 'armv7-linux-androideabi'
|
||||||
case 'arm64' : return 'aarch64-linux-android'
|
case 'arm64' : return 'aarch64-linux-android'
|
||||||
case 'x86' : return 'i686-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()) {
|
switch (arch.toLowerCase()) {
|
||||||
case 'arm' : return 'armeabi'
|
|
||||||
case 'armv7' : return 'armeabi-v7a'
|
case 'armv7' : return 'armeabi-v7a'
|
||||||
case 'arm64' : return 'arm64-v8a'
|
case 'arm64' : return 'arm64-v8a'
|
||||||
case 'x86' : return 'x86'
|
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
|
// Read environment variable used in rust build system
|
||||||
String ndkDir = System.getenv('ANDROID_NDK')
|
String ndkRoot = System.getenv('ANDROID_NDK_ROOT')
|
||||||
if (ndkDir == null) {
|
if (ndkRoot == null) {
|
||||||
ndkDir = System.getenv('ANDROID_NDK_HOME')
|
|
||||||
}
|
|
||||||
if (ndkDir == null) {
|
|
||||||
ndkDir = System.getenv('ANDROID_NDK_ROOT')
|
|
||||||
}
|
|
||||||
if (ndkDir == null) {
|
|
||||||
// Fallback to ndkDir in local.properties
|
// Fallback to ndkDir in local.properties
|
||||||
def rootDir = project.rootDir
|
def rootDir = project.rootDir
|
||||||
def localProperties = new File(rootDir, "local.properties")
|
def localProperties = new File(rootDir, "local.properties")
|
||||||
|
@ -72,14 +53,13 @@ String getNdkDir() {
|
||||||
properties.load(instr)
|
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 ndkDir = ndkRoot != null ? new File(ndkRoot) : null
|
||||||
def ndkbuild = new File(ndkDir + '/' + cmd)
|
if (!ndkDir || !ndkDir.exists()) {
|
||||||
if (!ndkbuild.exists()) {
|
throw new GradleException("Please set a valid ANDROID_NDK_ROOT environment variable" +
|
||||||
throw new GradleException("Please set a valid NDK_HOME environment variable" +
|
|
||||||
"or ndk.dir path in local.properties file");
|
"or ndk.dir path in local.properties file");
|
||||||
}
|
}
|
||||||
return ndkbuild.absolutePath
|
return ndkDir.absolutePath
|
||||||
}
|
}
|
||||||
|
|
21
support/android/apk/gradle.properties
Normal file
21
support/android/apk/gradle.properties
Normal file
|
@ -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
|
Binary file not shown.
|
@ -1,6 +1,5 @@
|
||||||
#Wed Jul 11 13:23:08 CEST 2018
|
|
||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
|
|
||||||
|
|
100
support/android/apk/gradlew
vendored
100
support/android/apk/gradlew
vendored
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
##############################################################################
|
##############################################################################
|
||||||
##
|
##
|
||||||
|
@ -6,42 +6,6 @@
|
||||||
##
|
##
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
|
||||||
DEFAULT_JVM_OPTS=""
|
|
||||||
|
|
||||||
APP_NAME="Gradle"
|
|
||||||
APP_BASE_NAME=`basename "$0"`
|
|
||||||
|
|
||||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
|
||||||
MAX_FD="maximum"
|
|
||||||
|
|
||||||
warn ( ) {
|
|
||||||
echo "$*"
|
|
||||||
}
|
|
||||||
|
|
||||||
die ( ) {
|
|
||||||
echo
|
|
||||||
echo "$*"
|
|
||||||
echo
|
|
||||||
exit 1
|
|
||||||
}
|
|
||||||
|
|
||||||
# OS specific support (must be 'true' or 'false').
|
|
||||||
cygwin=false
|
|
||||||
msys=false
|
|
||||||
darwin=false
|
|
||||||
case "`uname`" in
|
|
||||||
CYGWIN* )
|
|
||||||
cygwin=true
|
|
||||||
;;
|
|
||||||
Darwin* )
|
|
||||||
darwin=true
|
|
||||||
;;
|
|
||||||
MINGW* )
|
|
||||||
msys=true
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# Attempt to set APP_HOME
|
# Attempt to set APP_HOME
|
||||||
# Resolve links: $0 may be a link
|
# Resolve links: $0 may be a link
|
||||||
PRG="$0"
|
PRG="$0"
|
||||||
|
@ -60,6 +24,46 @@ cd "`dirname \"$PRG\"`/" >/dev/null
|
||||||
APP_HOME="`pwd -P`"
|
APP_HOME="`pwd -P`"
|
||||||
cd "$SAVED" >/dev/null
|
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 () {
|
||||||
|
echo "$*"
|
||||||
|
}
|
||||||
|
|
||||||
|
die () {
|
||||||
|
echo
|
||||||
|
echo "$*"
|
||||||
|
echo
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# OS specific support (must be 'true' or 'false').
|
||||||
|
cygwin=false
|
||||||
|
msys=false
|
||||||
|
darwin=false
|
||||||
|
nonstop=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN* )
|
||||||
|
cygwin=true
|
||||||
|
;;
|
||||||
|
Darwin* )
|
||||||
|
darwin=true
|
||||||
|
;;
|
||||||
|
MINGW* )
|
||||||
|
msys=true
|
||||||
|
;;
|
||||||
|
NONSTOP* )
|
||||||
|
nonstop=true
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
|
@ -85,7 +89,7 @@ location of your Java installation."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Increase the maximum file descriptors if we can.
|
# 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`
|
MAX_FD_LIMIT=`ulimit -H -n`
|
||||||
if [ $? -eq 0 ] ; then
|
if [ $? -eq 0 ] ; then
|
||||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||||
|
@ -150,11 +154,19 @@ if $cygwin ; then
|
||||||
esac
|
esac
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
# Escape application args
|
||||||
function splitJvmOpts() {
|
save () {
|
||||||
JVM_OPTS=("$@")
|
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||||
|
echo " "
|
||||||
}
|
}
|
||||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
APP_ARGS=$(save "$@")
|
||||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
|
||||||
|
|
||||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
# 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" "$@"
|
||||||
|
|
14
support/android/apk/gradlew.bat
vendored
14
support/android/apk/gradlew.bat
vendored
|
@ -8,14 +8,14 @@
|
||||||
@rem Set local scope for the variables with windows NT shell
|
@rem Set local scope for the variables with windows NT shell
|
||||||
if "%OS%"=="Windows_NT" setlocal
|
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
|
set DIRNAME=%~dp0
|
||||||
if "%DIRNAME%" == "" set DIRNAME=.
|
if "%DIRNAME%" == "" set DIRNAME=.
|
||||||
set APP_BASE_NAME=%~n0
|
set APP_BASE_NAME=%~n0
|
||||||
set APP_HOME=%DIRNAME%
|
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
|
@rem Find java.exe
|
||||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||||
|
|
||||||
|
@ -46,10 +46,9 @@ echo location of your Java installation.
|
||||||
goto fail
|
goto fail
|
||||||
|
|
||||||
:init
|
: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 not "%OS%" == "Windows_NT" goto win9xME_args
|
||||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
|
||||||
|
|
||||||
:win9xME_args
|
:win9xME_args
|
||||||
@rem Slurp the command line arguments.
|
@rem Slurp the command line arguments.
|
||||||
|
@ -60,11 +59,6 @@ set _SKIP=2
|
||||||
if "x%~1" == "x" goto execute
|
if "x%~1" == "x" goto execute
|
||||||
|
|
||||||
set CMD_LINE_ARGS=%*
|
set CMD_LINE_ARGS=%*
|
||||||
goto execute
|
|
||||||
|
|
||||||
:4NT_args
|
|
||||||
@rem Get arguments from the 4NT Shell from JP Software
|
|
||||||
set CMD_LINE_ARGS=%$
|
|
||||||
|
|
||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
|
@ -16,13 +16,7 @@
|
||||||
MY_LOCAL_PATH := $(call my-dir)
|
MY_LOCAL_PATH := $(call my-dir)
|
||||||
|
|
||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_PATH:= $(SERVO_TARGET_DIR)
|
LOCAL_PATH := $(SERVO_TARGET_DIR)
|
||||||
LOCAL_MODULE := servojni
|
LOCAL_MODULE := servojni
|
||||||
LOCAL_SRC_FILES := libsimpleservo.so
|
LOCAL_SRC_FILES := libsimpleservo.so
|
||||||
include $(PREBUILT_SHARED_LIBRARY)
|
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)
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
NDK_TOOLCHAIN_VERSION := clang
|
NDK_TOOLCHAIN_VERSION := clang
|
||||||
APP_MODULES := c++_shared servojni gstreamer
|
APP_MODULES := c++_shared servojni
|
||||||
APP_PLATFORM := android-21
|
APP_PLATFORM := android-30
|
||||||
APP_STL:= c++_shared
|
APP_STL := c++_shared
|
||||||
APP_ABI:= armeabi-v7a x86
|
APP_ABI := armeabi-v7a x86
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
apply plugin: 'com.android.application'
|
plugins {
|
||||||
|
id 'com.android.application'
|
||||||
|
}
|
||||||
|
|
||||||
import java.util.regex.Matcher
|
import java.util.regex.Matcher
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 27
|
compileSdk 33
|
||||||
buildToolsVersion '27.0.3'
|
buildToolsVersion "33.0.2"
|
||||||
|
|
||||||
|
namespace 'org.mozilla.servo'
|
||||||
|
|
||||||
buildDir = rootDir.absolutePath + "/../../../target/android/gradle/servoapp"
|
buildDir = rootDir.absolutePath + "/../../../target/android/gradle/servoapp"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.mozilla.servo"
|
applicationId "org.mozilla.servo"
|
||||||
minSdkVersion 21
|
minSdk 30
|
||||||
targetSdkVersion 27
|
targetSdk 30
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0.0"
|
versionName "1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -26,11 +30,7 @@ android {
|
||||||
flavorDimensions "default"
|
flavorDimensions "default"
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
main {
|
basic {
|
||||||
}
|
|
||||||
googlevr {
|
|
||||||
}
|
|
||||||
oculusvr {
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,19 +61,6 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom build types
|
// Custom build types
|
||||||
armDebug {
|
|
||||||
initWith(debug)
|
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('arm')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
armRelease {
|
|
||||||
initWith(release)
|
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('arm')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
armv7Debug {
|
armv7Debug {
|
||||||
initWith(debug)
|
initWith(debug)
|
||||||
ndk {
|
ndk {
|
||||||
|
@ -144,7 +131,6 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
|
||||||
if (findProject(':servoview-local')) {
|
if (findProject(':servoview-local')) {
|
||||||
implementation project(':servoview-local')
|
implementation project(':servoview-local')
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -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) -->
|
|
|
@ -1,7 +1,6 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<!-- BEGIN_INCLUDE(manifest) -->
|
<!-- BEGIN_INCLUDE(manifest) -->
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto">
|
||||||
package="org.mozilla.servo">
|
|
||||||
|
|
||||||
<uses-feature android:glEsVersion="0x00030000" android:required="true" />
|
<uses-feature android:glEsVersion="0x00030000" android:required="true" />
|
||||||
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
|
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
|
||||||
|
|
|
@ -78,8 +78,7 @@ public class MainActivity extends Activity implements Servo.Client {
|
||||||
Intent intent = getIntent();
|
Intent intent = getIntent();
|
||||||
String args = intent.getStringExtra("servoargs");
|
String args = intent.getStringExtra("servoargs");
|
||||||
String log = intent.getStringExtra("servolog");
|
String log = intent.getStringExtra("servolog");
|
||||||
String gstdebug = intent.getStringExtra("gstdebug");
|
mServoView.setServoArgs(args, log);
|
||||||
mServoView.setServoArgs(args, log, gstdebug);
|
|
||||||
|
|
||||||
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
|
if (Intent.ACTION_VIEW.equals(intent.getAction())) {
|
||||||
mServoView.loadUri(intent.getData());
|
mServoView.loadUri(intent.getData());
|
||||||
|
@ -89,8 +88,10 @@ public class MainActivity extends Activity implements Servo.Client {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDestroy() {
|
protected void onDestroy() {
|
||||||
super.onDestroy();
|
super.onDestroy();
|
||||||
mMediaSession.hideMediaSessionControls();
|
if (mMediaSession != null) {
|
||||||
|
mMediaSession.hideMediaSessionControls();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupUrlField() {
|
private void setupUrlField() {
|
||||||
|
@ -229,31 +230,31 @@ public class MainActivity extends Activity implements Servo.Client {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMediaSessionMetadata(String title, String artist, String album) {
|
public void onMediaSessionMetadata(String title, String artist, String album) {
|
||||||
if (mMediaSession == null) {
|
if (mMediaSession == null) {
|
||||||
mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
|
mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
|
||||||
}
|
}
|
||||||
Log.d("onMediaSessionMetadata", title + " " + artist + " " + album);
|
Log.d("onMediaSessionMetadata", title + " " + artist + " " + album);
|
||||||
mMediaSession.updateMetadata(title, artist, album);
|
mMediaSession.updateMetadata(title, artist, album);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMediaSessionPlaybackStateChange(int state) {
|
public void onMediaSessionPlaybackStateChange(int state) {
|
||||||
Log.d("onMediaSessionPlaybackStateChange", String.valueOf(state));
|
Log.d("onMediaSessionPlaybackStateChange", String.valueOf(state));
|
||||||
if (mMediaSession == null) {
|
if (mMediaSession == null) {
|
||||||
mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
|
mMediaSession = new MediaSession(mServoView, this, getApplicationContext());
|
||||||
}
|
}
|
||||||
|
|
||||||
mMediaSession.setPlaybackState(state);
|
mMediaSession.setPlaybackState(state);
|
||||||
|
|
||||||
if (state == MediaSession.PLAYBACK_STATE_NONE) {
|
if (state == MediaSession.PLAYBACK_STATE_NONE) {
|
||||||
mMediaSession.hideMediaSessionControls();
|
mMediaSession.hideMediaSessionControls();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (state == MediaSession.PLAYBACK_STATE_PLAYING ||
|
if (state == MediaSession.PLAYBACK_STATE_PLAYING ||
|
||||||
state == MediaSession.PLAYBACK_STATE_PAUSED) {
|
state == MediaSession.PLAYBACK_STATE_PAUSED) {
|
||||||
mMediaSession.showMediaSessionControls();
|
mMediaSession.showMediaSessionControls();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?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:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -102,4 +102,4 @@
|
||||||
android:focusable="true"/>
|
android:focusable="true"/>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
</android.support.constraint.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
|
|
|
@ -1,18 +1,23 @@
|
||||||
apply plugin: 'com.android.library'
|
plugins {
|
||||||
|
id 'com.android.library'
|
||||||
|
}
|
||||||
|
|
||||||
import groovy.io.FileType
|
import groovy.io.FileType
|
||||||
import java.util.regex.Matcher
|
import java.util.regex.Matcher
|
||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 27
|
compileSdk 33
|
||||||
buildToolsVersion '27.0.3'
|
buildToolsVersion "33.0.2"
|
||||||
|
|
||||||
|
namespace 'org.mozilla.servoview'
|
||||||
|
|
||||||
buildDir = rootDir.absolutePath + "/../../../target/android/gradle/servoview"
|
buildDir = rootDir.absolutePath + "/../../../target/android/gradle/servoview"
|
||||||
|
|
||||||
|
ndkPath = getNdkDir()
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 18
|
minSdk 30
|
||||||
targetSdkVersion 27
|
targetSdk 30
|
||||||
versionCode 1
|
versionCode 1
|
||||||
versionName "1.0"
|
versionName "1.0"
|
||||||
}
|
}
|
||||||
|
@ -26,24 +31,18 @@ android {
|
||||||
flavorDimensions "default"
|
flavorDimensions "default"
|
||||||
|
|
||||||
productFlavors {
|
productFlavors {
|
||||||
main {
|
basic {
|
||||||
}
|
|
||||||
googlevr {
|
|
||||||
minSdkVersion 21
|
|
||||||
}
|
|
||||||
oculusvr {
|
|
||||||
minSdkVersion 21
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
splits {
|
splits {
|
||||||
density {
|
density {
|
||||||
enable false
|
enable false
|
||||||
}
|
}
|
||||||
abi {
|
abi {
|
||||||
enable false
|
enable false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
buildTypes {
|
buildTypes {
|
||||||
|
@ -59,65 +58,29 @@ android {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Custom build types
|
// Custom build types
|
||||||
armDebug {
|
|
||||||
initWith(debug)
|
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('arm')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
armRelease {
|
|
||||||
initWith(release)
|
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('arm')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
armv7Debug {
|
armv7Debug {
|
||||||
initWith(debug)
|
initWith(debug)
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('armv7')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
armv7Release {
|
armv7Release {
|
||||||
initWith(release)
|
initWith(release)
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('armv7')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
arm64Debug {
|
arm64Debug {
|
||||||
initWith(debug)
|
initWith(debug)
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('arm64')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
arm64Release {
|
arm64Release {
|
||||||
initWith(release)
|
initWith(release)
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('arm64')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
x86Debug {
|
x86Debug {
|
||||||
initWith(debug)
|
initWith(debug)
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('x86')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
x86Release {
|
x86Release {
|
||||||
initWith(release)
|
initWith(release)
|
||||||
ndk {
|
|
||||||
abiFilters getNDKAbi('x86')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sourceSets {
|
sourceSets {
|
||||||
main {
|
main {
|
||||||
}
|
}
|
||||||
armDebug {
|
|
||||||
jniLibs.srcDirs = [getJniLibsPath(true, 'arm')]
|
|
||||||
}
|
|
||||||
armRelease {
|
|
||||||
jniLibs.srcDirs = [getJniLibsPath(false, 'arm')]
|
|
||||||
}
|
|
||||||
armv7Debug {
|
armv7Debug {
|
||||||
jniLibs.srcDirs = [getJniLibsPath(true, 'armv7')]
|
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 {
|
tasks.all {
|
||||||
compileTask ->
|
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)
|
Matcher matcher = pattern.matcher(compileTask.name)
|
||||||
if (!matcher.find()) {
|
if (!matcher.find()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
def taskName = "ndkbuild" + compileTask.name
|
def taskName = "ndkbuild" + compileTask.name
|
||||||
tasks.create(name: taskName, type: Exec) {
|
tasks.create(name: taskName, type: Exec) {
|
||||||
def debug = compileTask.name.contains("Debug")
|
def debug = compileTask.name.contains("Debug")
|
||||||
def arch = matcher.group(1)
|
def arch = matcher.group(1)
|
||||||
commandLine getNdkDir(),
|
commandLine getNdkDir() + "/ndk-build",
|
||||||
'APP_BUILD_SCRIPT=../jni/Android.mk',
|
'APP_BUILD_SCRIPT=../jni/Android.mk',
|
||||||
'NDK_APPLICATION_MK=../jni/Application.mk',
|
'NDK_APPLICATION_MK=../jni/Application.mk',
|
||||||
'NDK_LIBS_OUT=' + getJniLibsPath(debug, arch),
|
'NDK_LIBS_OUT=' + getJniLibsPath(debug, arch),
|
||||||
'NDK_OUT=' + getTargetDir(debug, arch) + '/apk/obj',
|
'NDK_DEBUG=' + (debug ? '1' : '0'),
|
||||||
'NDK_DEBUG=' + (debug ? '1' : '0'),
|
'APP_ABI=' + getNDKAbi(arch),
|
||||||
'APP_ABI=' + getNDKAbi(arch),
|
'NDK_LOG=1',
|
||||||
'SERVO_TARGET_DIR=' + getTargetDir(debug, arch)
|
'SERVO_TARGET_DIR=' + getNativeTargetDir(debug, arch)
|
||||||
}
|
}
|
||||||
|
|
||||||
compileTask.dependsOn taskName
|
compileTask.dependsOn taskName
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
project.afterEvaluate {
|
project.afterEvaluate {
|
||||||
android.libraryVariants.all { variant ->
|
android.libraryVariants.all { variant ->
|
||||||
Pattern pattern = Pattern.compile(/^[\w\d]+([A-Z][\w\d]+)(Debug|Release)/)
|
Pattern pattern = Pattern.compile(/^[\w\d]+([A-Z][\w\d]+)(Debug|Release)/)
|
||||||
|
@ -205,7 +183,7 @@ dependencies {
|
||||||
]
|
]
|
||||||
// Iterate all build types and dependencies
|
// Iterate all build types and dependencies
|
||||||
// For each dependency call the proper implementation command and set the correct dependency path
|
// 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 (arch in list) {
|
||||||
for (debug in [true, false]) {
|
for (debug in [true, false]) {
|
||||||
String basePath = getTargetDir(debug, arch) + "/build"
|
String basePath = getTargetDir(debug, arch) + "/build"
|
||||||
|
@ -220,10 +198,9 @@ dependencies {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
googlevrImplementation 'com.google.vr:sdk-base:1.140.0'
|
implementation 'androidx.appcompat:appcompat:1.6.1'
|
||||||
googlevrImplementation(name: 'GVRService', ext: 'aar')
|
implementation 'com.google.android.material:material:1.9.0'
|
||||||
oculusvrImplementation(name: 'OVRService', ext: 'aar')
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// folderFilter can be used to improve search performance
|
// folderFilter can be used to improve search performance
|
||||||
|
@ -258,42 +235,3 @@ class ServoDependency {
|
||||||
public String fileName;
|
public String fileName;
|
||||||
public String folderFilter;
|
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'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -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) -->
|
|
|
@ -1,2 +1 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
||||||
package="org.mozilla.servoview" />
|
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
package org.mozilla.servoview;
|
package org.mozilla.servoview;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
|
import android.view.Surface;
|
||||||
/**
|
/**
|
||||||
* Maps /ports/libsimpleservo API
|
* Maps /ports/libsimpleservo API
|
||||||
*/
|
*/
|
||||||
|
@ -14,13 +14,12 @@ import android.app.Activity;
|
||||||
public class JNIServo {
|
public class JNIServo {
|
||||||
JNIServo() {
|
JNIServo() {
|
||||||
System.loadLibrary("c++_shared");
|
System.loadLibrary("c++_shared");
|
||||||
System.loadLibrary("gstreamer_android");
|
|
||||||
System.loadLibrary("simpleservo");
|
System.loadLibrary("simpleservo");
|
||||||
}
|
}
|
||||||
|
|
||||||
public native String version();
|
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();
|
public native void deinit();
|
||||||
|
|
||||||
|
@ -66,6 +65,9 @@ public class JNIServo {
|
||||||
|
|
||||||
public native void click(float x, float y);
|
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 native void mediaSessionAction(int action);
|
||||||
|
|
||||||
public static class ServoOptions {
|
public static class ServoOptions {
|
||||||
|
|
|
@ -8,6 +8,7 @@ package org.mozilla.servoview;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
import android.view.Surface;
|
||||||
|
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.FutureTask;
|
import java.util.concurrent.FutureTask;
|
||||||
|
@ -30,21 +31,16 @@ public class Servo {
|
||||||
RunCallback runCallback,
|
RunCallback runCallback,
|
||||||
GfxCallbacks gfxcb,
|
GfxCallbacks gfxcb,
|
||||||
Client client,
|
Client client,
|
||||||
Activity activity) {
|
Activity activity,
|
||||||
|
Surface surface) {
|
||||||
|
|
||||||
mRunCallback = runCallback;
|
mRunCallback = runCallback;
|
||||||
|
|
||||||
mServoCallbacks = new Callbacks(client, gfxcb);
|
mServoCallbacks = new Callbacks(client, gfxcb);
|
||||||
|
|
||||||
mRunCallback.inGLThread(() -> {
|
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) {
|
public void resetGfxCallbacks(GfxCallbacks gfxcb) {
|
||||||
|
@ -164,6 +160,13 @@ public class Servo {
|
||||||
mRunCallback.inGLThread(() -> mJNI.click(x, y));
|
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) {
|
public void suspend(boolean suspended) {
|
||||||
mSuspended = suspended;
|
mSuspended = suspended;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,17 +7,15 @@ package org.mozilla.servoview;
|
||||||
|
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
|
||||||
import android.opengl.GLES31;
|
|
||||||
import android.opengl.GLSurfaceView;
|
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
|
import android.net.Uri;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.Looper;
|
||||||
import android.util.DisplayMetrics;
|
import android.util.DisplayMetrics;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.view.Choreographer;
|
import android.view.Surface;
|
||||||
import android.view.GestureDetector;
|
import android.view.SurfaceView;
|
||||||
import android.view.MotionEvent;
|
import android.view.SurfaceHolder;
|
||||||
import android.view.ScaleGestureDetector;
|
|
||||||
import android.widget.OverScroller;
|
|
||||||
|
|
||||||
import org.mozilla.servoview.JNIServo.ServoCoordinates;
|
import org.mozilla.servoview.JNIServo.ServoCoordinates;
|
||||||
import org.mozilla.servoview.JNIServo.ServoOptions;
|
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.GfxCallbacks;
|
||||||
import org.mozilla.servoview.Servo.RunCallback;
|
import org.mozilla.servoview.Servo.RunCallback;
|
||||||
|
|
||||||
import javax.microedition.khronos.egl.EGLConfig;
|
import android.view.Choreographer;
|
||||||
import javax.microedition.khronos.opengles.GL10;
|
import android.view.GestureDetector;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ScaleGestureDetector;
|
||||||
|
import android.widget.OverScroller;
|
||||||
|
|
||||||
public class ServoView extends GLSurfaceView
|
import java.util.ArrayList;
|
||||||
implements
|
|
||||||
GestureDetector.OnGestureListener,
|
|
||||||
ScaleGestureDetector.OnScaleGestureListener,
|
|
||||||
Choreographer.FrameCallback,
|
|
||||||
GfxCallbacks,
|
|
||||||
RunCallback {
|
|
||||||
|
|
||||||
|
public class ServoView extends SurfaceView
|
||||||
|
implements
|
||||||
|
GfxCallbacks,
|
||||||
|
RunCallback,
|
||||||
|
Choreographer.FrameCallback,
|
||||||
|
GestureDetector.OnGestureListener,
|
||||||
|
ScaleGestureDetector.OnScaleGestureListener {
|
||||||
private static final String LOGTAG = "ServoView";
|
private static final String LOGTAG = "ServoView";
|
||||||
|
private GLThread mGLThread;
|
||||||
private Activity mActivity;
|
private Handler mGLLooperHandler;
|
||||||
private Servo mServo;
|
private Surface mASurface;
|
||||||
|
protected Servo mServo = null;
|
||||||
private Client mClient = null;
|
private Client mClient = null;
|
||||||
private Uri mInitialUri = null;
|
|
||||||
private boolean mAnimating;
|
|
||||||
private String mServoArgs;
|
private String mServoArgs;
|
||||||
private String mServoLog;
|
private String mServoLog;
|
||||||
private String mGstDebug;
|
private String mInitialUri;
|
||||||
|
private Activity mActivity;
|
||||||
private GestureDetector mGestureDetector;
|
private GestureDetector mGestureDetector;
|
||||||
private ScaleGestureDetector mScaleGestureDetector;
|
|
||||||
|
|
||||||
private OverScroller mScroller;
|
|
||||||
private int mLastX = 0;
|
private int mLastX = 0;
|
||||||
private int mCurX = 0;
|
private int mCurX = 0;
|
||||||
private int mLastY = 0;
|
private int mLastY = 0;
|
||||||
private int mCurY = 0;
|
private int mCurY = 0;
|
||||||
private boolean mFlinging;
|
private boolean mFlinging;
|
||||||
|
private ScaleGestureDetector mScaleGestureDetector;
|
||||||
|
private OverScroller mScroller;
|
||||||
|
|
||||||
private boolean mZooming;
|
private boolean mZooming;
|
||||||
private float mZoomFactor = 1;
|
private float mZoomFactor = 1;
|
||||||
|
|
||||||
private boolean mRedrawing;
|
private boolean mRedrawing;
|
||||||
|
private boolean mAnimating;
|
||||||
|
private boolean mPaused = false;
|
||||||
|
|
||||||
public ServoView(Context context) {
|
public ServoView(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -71,79 +73,49 @@ public class ServoView extends GLSurfaceView
|
||||||
init(context);
|
init(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDetachedFromWindow() {
|
|
||||||
mServo.shutdown();
|
|
||||||
mServo = null;
|
|
||||||
super.onDetachedFromWindow();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void init(Context context) {
|
private void init(Context context) {
|
||||||
mActivity = (Activity) context;
|
mActivity = (Activity) context;
|
||||||
setFocusable(true);
|
setFocusable(true);
|
||||||
setFocusableInTouchMode(true);
|
setFocusableInTouchMode(true);
|
||||||
|
setClickable(true);
|
||||||
|
ArrayList view = new ArrayList();
|
||||||
|
view.add(this);
|
||||||
|
addTouchables(view);
|
||||||
setWillNotCacheDrawing(false);
|
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);
|
initGestures(context);
|
||||||
|
|
||||||
|
mGLThread = new GLThread(mActivity, this);
|
||||||
|
getHolder().addCallback(mGLThread);
|
||||||
|
mGLThread.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setServoArgs(String args, String log, String gstdebug) {
|
|
||||||
|
public void setClient(Client client) {
|
||||||
|
mClient = client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServoArgs(String args, String log) {
|
||||||
mServoArgs = args;
|
mServoArgs = args;
|
||||||
mServoLog = log;
|
mServoLog = log;
|
||||||
mGstDebug = gstdebug;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void reload() {
|
|
||||||
mServo.reload();
|
// RunCallback
|
||||||
|
public void inGLThread(Runnable r) {
|
||||||
|
mGLLooperHandler.post(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void goBack() {
|
public void inUIThread(Runnable r) {
|
||||||
mServo.goBack();
|
post(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void goForward() {
|
|
||||||
mServo.goForward();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
mServo.stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void loadUri(Uri uri) {
|
|
||||||
if (mServo != null) {
|
|
||||||
mServo.loadUri(uri.toString());
|
|
||||||
} else {
|
|
||||||
mInitialUri = uri;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void mediaSessionAction(int action) {
|
|
||||||
mServo.mediaSessionAction(action);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// GfxCallbacks
|
||||||
public void flushGLBuffers() {
|
public void flushGLBuffers() {
|
||||||
requestRender();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Scroll and click
|
// Scroll and click
|
||||||
|
|
||||||
public void animationStateChanged(boolean animating) {
|
public void animationStateChanged(boolean animating) {
|
||||||
if (!mAnimating && animating) {
|
if (!mAnimating && animating) {
|
||||||
post(() -> startLooping());
|
post(() -> startLooping());
|
||||||
|
@ -154,48 +126,6 @@ public class ServoView extends GLSurfaceView
|
||||||
public void makeCurrent() {
|
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() {
|
private void startLooping() {
|
||||||
// In case we were already drawing.
|
// 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) {
|
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
|
||||||
mFlinging = true;
|
mFlinging = true;
|
||||||
|
|
||||||
|
@ -275,20 +262,22 @@ public class ServoView extends GLSurfaceView
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public boolean onTouchEvent(final MotionEvent e) {
|
public boolean onTouchEvent(final MotionEvent e) {
|
||||||
mGestureDetector.onTouchEvent(e);
|
mGestureDetector.onTouchEvent(e);
|
||||||
mScaleGestureDetector.onTouchEvent(e);
|
mScaleGestureDetector.onTouchEvent(e);
|
||||||
|
|
||||||
int action = e.getActionMasked();
|
int action = e.getActionMasked();
|
||||||
|
|
||||||
float x = e.getX();
|
float x = e.getX();
|
||||||
|
|
||||||
float y = e.getY();
|
float y = e.getY();
|
||||||
|
|
||||||
int pointerIndex = e.getActionIndex();
|
int pointerIndex = e.getActionIndex();
|
||||||
int pointerId = e.getPointerId(pointerIndex);
|
int pointerId = e.getPointerId(pointerIndex);
|
||||||
|
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case (MotionEvent.ACTION_DOWN):
|
case (MotionEvent.ACTION_DOWN):
|
||||||
mServo.touchDown(x, y, pointerId);
|
case (MotionEvent.ACTION_POINTER_DOWN):
|
||||||
mFlinging = false;
|
mFlinging = false;
|
||||||
mScroller.forceFinished(true);
|
mScroller.forceFinished(true);
|
||||||
mCurX = (int) x;
|
mCurX = (int) x;
|
||||||
|
@ -299,32 +288,35 @@ public class ServoView extends GLSurfaceView
|
||||||
case (MotionEvent.ACTION_MOVE):
|
case (MotionEvent.ACTION_MOVE):
|
||||||
mCurX = (int) x;
|
mCurX = (int) x;
|
||||||
mCurY = (int) y;
|
mCurY = (int) y;
|
||||||
mServo.touchMove(x, y, pointerId);
|
|
||||||
return true;
|
return true;
|
||||||
case (MotionEvent.ACTION_UP):
|
case (MotionEvent.ACTION_UP):
|
||||||
mServo.touchUp(x, y, pointerId);
|
case (MotionEvent.ACTION_POINTER_UP):
|
||||||
|
return true;
|
||||||
case (MotionEvent.ACTION_CANCEL):
|
case (MotionEvent.ACTION_CANCEL):
|
||||||
mServo.touchCancel(x, y, pointerId);
|
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onSingleTapUp(MotionEvent e) {
|
// OnGestureListener
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void onLongPress(MotionEvent e) {
|
public void onLongPress(MotionEvent e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean onSingleTapUp(MotionEvent e) {
|
||||||
|
click(e.getX(), e.getY());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public void onShowPress(MotionEvent e) {
|
public void onShowPress(MotionEvent e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// OnScaleGestureListener
|
||||||
@Override
|
@Override
|
||||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||||
if (mScroller.isFinished()) {
|
if (mScroller.isFinished()) {
|
||||||
|
@ -351,41 +343,81 @@ public class ServoView extends GLSurfaceView
|
||||||
mServo.pinchZoomEnd(mZoomFactor, 0, 0);
|
mServo.pinchZoomEnd(mZoomFactor, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void initGestures(Context context) {
|
||||||
@Override
|
mGestureDetector = new GestureDetector(context, this);
|
||||||
public void onPause() {
|
mScaleGestureDetector = new ScaleGestureDetector(context, this);
|
||||||
super.onPause();
|
mScroller = new OverScroller(context);
|
||||||
if (mServo != null) {
|
|
||||||
mServo.suspend(true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
public void mediaSessionAction(int action) {
|
||||||
public void onResume() {
|
mServo.mediaSessionAction(action);
|
||||||
super.onResume();
|
|
||||||
if (mServo != null) {
|
|
||||||
mServo.suspend(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class ServoGLRenderer implements Renderer {
|
class GLThread extends Thread implements SurfaceHolder.Callback {
|
||||||
|
private Activity mActivity;
|
||||||
private final ServoView mView;
|
private ServoView mServoView;
|
||||||
|
GLThread(Activity activity, ServoView servoView) {
|
||||||
ServoGLRenderer(ServoView view) {
|
mActivity = activity;
|
||||||
mView = view;
|
mServoView = servoView;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onSurfaceCreated(GL10 unused, EGLConfig config) {
|
public void surfaceCreated(SurfaceHolder holder) {
|
||||||
mView.onGLReady();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onDrawFrame(GL10 unused) {
|
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 onSurfaceChanged(GL10 gl, int width, int height) {
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||||
GLES31.glViewport(0, 0, width, height);
|
Log.d(LOGTAG, "GLThread::surfaceDestroyed");
|
||||||
mView.onSurfaceInvalidated(width, height);
|
mPaused = true;
|
||||||
|
mServoView.mServo.pauseCompositor();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void shutdown() {
|
||||||
|
Log.d(LOGTAG, "GLThread::shutdown");
|
||||||
|
mGLLooperHandler.getLooper().quitSafely();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
Looper.prepare();
|
||||||
|
|
||||||
|
mGLLooperHandler = new Handler();
|
||||||
|
|
||||||
|
Looper.loop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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) -->
|
|
|
@ -1,3 +1,19 @@
|
||||||
|
pluginManagement {
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencyResolutionManagement {
|
||||||
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
include ':servoapp'
|
include ':servoapp'
|
||||||
|
|
||||||
def userPropertiesFile = new File('user.properties')
|
def userPropertiesFile = new File('user.properties')
|
||||||
|
|
|
@ -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"
|
|
|
@ -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"
|
|
|
@ -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"
|
|
|
@ -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"
|
|
|
@ -1,2 +0,0 @@
|
||||||
@echo off
|
|
||||||
gcc -mwindows %*
|
|
|
@ -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++
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue