mirror of
https://github.com/servo/servo.git
synced 2025-06-06 00:25:37 +00:00
Android life cycle improvements and Gradle integration
This commit is contained in:
parent
350d9c6c47
commit
7a2a90959e
30 changed files with 945 additions and 634 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -24,6 +24,10 @@ Servo.app
|
|||
# IntelliJ
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
|
||||
#Gradle
|
||||
.gradle
|
||||
|
||||
# VSCode
|
||||
.vscode
|
||||
|
|
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -39,11 +39,10 @@ source = "git+https://github.com/mmatyas/android-rs-injected-glue#1995be2c692d8d
|
|||
|
||||
[[package]]
|
||||
name = "angle"
|
||||
version = "0.1.2"
|
||||
source = "git+https://github.com/servo/angle?branch=servo#99128001400771ee9c8a74dcf54cf6fe11b1e532"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/servo/angle?branch=servo#a1371e8a160128677af863d1d73f150862ba42b2"
|
||||
dependencies = [
|
||||
"cmake 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"libc 0.2.21 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -266,13 +265,6 @@ name = "browserhtml"
|
|||
version = "0.1.17"
|
||||
source = "git+https://github.com/browserhtml/browserhtml?branch=crate#7c66ae9a3e29d35230d5b9f16d19a562b1312c87"
|
||||
|
||||
[[package]]
|
||||
name = "build-apk"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
version = "1.0.0"
|
||||
|
@ -2240,7 +2232,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
name = "script"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"angle 0.1.2 (git+https://github.com/servo/angle?branch=servo)",
|
||||
"angle 0.2.0 (git+https://github.com/servo/angle?branch=servo)",
|
||||
"app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"atomic_refcell 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"audio-video-metadata 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -2573,6 +2565,7 @@ dependencies = [
|
|||
name = "servo_config"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"android_injected_glue 0.2.2 (git+https://github.com/mmatyas/android-rs-injected-glue)",
|
||||
"env_logger 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"euclid 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
@ -3324,7 +3317,7 @@ dependencies = [
|
|||
"checksum alloc-no-stdlib 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b21f6ad9c9957eb5d70c3dee16d31c092b3cab339628f821766b05e6833d72b8"
|
||||
"checksum android_glue 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d8289e9637439939cc92b1995b0972117905be88bc28116c86b64d6e589bcd38"
|
||||
"checksum android_injected_glue 0.2.2 (git+https://github.com/mmatyas/android-rs-injected-glue)" = "<none>"
|
||||
"checksum angle 0.1.2 (git+https://github.com/servo/angle?branch=servo)" = "<none>"
|
||||
"checksum angle 0.2.0 (git+https://github.com/servo/angle?branch=servo)" = "<none>"
|
||||
"checksum ansi_term 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23ac7c30002a5accbf7e8987d0632fa6de155b7c3d39d0067317a391e00a2ef6"
|
||||
"checksum antidote 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "34fde25430d87a9388dadbe6e34d7f72a462c8b43ac8d309b42b0a8505d7e2a5"
|
||||
"checksum app_units 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a0c3b5be4ed53affe3e1a162b2e7ef9979bcaac80daa9026e9d7988c41e0e83"
|
||||
|
|
|
@ -3,7 +3,6 @@ members = [
|
|||
"ports/cef",
|
||||
"ports/geckolib",
|
||||
"ports/servo",
|
||||
"support/android/build-apk",
|
||||
]
|
||||
|
||||
[profile.dev]
|
||||
|
|
|
@ -27,3 +27,6 @@ env_logger = "0.4"
|
|||
|
||||
[target.'cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))'.dependencies]
|
||||
xdg = "2.0"
|
||||
|
||||
[target.'cfg(target_os = "android")'.dependencies]
|
||||
android_injected_glue = {git = "https://github.com/mmatyas/android-rs-injected-glue"}
|
||||
|
|
|
@ -6,8 +6,12 @@
|
|||
//! For linux based platforms, it uses the XDG base directory spec but provides
|
||||
//! similar abstractions for non-linux platforms.
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
use android_injected_glue;
|
||||
#[cfg(any(target_os = "macos", target_os = "windows"))]
|
||||
use std::env;
|
||||
#[cfg(target_os = "android")]
|
||||
use std::ffi::CStr;
|
||||
use std::path::PathBuf;
|
||||
#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
|
||||
use xdg;
|
||||
|
@ -20,8 +24,12 @@ pub fn default_config_dir() -> Option<PathBuf> {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(unsafe_code)]
|
||||
pub fn default_config_dir() -> Option<PathBuf> {
|
||||
Some(PathBuf::from("/sdcard/servo"))
|
||||
let dir = unsafe {
|
||||
CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath)
|
||||
};
|
||||
Some(PathBuf::from(dir.to_str().unwrap()))
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
|
||||
|
@ -32,8 +40,12 @@ pub fn default_data_dir() -> Option<PathBuf> {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(unsafe_code)]
|
||||
pub fn default_data_dir() -> Option<PathBuf> {
|
||||
Some(PathBuf::from("/sdcard/servo"))
|
||||
let dir = unsafe {
|
||||
CStr::from_ptr((*android_injected_glue::get_app().activity).internalDataPath)
|
||||
};
|
||||
Some(PathBuf::from(dir.to_str().unwrap()))
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(target_os = "macos"), not(target_os = "ios"), not(target_os = "android")))]
|
||||
|
@ -44,8 +56,14 @@ pub fn default_cache_dir() -> Option<PathBuf> {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(unsafe_code)]
|
||||
pub fn default_cache_dir() -> Option<PathBuf> {
|
||||
Some(PathBuf::from("/sdcard/servo"))
|
||||
// TODO: Use JNI to call context.getCacheDir().
|
||||
// There is no equivalent function in NDK/NativeActivity.
|
||||
let dir = unsafe {
|
||||
CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath)
|
||||
};
|
||||
Some(PathBuf::from(dir.to_str().unwrap()))
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#![deny(unsafe_code)]
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
extern crate android_injected_glue;
|
||||
extern crate euclid;
|
||||
extern crate getopts;
|
||||
#[macro_use] extern crate lazy_static;
|
||||
|
|
|
@ -2,8 +2,12 @@
|
|||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
use android_injected_glue;
|
||||
#[cfg(not(target_os = "android"))]
|
||||
use std::env;
|
||||
#[cfg(target_os = "android")]
|
||||
use std::ffi::CStr;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -21,8 +25,12 @@ pub fn set_resources_path(path: Option<String>) {
|
|||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[allow(unsafe_code)]
|
||||
pub fn resources_dir_path() -> io::Result<PathBuf> {
|
||||
Ok(PathBuf::from("/sdcard/servo/"))
|
||||
let dir = unsafe {
|
||||
CStr::from_ptr((*android_injected_glue::get_app().activity).externalDataPath)
|
||||
};
|
||||
Ok(PathBuf::from(dir.to_str().unwrap()))
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
|
|
|
@ -94,7 +94,7 @@ linux-nightly:
|
|||
android:
|
||||
- ./mach clean-nightlies --keep 3 --force
|
||||
- env SERVO_RUSTC_LLVM_ASSERTIONS=1 ./mach build --android --dev
|
||||
- env SERVO_RUSTC_LLVM_ASSERTIONS=1 ./mach package --android --dev
|
||||
- env SERVO_RUSTC_LLVM_ASSERTIONS=1 ANDROID_SDK=/home/servo/android/sdk/r25.2.3 ./mach package --android --dev
|
||||
- bash ./etc/ci/lockfile_changed.sh
|
||||
- bash ./etc/ci/manifest_changed.sh
|
||||
- python ./etc/ci/check_dynamic_symbols.py
|
||||
|
@ -102,7 +102,7 @@ android:
|
|||
android-nightly:
|
||||
- ./mach clean-nightlies --keep 3 --force
|
||||
- env SERVO_RUSTC_LLVM_ASSERTIONS=1 ./mach build --android --release
|
||||
- env SERVO_RUSTC_LLVM_ASSERTIONS=1 ./mach package --android --release
|
||||
- env SERVO_RUSTC_LLVM_ASSERTIONS=1 ANDROID_SDK=/home/servo/android/sdk/r25.2.3 ./mach package --android --release
|
||||
- ./etc/ci/upload_nightly.sh android
|
||||
|
||||
arm32:
|
||||
|
|
|
@ -940,14 +940,6 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
// WindowProxy is not implemented for android yet
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
fn create_window_proxy(_: &Window) -> Option<glutin::WindowProxy> {
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "android"))]
|
||||
fn create_window_proxy(window: &Window) -> Option<glutin::WindowProxy> {
|
||||
match window.kind {
|
||||
WindowKind::Window(ref window) => {
|
||||
|
|
|
@ -33,6 +33,7 @@ extern crate sig;
|
|||
use backtrace::Backtrace;
|
||||
use servo::Browser;
|
||||
use servo::compositing::windowing::WindowEvent;
|
||||
use servo::config;
|
||||
use servo::config::opts::{self, ArgumentParsingResult};
|
||||
use servo::config::servo_version;
|
||||
use std::env;
|
||||
|
@ -219,8 +220,9 @@ fn args() -> Vec<String> {
|
|||
use std::fs::File;
|
||||
use std::io::{BufRead, BufReader};
|
||||
|
||||
const PARAMS_FILE: &'static str = "/sdcard/servo/android_params";
|
||||
match File::open(PARAMS_FILE) {
|
||||
let mut params_file = config::basedir::default_config_dir().unwrap();
|
||||
params_file.push("android_params");
|
||||
match File::open(params_file.to_str().unwrap()) {
|
||||
Ok(f) => {
|
||||
let mut vec = Vec::new();
|
||||
let file = BufReader::new(&f);
|
||||
|
@ -236,7 +238,7 @@ fn args() -> Vec<String> {
|
|||
},
|
||||
Err(e) => {
|
||||
debug!("Failed to open params file '{}': {}",
|
||||
PARAMS_FILE,
|
||||
params_file.to_str().unwrap(),
|
||||
Error::description(&e));
|
||||
vec!["servo".to_owned(), "http://en.wikipedia.org/wiki/Rust".to_owned()]
|
||||
},
|
||||
|
|
|
@ -28,7 +28,6 @@ from servo.command_base import (
|
|||
BuildNotFound,
|
||||
cd,
|
||||
CommandBase,
|
||||
find_dep_path_newest,
|
||||
is_macosx,
|
||||
is_windows,
|
||||
get_browserhtml_path,
|
||||
|
@ -143,34 +142,12 @@ class PackageCommands(CommandBase):
|
|||
target_dir = path.dirname(binary_path)
|
||||
if android:
|
||||
if dev:
|
||||
env["NDK_DEBUG"] = "1"
|
||||
env["ANT_FLAVOR"] = "debug"
|
||||
dev_flag = "-d"
|
||||
task_name = "assembleArmDebug"
|
||||
else:
|
||||
env["ANT_FLAVOR"] = "release"
|
||||
dev_flag = ""
|
||||
|
||||
output_apk = "{}.apk".format(binary_path)
|
||||
|
||||
dir_to_apk = path.join(target_dir, "apk")
|
||||
if path.exists(dir_to_apk):
|
||||
print("Cleaning up from previous packaging")
|
||||
delete(dir_to_apk)
|
||||
shutil.copytree(path.join(dir_to_root, "support", "android", "apk"), dir_to_apk)
|
||||
|
||||
blurdroid_path = find_dep_path_newest('blurdroid', binary_path)
|
||||
if blurdroid_path is None:
|
||||
print("Could not find blurdroid package; perhaps you haven't built Servo.")
|
||||
return 1
|
||||
else:
|
||||
dir_to_libs = path.join(dir_to_apk, "libs")
|
||||
if not path.exists(dir_to_libs):
|
||||
os.makedirs(dir_to_libs)
|
||||
shutil.copy2(blurdroid_path + '/out/blurdroid.jar', dir_to_libs)
|
||||
task_name = "assembleArmRelease"
|
||||
try:
|
||||
with cd(path.join("support", "android", "build-apk")):
|
||||
subprocess.check_call(["cargo", "run", "--", dev_flag, "-o", output_apk, "-t", target_dir,
|
||||
"-r", dir_to_root], env=env)
|
||||
with cd(path.join("support", "android", "apk")):
|
||||
subprocess.check_call(["./gradlew", "--no-daemon", task_name], env=env)
|
||||
except subprocess.CalledProcessError as e:
|
||||
print("Packaging Android exited with return value %d" % e.returncode)
|
||||
return e.returncode
|
||||
|
|
|
@ -83,11 +83,12 @@ class PostBuildCommands(CommandBase):
|
|||
return
|
||||
script = [
|
||||
"am force-stop com.mozilla.servo",
|
||||
"echo servo >/sdcard/servo/android_params"
|
||||
"echo servo >/sdcard/Android/data/com.mozilla.servo/files/android_params"
|
||||
]
|
||||
for param in params:
|
||||
script += [
|
||||
"echo '%s' >>/sdcard/servo/android_params" % param.replace("'", "\\'")
|
||||
"echo '%s' >>/sdcard/Android/data/com.mozilla.servo/files/android_params"
|
||||
% param.replace("'", "\\'")
|
||||
]
|
||||
script += [
|
||||
"am start com.mozilla.servo/com.mozilla.servo.MainActivity",
|
||||
|
|
|
@ -63,5 +63,7 @@
|
|||
"session-history.max-length": 20,
|
||||
"shell.builtin-key-shortcuts.enabled": true,
|
||||
"shell.homepage": "https://servo.org",
|
||||
"shell.keep_screen_on.enabled": false,
|
||||
"shell.native-orientation": "both",
|
||||
"shell.native-titlebar.enabled": true
|
||||
}
|
||||
|
|
299
support/android/apk/app/build.gradle
Normal file
299
support/android/apk/app/build.gradle
Normal file
|
@ -0,0 +1,299 @@
|
|||
apply plugin: 'com.android.application'
|
||||
|
||||
import groovy.io.FileType
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
|
||||
android {
|
||||
compileSdkVersion 25
|
||||
buildToolsVersion "25.0.2"
|
||||
|
||||
defaultConfig {
|
||||
applicationId "com.mozilla.servo"
|
||||
minSdkVersion 18
|
||||
targetSdkVersion 25
|
||||
versionCode 1
|
||||
versionName "1.0.0"
|
||||
jackOptions {
|
||||
enabled true
|
||||
}
|
||||
}
|
||||
|
||||
compileOptions {
|
||||
incremental false
|
||||
}
|
||||
|
||||
splits {
|
||||
density {
|
||||
enable false
|
||||
}
|
||||
abi {
|
||||
enable false
|
||||
}
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
main {
|
||||
java.srcDirs = ['src/main/java']
|
||||
assets.srcDirs = ['../../../../resources']
|
||||
}
|
||||
armDebug {
|
||||
jniLibs.srcDirs = [getJniLibsPath(true, 'arm')]
|
||||
}
|
||||
armRelease {
|
||||
jniLibs.srcDirs = [getJniLibsPath(false, 'arm')]
|
||||
}
|
||||
armv7Debug {
|
||||
jniLibs.srcDirs = [getJniLibsPath(true, 'armv7')]
|
||||
}
|
||||
armv7Release {
|
||||
jniLibs.srcDirs = [getJniLibsPath(false, 'armv7')]
|
||||
}
|
||||
arm64Debug {
|
||||
jniLibs.srcDirs = [getJniLibsPath(true, 'arm64')]
|
||||
}
|
||||
arm64Release {
|
||||
jniLibs.srcDirs = [getJniLibsPath(false, 'arm64')]
|
||||
}
|
||||
x86Debug {
|
||||
jniLibs.srcDirs = [getJniLibsPath(true, 'x86')]
|
||||
}
|
||||
x86Release {
|
||||
jniLibs.srcDirs = [getJniLibsPath(false, 'x86')]
|
||||
}
|
||||
}
|
||||
|
||||
buildTypes {
|
||||
// Default debug and release build types are used as templates
|
||||
debug {
|
||||
jniDebuggable true
|
||||
}
|
||||
|
||||
release {
|
||||
signingConfig signingConfigs.debug // Change this to sign with a production key
|
||||
minifyEnabled false
|
||||
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
|
||||
}
|
||||
|
||||
// Custom build types
|
||||
armDebug {
|
||||
initWith(debug)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('arm')
|
||||
}
|
||||
}
|
||||
armRelease {
|
||||
initWith(release)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('arm')
|
||||
}
|
||||
}
|
||||
armv7Debug {
|
||||
initWith(debug)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('armv7')
|
||||
}
|
||||
}
|
||||
armv7Release {
|
||||
initWith(release)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('armv7')
|
||||
}
|
||||
}
|
||||
arm64Debug {
|
||||
initWith(debug)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('arm64')
|
||||
}
|
||||
}
|
||||
arm64Release {
|
||||
initWith(release)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('arm64')
|
||||
}
|
||||
}
|
||||
x86Debug {
|
||||
initWith(debug)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('x86')
|
||||
}
|
||||
}
|
||||
x86Release {
|
||||
initWith(release)
|
||||
ndk {
|
||||
abiFilters getNDKAbi('x86')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Ignore default 'debug' and 'release' build types
|
||||
variantFilter { variant ->
|
||||
if(variant.buildType.name.equals('release') || variant.buildType.name.equals('debug')) {
|
||||
variant.setIgnore(true);
|
||||
}
|
||||
}
|
||||
|
||||
// Define apk output directory
|
||||
applicationVariants.all { variant ->
|
||||
variant.outputs.each { output ->
|
||||
def name = variant.buildType.name
|
||||
output.outputFile = new File(getApkPath(isDebug(name), getArch(name)))
|
||||
}
|
||||
}
|
||||
|
||||
// Call our custom NDK Build task using flavor parameters
|
||||
tasks.all {
|
||||
compileTask ->
|
||||
Pattern pattern = Pattern.compile(/^transformJackWithJackFor([\w\d]+)(Debug|Release)/);
|
||||
Matcher matcher = pattern.matcher(compileTask.name);
|
||||
// You can use this alternative pattern when jackCompiler is disabled
|
||||
// Pattern pattern = Pattern.compile(/^compile([\w\d]+)(Debug|Release)/);
|
||||
// Matcher matcher = pattern.matcher(compileTask.name);
|
||||
if (!matcher.find()) {
|
||||
return
|
||||
}
|
||||
|
||||
def taskName = "ndkbuild" + compileTask.name
|
||||
tasks.create(name: taskName, type: Exec) {
|
||||
def debug = compileTask.name.contains("Debug")
|
||||
def arch = matcher.group(1)
|
||||
commandLine getNdkDir(),
|
||||
'APP_BUILD_SCRIPT=../jni/Android.mk',
|
||||
'NDK_APPLICATION_MK=../jni/Application.mk',
|
||||
'NDK_LIBS_OUT=' + getJniLibsPath(debug, arch),
|
||||
'NDK_OUT=' + getTargetDir(debug, arch) + '/apk/obj',
|
||||
'NDK_DEBUG=' + (debug ? '1' : '0'),
|
||||
'APP_ABI=' + getNDKAbi(arch),
|
||||
'SERVO_TARGET_DIR=' + getTargetDir(debug, arch)
|
||||
}
|
||||
|
||||
compileTask.dependsOn taskName
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
//Dependency list
|
||||
def deps = [
|
||||
new ServoDependency("blurdroid.jar", "blurdroid")
|
||||
]
|
||||
|
||||
// Iterate all build types and dependencies
|
||||
// For each dependency call the proper compile command and set the correct dependency path
|
||||
def list = ['arm', 'armv7', 'arm64', 'x86']
|
||||
for (arch in list) {
|
||||
for (debug in [true, false]) {
|
||||
String basePath = getTargetDir(debug, arch) + "/build"
|
||||
String cmd = arch + (debug ? "Debug" : "Release") + "Compile"
|
||||
|
||||
for (ServoDependency dep: deps) {
|
||||
String path = findDependencyPath(basePath, dep.fileName, dep.folderFilter)
|
||||
if (path) {
|
||||
"${cmd}" files(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Utility methods
|
||||
String getTargetDir(boolean debug, String arch) {
|
||||
def basePath = project.rootDir.getParentFile().getParentFile().getParentFile().absolutePath
|
||||
return basePath + '/target/' + getRustTarget(arch) + '/' + (debug ? 'debug' : 'release')
|
||||
}
|
||||
|
||||
String getApkPath(boolean debug, String arch) {
|
||||
return getTargetDir(debug, arch) + '/servo.apk'
|
||||
}
|
||||
|
||||
String getJniLibsPath(boolean debug, String arch) {
|
||||
return getTargetDir(debug, arch) + '/apk/jniLibs'
|
||||
}
|
||||
|
||||
String getArch(String buildType) {
|
||||
return buildType.replaceAll(/(Debug|Release)/, '')
|
||||
}
|
||||
|
||||
boolean isDebug(String buildType) {
|
||||
return buildType.contains("Debug")
|
||||
}
|
||||
|
||||
String getRustTarget(String arch) {
|
||||
switch (arch.toLowerCase()) {
|
||||
case 'arm' : return 'arm-linux-androideabi'
|
||||
case 'armv7' : return 'armv7-linux-androideabi'
|
||||
case 'arm64' : return 'aarch64-linux-android'
|
||||
case 'x86' : return 'x86'
|
||||
default: throw new GradleException("Invalid target architecture " + arch)
|
||||
}
|
||||
}
|
||||
|
||||
String getNDKAbi(String arch) {
|
||||
switch (arch.toLowerCase()) {
|
||||
case 'arm' : return 'armeabi'
|
||||
case 'armv7' : return 'armeabi-v7a'
|
||||
case 'arm64' : return 'arm64-v8a'
|
||||
case 'x86' : return 'x86'
|
||||
default: throw new GradleException("Invalid target architecture " + arch)
|
||||
}
|
||||
}
|
||||
|
||||
String getNdkDir() {
|
||||
// Read environment variable used in rust build system
|
||||
String ndkDir = System.getenv('ANDROID_NDK')
|
||||
if (ndkDir == null) {
|
||||
ndkDir = System.getenv('ANDROID_NDK_HOME')
|
||||
}
|
||||
if (ndkDir == null) {
|
||||
// Fallback to ndkDir in local.properties
|
||||
def rootDir = project.rootDir
|
||||
def localProperties = new File(rootDir, "local.properties")
|
||||
Properties properties = new Properties()
|
||||
localProperties.withInputStream { instr ->
|
||||
properties.load(instr)
|
||||
}
|
||||
|
||||
ndkDir = properties.getProperty('ndk.dir')
|
||||
}
|
||||
|
||||
def cmd = Os.isFamily(Os.FAMILY_WINDOWS) ? 'ndk-build.cmd' : 'ndk-build'
|
||||
def ndkbuild = new File(ndkDir + '/' + cmd)
|
||||
if (!ndkbuild.exists()) {
|
||||
throw new GradleException("Please set a valid NDK_HOME environment variable" +
|
||||
"or ndk.dir path in local.properties file");
|
||||
}
|
||||
return ndkbuild.absolutePath
|
||||
}
|
||||
|
||||
// folderFilter can be used to improve search performance
|
||||
String findDependencyPath(String basePath, String filename, String folderFilter) {
|
||||
File path = new File(basePath);
|
||||
if (!path.exists()) {
|
||||
return ''
|
||||
}
|
||||
|
||||
if (folderFilter) {
|
||||
path.eachDir {
|
||||
if (it.name.contains(folderFilter)) {
|
||||
path = new File(it.absolutePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
def result = ''
|
||||
path.eachFileRecurse(FileType.FILES) {
|
||||
if(it.name.equals(filename)) {
|
||||
result = it.absolutePath
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
class ServoDependency {
|
||||
public ServoDependency(String fileName, String folderFilter = null) {
|
||||
this.fileName = fileName;
|
||||
this.folderFilter = folderFilter;
|
||||
}
|
||||
public String fileName;
|
||||
public String folderFilter;
|
||||
}
|
|
@ -1,13 +1,9 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- BEGIN_INCLUDE(manifest) -->
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.mozilla.servo"
|
||||
android:versionCode="1"
|
||||
android:versionName="1.0">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="auto"
|
||||
package="com.mozilla.servo">
|
||||
|
||||
<uses-sdk android:minSdkVersion="18" />
|
||||
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true"></uses-feature>
|
||||
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
|
||||
<uses-feature android:name="android.hardware.bluetooth_le" android:required="true"/>
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
|
@ -16,9 +12,10 @@
|
|||
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
|
||||
|
||||
<application android:label="Servo" android:icon="@mipmap/servo">
|
||||
<activity android:name="com.mozilla.servo.MainActivity"
|
||||
<activity android:name=".MainActivity"
|
||||
android:label="Servo"
|
||||
android:configChanges="orientation|keyboardHidden">
|
||||
android:configChanges="orientation|keyboardHidden|screenSize">
|
||||
<meta-data android:name="android.app.lib_name" android:value="servo" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
@ -0,0 +1,299 @@
|
|||
package com.mozilla.servo;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.os.Bundle;
|
||||
import android.os.Environment;
|
||||
import android.os.Handler;
|
||||
import android.os.PowerManager;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.webkit.URLUtil;
|
||||
|
||||
import com.mozilla.servo.BuildConfig;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.System;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
|
||||
public class MainActivity extends android.app.NativeActivity {
|
||||
private static final String LOGTAG = "Servo";
|
||||
private boolean mFullScreen = false;
|
||||
private static final String PREF_KEY_RESOURCES_SYNC = "res_sync_v";
|
||||
|
||||
static {
|
||||
Log.i(LOGTAG, "Loading the NativeActivity");
|
||||
|
||||
// Libaries should be loaded in reverse dependency order
|
||||
System.loadLibrary("c++_shared");
|
||||
System.loadLibrary("servo");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
try {
|
||||
extractAssets();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
final Intent intent = getIntent();
|
||||
if (intent != null && intent.getAction().equals(Intent.ACTION_VIEW)) {
|
||||
final String url = intent.getDataString();
|
||||
if (url != null && URLUtil.isValidUrl(url)) {
|
||||
Log.d(LOGTAG, "Received url "+url);
|
||||
set_url(url);
|
||||
}
|
||||
}
|
||||
|
||||
JSONObject preferences = loadPreferences();
|
||||
boolean keepScreenOn = preferences.optBoolean("shell.keep_screen_on.enabled", false);
|
||||
mFullScreen = !preferences.optBoolean("shell.native-titlebar.enabled", false);
|
||||
String orientation = preferences.optString("shell.native-orientation", "both");
|
||||
|
||||
// Handle orientation preference
|
||||
if (orientation.equalsIgnoreCase("portrait")) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
|
||||
}
|
||||
else if (orientation.equalsIgnoreCase("landscape")) {
|
||||
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
|
||||
}
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// Handle keep screen on preference
|
||||
if (keepScreenOn) {
|
||||
keepScreenOn();
|
||||
}
|
||||
|
||||
// Handle full screen preference
|
||||
if (mFullScreen) {
|
||||
addFullScreenListener();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
Log.d(LOGTAG, "onStop");
|
||||
super.onStop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
Log.d(LOGTAG, "onPause");
|
||||
super.onPause();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
Log.d(LOGTAG, "onPause");
|
||||
if (mFullScreen) {
|
||||
setFullScreen();
|
||||
}
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasFocus) {
|
||||
super.onWindowFocusChanged(hasFocus);
|
||||
if (hasFocus && mFullScreen) {
|
||||
setFullScreen();
|
||||
}
|
||||
}
|
||||
|
||||
// keep the device's screen turned on and bright.
|
||||
private void keepScreenOn() {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
||||
}
|
||||
|
||||
// Dim toolbar and make the view fullscreen
|
||||
private void setFullScreen() {
|
||||
int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // Hides navigation bar
|
||||
| View.SYSTEM_UI_FLAG_FULLSCREEN; // Hides status bar
|
||||
if( android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
|
||||
flags |= getImmersiveFlag();
|
||||
} else {
|
||||
flags |= View.SYSTEM_UI_FLAG_LOW_PROFILE;
|
||||
}
|
||||
getWindow().getDecorView().setSystemUiVisibility(flags);
|
||||
}
|
||||
|
||||
@TargetApi(19)
|
||||
private int getImmersiveFlag() {
|
||||
return View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
|
||||
}
|
||||
|
||||
private void addFullScreenListener() {
|
||||
View decorView = getWindow().getDecorView();
|
||||
decorView.setOnSystemUiVisibilityChangeListener(
|
||||
new View.OnSystemUiVisibilityChangeListener() {
|
||||
public void onSystemUiVisibilityChange(int visibility) {
|
||||
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
||||
setFullScreen();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private String loadAsset(String file) {
|
||||
InputStream is = null;
|
||||
BufferedReader reader = null;
|
||||
try {
|
||||
is = getAssets().open(file);
|
||||
reader = new BufferedReader(new InputStreamReader(is));
|
||||
StringBuilder result = new StringBuilder();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
result.append(line).append('\n');
|
||||
}
|
||||
return result.toString();
|
||||
} catch (IOException e) {
|
||||
Log.e(LOGTAG, Log.getStackTraceString(e));
|
||||
return null;
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
if (reader != null) {
|
||||
reader.close();
|
||||
}
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, Log.getStackTraceString(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject loadPreferences() {
|
||||
String json = loadAsset("prefs.json");
|
||||
try {
|
||||
return new JSONObject(json);
|
||||
} catch (JSONException e) {
|
||||
Log.e(LOGTAG, Log.getStackTraceString(e));
|
||||
return new JSONObject();
|
||||
}
|
||||
}
|
||||
|
||||
private boolean needsToExtractAssets(String path) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
int version = BuildConfig.VERSION_CODE;
|
||||
|
||||
if (!new File(path).exists()) {
|
||||
// Assets folder doesn't exist, resources need to be copied
|
||||
prefs.edit().putInt(PREF_KEY_RESOURCES_SYNC, version).apply();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (version != prefs.getInt(PREF_KEY_RESOURCES_SYNC, -1)) {
|
||||
// Also force a reextract when the version changes and the resources may be updated
|
||||
// This can be improved by generating a hash or version number of the resources
|
||||
// instead of using version code of the app
|
||||
prefs.edit().putInt(PREF_KEY_RESOURCES_SYNC, version).apply();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private File getAppDataDir() {
|
||||
File file = getExternalFilesDir(null);
|
||||
return file != null ? file : getFilesDir();
|
||||
}
|
||||
/**
|
||||
* extracts assets/ in the APK to /sdcard/servo.
|
||||
*/
|
||||
private void extractAssets() throws IOException {
|
||||
String path = getAppDataDir().getAbsolutePath();
|
||||
if (!needsToExtractAssets(path)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ZipFile zipFile = null;
|
||||
File targetDir = new File(path);
|
||||
try {
|
||||
zipFile = new ZipFile(this.getApplicationInfo().sourceDir);
|
||||
for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
if (entry.isDirectory() || !entry.getName().startsWith("assets/")) {
|
||||
continue;
|
||||
}
|
||||
File targetFile = new File(targetDir, entry.getName().substring("assets/".length()));
|
||||
targetFile.getParentFile().mkdirs();
|
||||
byte[] tempBuffer = new byte[(int)entry.getSize()];
|
||||
BufferedInputStream is = null;
|
||||
FileOutputStream os = null;
|
||||
try {
|
||||
is = new BufferedInputStream(zipFile.getInputStream(entry));
|
||||
os = new FileOutputStream(targetFile);
|
||||
is.read(tempBuffer);
|
||||
os.write(tempBuffer);
|
||||
} finally {
|
||||
try {
|
||||
if (is != null) {
|
||||
is.close();
|
||||
}
|
||||
if (os != null) {
|
||||
os.close();
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
Log.e(LOGTAG, Log.getStackTraceString(ex));
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
try {
|
||||
if (zipFile != null) {
|
||||
zipFile.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, Log.getStackTraceString(e));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void set_url(String url) {
|
||||
try {
|
||||
File file = new File(getAppDataDir() + "/android_params");
|
||||
if (!file.exists()) {
|
||||
file.createNewFile();
|
||||
}
|
||||
PrintStream out = new PrintStream(new FileOutputStream(file, false));
|
||||
out.println("# The first line here should be the \"servo\" argument (without quotes) and the");
|
||||
out.println("# last should be the URL to load.");
|
||||
out.println("# Blank lines and those beginning with a '#' are ignored.");
|
||||
out.println("# Each line should be a separate parameter as would be parsed by the shell.");
|
||||
out.println("# For example, \"servo -p 10 http://en.wikipedia.org/wiki/Rust\" would take 4");
|
||||
out.println("# lines (the \"-p\" and \"10\" are separate even though they are related).");
|
||||
out.println("servo");
|
||||
out.println("-w");
|
||||
String absUrl = url.replace("file:///storage/emulated/0/", "/sdcard/");
|
||||
out.println(absUrl);
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (Exception e) {
|
||||
Log.e(LOGTAG, Log.getStackTraceString(e));
|
||||
}
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 509 KiB After Width: | Height: | Size: 509 KiB |
17
support/android/apk/build.gradle
Normal file
17
support/android/apk/build.gradle
Normal file
|
@ -0,0 +1,17 @@
|
|||
// Top-level build file where you can add configuration options common to all sub-projects/modules.
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
dependencies {
|
||||
classpath 'com.android.tools.build:gradle:2.2.3'
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
}
|
||||
|
||||
buildDir = rootDir.absolutePath + "/../../../target/gradle"
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project name="Servo" default="help">
|
||||
|
||||
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||
It contains the path to the SDK. It should *NOT* be checked into
|
||||
Version Control Systems. -->
|
||||
<property file="local.properties" />
|
||||
|
||||
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||
'android' tool to add properties to it.
|
||||
This is the place to change some Ant specific build properties.
|
||||
Here are some properties you may want to change/update:
|
||||
|
||||
source.dir
|
||||
The name of the source directory. Default is 'src'.
|
||||
out.dir
|
||||
The name of the output directory. Default is 'bin'.
|
||||
|
||||
For other overridable properties, look at the beginning of the rules
|
||||
files in the SDK, at tools/ant/build.xml
|
||||
|
||||
Properties related to the SDK location or the project target should
|
||||
be updated using the 'android' tool with the 'update' action.
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems.
|
||||
|
||||
-->
|
||||
<property file="ant.properties" />
|
||||
|
||||
<!-- if sdk.dir was not set from one of the property file, then
|
||||
get it from the ANDROID_HOME env var.
|
||||
This must be done before we load project.properties since
|
||||
the proguard config can use sdk.dir -->
|
||||
<property environment="env" />
|
||||
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||
<isset property="env.ANDROID_HOME" />
|
||||
</condition>
|
||||
|
||||
<!-- The project.properties file is created and updated by the 'android'
|
||||
tool, as well as ADT.
|
||||
|
||||
This contains project specific properties such as project target, and library
|
||||
dependencies. Lower level build properties are stored in ant.properties
|
||||
(or in .classpath for Eclipse projects).
|
||||
|
||||
This file is an integral part of the build system for your
|
||||
application and should be checked into Version Control Systems. -->
|
||||
<loadproperties srcFile="project.properties" />
|
||||
|
||||
<!-- quick check on sdk.dir -->
|
||||
<fail
|
||||
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||
unless="sdk.dir"
|
||||
/>
|
||||
|
||||
<!--
|
||||
Import per project custom build rules if present at the root of the project.
|
||||
This is the place to put custom intermediary targets such as:
|
||||
-pre-build
|
||||
-pre-compile
|
||||
-post-compile (This is typically used for code obfuscation.
|
||||
Compiled code location: ${out.classes.absolute.dir}
|
||||
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||
-post-package
|
||||
-post-build
|
||||
-pre-clean
|
||||
-->
|
||||
<import file="custom_rules.xml" optional="true" />
|
||||
|
||||
<!-- Import the actual build file.
|
||||
|
||||
To customize existing targets, there are two options:
|
||||
- Customize only one target:
|
||||
- copy/paste the target into this file, *before* the
|
||||
<import> task.
|
||||
- customize it to your needs.
|
||||
- Customize the whole content of build.xml
|
||||
- copy/paste the content of the rules files (minus the top node)
|
||||
into this file, replacing the <import> task.
|
||||
- customize to your needs.
|
||||
|
||||
***********************
|
||||
****** IMPORTANT ******
|
||||
***********************
|
||||
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||
in order to avoid having your file be overridden by tools such as "android update project"
|
||||
-->
|
||||
<!-- version-tag: 1 -->
|
||||
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||
|
||||
</project>
|
BIN
support/android/apk/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
BIN
support/android/apk/gradle/wrapper/gradle-wrapper.jar
vendored
Normal file
Binary file not shown.
5
support/android/apk/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
5
support/android/apk/gradle/wrapper/gradle-wrapper.properties
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip
|
160
support/android/apk/gradlew
vendored
Executable file
160
support/android/apk/gradlew
vendored
Executable file
|
@ -0,0 +1,160 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
##############################################################################
|
||||
|
||||
# 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
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
|
||||
function splitJvmOpts() {
|
||||
JVM_OPTS=("$@")
|
||||
}
|
||||
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
|
||||
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
|
||||
|
||||
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"
|
90
support/android/apk/gradlew.bat
vendored
Normal file
90
support/android/apk/gradlew.bat
vendored
Normal file
|
@ -0,0 +1,90 @@
|
|||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@rem
|
||||
@rem ##########################################################################
|
||||
|
||||
@rem Set local scope for the variables with windows NT shell
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:findJavaFromJavaHome
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
echo.
|
||||
echo Please set the JAVA_HOME variable in your environment to match the
|
||||
echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windowz variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
if "%@eval[2+2]" == "4" goto 4NT_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
goto execute
|
||||
|
||||
:4NT_args
|
||||
@rem Get arguments from the 4NT Shell from JP Software
|
||||
set CMD_LINE_ARGS=%$
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
:omega
|
|
@ -12,11 +12,11 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
MY_LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
LOCAL_PATH:= $(SERVO_TARGET_DIR)
|
||||
LOCAL_MODULE := servo
|
||||
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libmain.so
|
||||
LOCAL_SRC_FILES := libservo.so
|
||||
include $(PREBUILT_SHARED_LIBRARY)
|
||||
|
||||
# $(call import-module)
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
APP_ABI := armeabi
|
||||
APP_PLATFORM := $(ANDROID_PLATFORM)
|
||||
NDK_TOOLCHAIN_VERSION := 4.9
|
||||
APP_MODULES := c++_shared servo
|
||||
APP_PLATFORM := android-18
|
||||
APP_STL:= c++_shared
|
||||
|
|
1
support/android/apk/settings.gradle
Normal file
1
support/android/apk/settings.gradle
Normal file
|
@ -0,0 +1 @@
|
|||
include ':app'
|
|
@ -1,118 +0,0 @@
|
|||
package com.mozilla.servo;
|
||||
import android.app.NativeActivity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.System;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
|
||||
public class MainActivity extends android.app.NativeActivity {
|
||||
private static final String LOGTAG="ServoWrapper";
|
||||
static {
|
||||
Log.i(LOGTAG, "Loading the NativeActivity");
|
||||
// libmain.so contains all of Servo native code with the injected glue.
|
||||
System.loadLibrary("main");
|
||||
Log.i(LOGTAG, "libmain.so loaded");
|
||||
}
|
||||
|
||||
private void set_url(String url) {
|
||||
try {
|
||||
PrintStream out = new PrintStream(new FileOutputStream("/sdcard/servo/android_params"));
|
||||
out.println("# The first line here should be the \"servo\" argument (without quotes) and the");
|
||||
out.println("# last should be the URL to load.");
|
||||
out.println("# Blank lines and those beginning with a '#' are ignored.");
|
||||
out.println("# Each line should be a separate parameter as would be parsed by the shell.");
|
||||
out.println("# For example, \"servo -p 10 http://en.wikipedia.org/wiki/Rust\" would take 4");
|
||||
out.println("# lines (the \"-p\" and \"10\" are separate even though they are related).");
|
||||
out.println("servo");
|
||||
out.println("-w");
|
||||
String absUrl = url.replace("file:///storage/emulated/0/", "/sdcard/");
|
||||
out.println(absUrl);
|
||||
out.flush();
|
||||
out.close();
|
||||
} catch (FileNotFoundException e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
if (needsToExtractAssets()) {
|
||||
try {
|
||||
extractAssets();
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
super.onCreate(savedInstanceState);
|
||||
final Intent intent = getIntent();
|
||||
if (intent.getAction().equals(Intent.ACTION_VIEW)) {
|
||||
final String url = intent.getDataString();
|
||||
Log.d(LOGTAG, "Received url "+url);
|
||||
set_url(url);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStop() {
|
||||
super.onStop(); // Always call the superclass method first
|
||||
|
||||
Log.d(LOGTAG, "got onStop; finishing servo activity");
|
||||
finish();
|
||||
|
||||
// Glutin and the Java wrapper libraries that we use currently do not support restoring
|
||||
// Servo after Android has sent it to the background, as the resources were reclaimed.
|
||||
// Until we either address that in glutin or move to a library that supports recreating
|
||||
// the native resources after being restored, we just forcibly shut Servo down when it
|
||||
// is sent to the background.
|
||||
int pid = android.os.Process.myPid();
|
||||
android.os.Process.killProcess(pid);
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
private boolean needsToExtractAssets() {
|
||||
// todo: also force a reextract when the resources are updated.
|
||||
return !(new File("/sdcard/servo").exists());
|
||||
}
|
||||
|
||||
/**
|
||||
* extracts assets/ in the APK to /sdcard/servo.
|
||||
*/
|
||||
private void extractAssets() throws IOException {
|
||||
ZipFile zipFile = null;
|
||||
File targetDir = new File("/sdcard/servo");
|
||||
try {
|
||||
zipFile = new ZipFile(this.getApplicationInfo().sourceDir);
|
||||
for (Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements(); ) {
|
||||
ZipEntry entry = e.nextElement();
|
||||
if (entry.isDirectory() || !entry.getName().startsWith("assets/")) {
|
||||
continue;
|
||||
}
|
||||
File targetFile = new File(targetDir, entry.getName().substring("assets/".length()));
|
||||
targetFile.getParentFile().mkdirs();
|
||||
byte[] tempBuffer = new byte[(int)entry.getSize()];
|
||||
BufferedInputStream is = null;
|
||||
FileOutputStream os = null;
|
||||
try {
|
||||
is = new BufferedInputStream(zipFile.getInputStream(entry));
|
||||
os = new FileOutputStream(targetFile);
|
||||
is.read(tempBuffer);
|
||||
os.write(tempBuffer);
|
||||
} finally {
|
||||
if (is != null) is.close();
|
||||
if (os != null) os.close();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
if (zipFile != null) zipFile.close();
|
||||
}
|
||||
}
|
||||
}
|
35
support/android/build-apk/Cargo.lock
generated
35
support/android/build-apk/Cargo.lock
generated
|
@ -1,35 +0,0 @@
|
|||
[root]
|
||||
name = "build-apk"
|
||||
version = "0.0.1"
|
||||
dependencies = [
|
||||
"walkdir 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kernel32-sys"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "walkdir"
|
||||
version = "0.1.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"winapi 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
||||
[[package]]
|
||||
name = "winapi-build"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
[package]
|
||||
|
||||
name = "build-apk"
|
||||
version = "0.0.1"
|
||||
authors = ["Pierre Krieger <pierre.krieger1708@gmail.com>", "The Servo Project Developers"]
|
||||
license = "MPL-2.0"
|
||||
|
||||
[[bin]]
|
||||
name = "build-apk"
|
||||
path = "src/main.rs"
|
||||
test = false
|
||||
doc = false
|
||||
bench = false
|
||||
|
||||
[dependencies]
|
||||
walkdir = "1.0"
|
|
@ -1,299 +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 http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
extern crate walkdir;
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::fs::DirBuilder;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process;
|
||||
use std::process::{Command, Stdio};
|
||||
use walkdir::WalkDir;
|
||||
|
||||
fn main() {
|
||||
let (args, passthrough) = parse_arguments();
|
||||
|
||||
// Find all the native shared libraries that exist in the target directory.
|
||||
let mut native_shared_libs = find_native_libs(&args);
|
||||
|
||||
// Get the SDK path from the ANDROID_HOME env.
|
||||
let sdk_path = env::var("ANDROID_HOME").ok().expect("Please set the ANDROID_HOME environment variable");
|
||||
let sdk_path = Path::new(&sdk_path);
|
||||
|
||||
// Get the NDK path from NDK_HOME env.
|
||||
let ndk_path = env::var("NDK_HOME").ok().expect("Please set the NDK_HOME environment variable");
|
||||
let ndk_path = Path::new(&ndk_path);
|
||||
|
||||
// Get the target android platform from ANDROID_PLATFORM env. Expecting "android-{version}"
|
||||
let android_platform = env::var("ANDROID_PLATFORM")
|
||||
.ok()
|
||||
.expect("Please set the ANDROID_PLATFORM environment variable");
|
||||
|
||||
// Add the C++ runtime .so
|
||||
{
|
||||
let libcpp_base_path = ndk_path.join("sources").join("cxx-stl").join("llvm-libc++").join("libs");
|
||||
let libcpp_filename = "libc++_shared.so";
|
||||
let libcpp_path = libcpp_base_path.join("armeabi").join(libcpp_filename);
|
||||
native_shared_libs.insert(libcpp_filename.to_string(), libcpp_path);
|
||||
}
|
||||
|
||||
// Get the standalone NDK path from NDK_STANDALONE env.
|
||||
// let standalone_path = env::var("NDK_STANDALONE").ok().unwrap_or("/opt/ndk_standalone".to_string());
|
||||
// let standalone_path = Path::new(&standalone_path);
|
||||
|
||||
let debug = passthrough.contains(&"-d".to_string());
|
||||
|
||||
// Set the build directory that will contain all the necessary files to create the apk
|
||||
let directory = args.target_path.join("apk");
|
||||
let resdir = args.root_path.join("resources/");
|
||||
|
||||
// executing ndk-build
|
||||
env::set_var("V", "1");
|
||||
if debug {
|
||||
env::set_var("NDK_DEBUG", "1");
|
||||
env::set_var("APP_OPTIM", "0");
|
||||
} else {
|
||||
// Overrides android:debuggable propery in the .xml file.
|
||||
env::set_var("APP_OPTIM", "1");
|
||||
}
|
||||
|
||||
// Copy libservo.so into the jni folder for inclusion in the build
|
||||
// TODO: pass/detect target architecture
|
||||
{
|
||||
let source = &args.target_path.join("libservo.so");
|
||||
let target_dir = &directory.join("jni").join("armeabi");
|
||||
let _ = DirBuilder::new().recursive(true).create(target_dir);
|
||||
let target = target_dir.join("libmain.so");
|
||||
println!("Copying the file {:?} to {:?}", source, target);
|
||||
fs::copy(source, target).unwrap();
|
||||
}
|
||||
|
||||
let ndkcmd = Command::new(ndk_path.join("ndk-build"))
|
||||
.arg("-B")
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(directory.clone())
|
||||
.status();
|
||||
if ndkcmd.is_err() || ndkcmd.unwrap().code().unwrap() != 0 {
|
||||
println!("Error while executing program `ndk-build`, or missing program.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// Copy the additional native libs into the libs directory.
|
||||
for (name, path) in native_shared_libs.iter() {
|
||||
let target = &directory.join("libs").join("armeabi").join(name);
|
||||
println!("Copying the file {:?} to {:?}", name, target);
|
||||
fs::copy(path, target).unwrap();
|
||||
}
|
||||
|
||||
// Copy over the resources
|
||||
let cpcmd = Command::new("cp")
|
||||
.arg("-R")
|
||||
.arg(&resdir)
|
||||
.arg(&directory.join("assets"))
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(directory.clone())
|
||||
.status();
|
||||
if cpcmd.is_err() || cpcmd.unwrap().code().unwrap() != 0 {
|
||||
println!("Error while copying files from the resources dir to the assets dir");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// Update the project
|
||||
let androidcmd = Command::new(sdk_path.join("tools").join("android"))
|
||||
.arg("update")
|
||||
.arg("project")
|
||||
.arg("--name")
|
||||
.arg("Servo")
|
||||
.arg("--target")
|
||||
.arg(&android_platform)
|
||||
.arg("--path")
|
||||
.arg(".")
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(directory.clone())
|
||||
.status();
|
||||
if androidcmd.is_err() || androidcmd.unwrap().code().unwrap() != 0 {
|
||||
println!("Error while updating the project with the android command");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// Build the APK
|
||||
let mut antcmd = Command::new("ant");
|
||||
if debug {
|
||||
antcmd.arg("debug");
|
||||
} else {
|
||||
antcmd.arg("release");
|
||||
}
|
||||
let antresult = antcmd.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(directory.clone())
|
||||
.status();
|
||||
if antresult.is_err() || antresult.unwrap().code().unwrap() != 0 {
|
||||
println!("Error while executing program `ant`, or missing program.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// Copying apk file to the requested output
|
||||
// Release builds also need to be signed. For now, we use a simple debug
|
||||
// signing key.
|
||||
if debug {
|
||||
fs::copy(&directory.join("bin").join("Servo-debug.apk"), &args.output).unwrap();
|
||||
} else {
|
||||
let keystore_dir = env::home_dir().expect("Please have a home directory");
|
||||
let keystore_dir = Path::new(&keystore_dir).join(".keystore");
|
||||
let keytoolcmd = Command::new("keytool")
|
||||
.arg("-list")
|
||||
.arg("-storepass")
|
||||
.arg("android")
|
||||
.arg("-alias")
|
||||
.arg("androiddebugkey")
|
||||
.arg("-keystore")
|
||||
.arg(&keystore_dir)
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(directory.clone())
|
||||
.status();
|
||||
if keytoolcmd.is_err() || keytoolcmd.unwrap().code().unwrap() != 0 {
|
||||
let keytoolcreatecmd = Command::new("keytool")
|
||||
.arg("-genkeypair")
|
||||
.arg("-keystore")
|
||||
.arg(&keystore_dir)
|
||||
.arg("-storepass")
|
||||
.arg("android")
|
||||
.arg("-alias")
|
||||
.arg("androiddebugkey")
|
||||
.arg("-keypass")
|
||||
.arg("android")
|
||||
.arg("-dname")
|
||||
.arg("CN=Android Debug,O=Android,C=US")
|
||||
.arg("-keyalg")
|
||||
.arg("RSA")
|
||||
.arg("-validity")
|
||||
.arg("365")
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(directory.clone())
|
||||
.status();
|
||||
if keytoolcreatecmd.is_err() || keytoolcreatecmd.unwrap().code().unwrap() != 0 {
|
||||
println!("Error while using `keytool` to create the debug keystore.");
|
||||
process::exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
let jarsigncmd = Command::new("jarsigner")
|
||||
.arg("-digestalg")
|
||||
.arg("SHA1")
|
||||
.arg("-sigalg")
|
||||
.arg("MD5withRSA")
|
||||
.arg("-storepass")
|
||||
.arg("android")
|
||||
.arg("-keystore")
|
||||
.arg(&keystore_dir)
|
||||
.arg(&directory.join("bin").join("Servo-release-unsigned.apk"))
|
||||
.arg("androiddebugkey")
|
||||
.stdout(Stdio::inherit())
|
||||
.stderr(Stdio::inherit())
|
||||
.current_dir(directory.clone())
|
||||
.status();
|
||||
if jarsigncmd.is_err() || jarsigncmd.unwrap().code().unwrap() != 0 {
|
||||
println!("Error while using `jarsign` to sign the APK.");
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
fs::copy(&directory.join("bin").join("Servo-release-unsigned.apk"),
|
||||
&args.output)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
struct Args {
|
||||
output: PathBuf,
|
||||
root_path: PathBuf,
|
||||
target_path: PathBuf,
|
||||
shared_libraries: HashSet<String>,
|
||||
}
|
||||
|
||||
fn parse_arguments() -> (Args, Vec<String>) {
|
||||
let mut result_output = None;
|
||||
let mut result_root_path = None;
|
||||
let mut result_target_path = None;
|
||||
let mut result_shared_libraries = HashSet::new();
|
||||
let mut result_passthrough = Vec::new();
|
||||
|
||||
let args = env::args();
|
||||
let mut args = args.skip(1);
|
||||
|
||||
loop {
|
||||
let arg = match args.next() {
|
||||
None => {
|
||||
return (Args {
|
||||
output: result_output.expect("Could not find -o argument"),
|
||||
root_path: result_root_path.expect("Could not find -r enlistment root argument"),
|
||||
target_path: result_target_path.expect("Could not find -t target path argument"),
|
||||
shared_libraries: result_shared_libraries,
|
||||
},
|
||||
result_passthrough)
|
||||
},
|
||||
Some(arg) => arg,
|
||||
};
|
||||
|
||||
match &*arg {
|
||||
"-o" => {
|
||||
result_output = Some(PathBuf::from(args.next().expect("-o must be followed by the output name")));
|
||||
},
|
||||
"-r" => {
|
||||
result_root_path = Some(PathBuf::from(args.next()
|
||||
.expect("-r must be followed by the enlistment root directory")));
|
||||
},
|
||||
"-t" => {
|
||||
result_target_path = Some(PathBuf::from(args.next()
|
||||
.expect("-t must be followed by the target output directory")));
|
||||
},
|
||||
"-l" => {
|
||||
let name = args.next().expect("-l must be followed by a library name");
|
||||
result_shared_libraries.insert(vec!["lib", &name, ".so"].concat());
|
||||
|
||||
// Also pass these through.
|
||||
result_passthrough.push(arg);
|
||||
result_passthrough.push(name);
|
||||
},
|
||||
_ => {
|
||||
if arg.starts_with("-l") {
|
||||
result_shared_libraries.insert(vec!["lib", &arg[2..], ".so"].concat());
|
||||
}
|
||||
result_passthrough.push(arg)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
fn find_native_libs(args: &Args) -> HashMap<String, PathBuf> {
|
||||
let mut native_shared_libs: HashMap<String, PathBuf> = HashMap::new();
|
||||
|
||||
// Add requested .so files
|
||||
for dir_entry in WalkDir::new(&args.target_path) {
|
||||
let dir_entry = dir_entry.unwrap();
|
||||
let path = dir_entry.path();
|
||||
|
||||
match (path.file_name(), path.extension()) {
|
||||
(Some(file_name), Some(extension)) => {
|
||||
let file_name = file_name.to_str().unwrap();
|
||||
|
||||
if file_name.starts_with("lib") && extension == "so" && args.shared_libraries.contains(file_name) {
|
||||
println!("Adding the file {:?}", file_name);
|
||||
native_shared_libs.insert(file_name.to_string(), path.to_path_buf().clone());
|
||||
break;
|
||||
}
|
||||
},
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
|
||||
native_shared_libs
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue