Commit 63349e4f authored by agrieve's avatar agrieve Committed by Commit bot

Add use_apk_split parameter to java_apk.gypi / android_apk (gn)

Testing:
- For GN, splits install and crash on start-up just like non-split version
- For GYP, tested with:
  - component=shared_library, component=static_library
  - gyp_managed_install=1, 0
  - load_library_from_zip_file=1, 0

BUG=484797

Review URL: https://codereview.chromium.org/1137313003

Cr-Commit-Position: refs/heads/master@{#330523}
parent b5bc4f06
......@@ -7,11 +7,29 @@ package org.chromium.base;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
/**
* This class provides package checking related methods.
*/
public class PackageUtils {
/**
* Retrieves the PackageInfo object for this application.
*
* @param context Any context.
* @return The PackageInfo object for this application.
*/
public static PackageInfo getOwnPackageInfo(Context context) {
PackageManager manager = context.getPackageManager();
try {
String packageName = context.getApplicationContext().getPackageName();
return manager.getPackageInfo(packageName, 0);
} catch (NameNotFoundException e) {
// Should never happen.
throw new AssertionError("Failed to retrieve own package info");
}
}
/**
* Retrieves the version of the given package installed on the device.
*
......
......@@ -4,14 +4,19 @@
package org.chromium.base.library_loader;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.os.SystemClock;
import android.util.Log;
import org.chromium.base.CalledByNative;
import org.chromium.base.CommandLine;
import org.chromium.base.JNINamespace;
import org.chromium.base.PackageUtils;
import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
......@@ -250,7 +255,7 @@ public class LibraryLoader {
// Check if the device supports memory mapping the APK file
// with executable permissions.
if (context != null) {
apkFilePath = context.getApplicationInfo().sourceDir;
apkFilePath = getLibraryApkPath(context);
if (mProbeMapApkWithExecPermission) {
mMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
} else {
......@@ -367,6 +372,31 @@ public class LibraryLoader {
}
}
// Returns whether the given split name is that of the ABI split.
private static boolean isAbiSplit(String splitName) {
// The split name for the ABI split is manually set in the build rules.
return splitName.startsWith("abi_");
}
// Returns the path to the .apk that holds the native libraries.
// This is either the main .apk, or the abi split apk.
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
private static String getLibraryApkPath(Context context) {
ApplicationInfo appInfo = context.getApplicationInfo();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return appInfo.sourceDir;
}
PackageInfo packageInfo = PackageUtils.getOwnPackageInfo(context);
if (packageInfo.splitNames != null) {
for (int i = 0; i < packageInfo.splitNames.length; ++i) {
if (isAbiSplit(packageInfo.splitNames[i])) {
return appInfo.splitSourceDirs[i];
}
}
}
return appInfo.sourceDir;
}
// Load a native shared library with the Chromium linker. If the zip file
// path is not null, the library is loaded directly from the zip file.
private void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
......
......@@ -24,6 +24,7 @@
'keystore_password%': 'chromium',
'zipalign_path%': '<(android_sdk_tools)/zipalign',
'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar',
'load_library_from_zip%': 0,
},
'inputs': [
'<(DEPTH)/build/android/gyp/finalize_apk.py',
......@@ -42,7 +43,7 @@
'--key-path=<(keystore_path)',
'--key-name=<(keystore_name)',
'--key-passwd=<(keystore_password)',
'--load-library-from-zip-file=<(load_library_from_zip_file)',
'--load-library-from-zip-file=<(load_library_from_zip)',
'--rezip-apk-jar-path=<(rezip_apk_jar_path)',
],
}
......@@ -1203,7 +1203,7 @@ template("android_apk") {
base_path = "$gen_dir/$target_name"
_build_config = "$target_gen_dir/$target_name.build_config"
resources_zip_path = "$base_path.resources.zip"
all_resources_zip_path = "$base_path.resources.all.zip"
_all_resources_zip_path = "$base_path.resources.all.zip"
jar_path = "$base_path.jar"
final_dex_path = "$gen_dir/classes.dex"
_template_name = target_name
......@@ -1221,6 +1221,15 @@ template("android_apk") {
_native_libs = []
_version_code = "1"
if (defined(invoker.version_code)) {
_version_code = invoker.version_code
}
_version_name = "Developer Build"
if (defined(invoker.version_name)) {
_version_name = invoker.version_name
}
_keystore_path = android_default_keystore_path
_keystore_name = android_default_keystore_name
_keystore_password = android_default_keystore_password
......@@ -1286,6 +1295,11 @@ template("android_apk") {
_android_manifest = invoker.android_manifest
_rebased_build_config = rebase_path(_build_config, root_build_dir)
_create_abi_split =
defined(invoker.create_abi_split) && invoker.create_abi_split
# Help GN understand that _create_abi_split is not unused (bug in GN).
assert(_create_abi_split || true)
write_build_config("${_template_name}__build_config") {
type = "android_apk"
......@@ -1314,6 +1328,7 @@ template("android_apk") {
android_manifest = _android_manifest
resource_dirs = [ "//build/android/ant/empty/res" ]
zip_path = resources_zip_path
all_resources_zip_path = _all_resources_zip_path
generate_constant_ids = true
build_config = _build_config
......@@ -1470,19 +1485,12 @@ template("android_apk") {
create_apk("${_template_name}__create") {
apk_path = _final_apk_path
android_manifest = _android_manifest
resources_zip = all_resources_zip_path
resources_zip = _all_resources_zip_path
dex_path = final_dex_path
load_library_from_apk = _load_library_from_apk
version_code = "1"
if (defined(invoker.version_code)) {
version_code = invoker.version_code
}
version_name = "Developer Build"
if (defined(invoker.version_name)) {
version_name = invoker.version_name
}
version_code = _version_code
version_name = _version_name
keystore_name = _keystore_name
keystore_path = _keystore_path
......@@ -1500,12 +1508,48 @@ template("android_apk") {
}
}
if (_native_libs != []) {
if (_native_libs != [] && !_create_abi_split) {
native_libs_dir = _native_libs_dir
deps += [ ":${_template_name}__prepare_native" ]
}
}
if (_native_libs != [] && _create_abi_split) {
_manifest_rule = "${_template_name}__split_manifest_abi_${android_app_abi}"
generate_split_manifest(_manifest_rule) {
main_manifest = _android_manifest
out_manifest =
"$gen_dir/split-manifests/${android_app_abi}/AndroidManifest.xml"
split_name = "abi_${android_app_abi}"
}
_apk_rule = "${_template_name}__split_apk_abi_${android_app_abi}"
final_deps += [ ":$_apk_rule" ]
create_apk(_apk_rule) {
_split_paths = process_file_template(
[ _final_apk_path ],
"{{source_dir}}/{{source_name_part}}-abi-${android_app_abi}.apk")
apk_path = _split_paths[0]
base_path = "$gen_dir/$_apk_rule"
manifest_outputs = get_target_outputs(":${_manifest_rule}")
android_manifest = manifest_outputs[1]
load_library_from_apk = _load_library_from_apk
version_code = _version_code
version_name = _version_name
keystore_name = _keystore_name
keystore_path = _keystore_path
keystore_password = _keystore_password
native_libs_dir = _native_libs_dir
deps = [
":${_template_name}__prepare_native",
]
}
}
group(target_name) {
deps = final_deps
if (defined(invoker.datadeps)) {
......
......@@ -126,12 +126,13 @@
'dex_path': '<(intermediate_dir)/classes.dex',
'emma_device_jar': '<(android_sdk_root)/tools/lib/emma_device.jar',
'android_manifest_path%': '<(java_in_dir)/AndroidManifest.xml',
'split_android_manifest_path': '<(intermediate_dir)/split-manifests/<(android_app_abi)/AndroidManifest.xml',
'push_stamp': '<(intermediate_dir)/push.stamp',
'link_stamp': '<(intermediate_dir)/link.stamp',
'resource_zip_path': '<(intermediate_dir)/<(_target_name).resources.zip',
'shared_resources%': 0,
'unsigned_apk_path': '<(intermediate_dir)/<(apk_name)-unsigned.apk',
'final_apk_path%': '<(PRODUCT_DIR)/apks/<(apk_name).apk',
'final_abi_split_apk_path%': '<(PRODUCT_DIR)/apks/<(apk_name)-abi-<(android_app_abi).apk',
'incomplete_apk_path': '<(intermediate_dir)/<(apk_name)-incomplete.apk',
'apk_install_record': '<(intermediate_dir)/apk_install.record.stamp',
'device_intermediate_dir': '/data/data/org.chromium.gyp_managed_install/<(_target_name)/<(CONFIGURATION_NAME)',
......@@ -144,14 +145,25 @@
'native_lib_target%': '',
'native_lib_version_name%': '',
'use_chromium_linker%' : 0,
'load_library_from_zip_file%' : 0,
'use_relocation_packer%' : 0,
'enable_chromium_linker_tests%': 0,
'is_test_apk%': 0,
'unsigned_apk_path': '<(intermediate_dir)/<(apk_name)-unsigned.apk',
'unsigned_abi_split_apk_path': '<(intermediate_dir)/<(apk_name)-abi-<(android_app_abi)-unsigned.apk',
'create_abi_split%': 0,
},
'unsigned_apk_path': '<(unsigned_apk_path)',
'unsigned_abi_split_apk_path': '<(unsigned_abi_split_apk_path)',
'create_abi_split%': '<(create_abi_split)',
'conditions': [
['gyp_managed_install == 1 and native_lib_target != ""', {
'unsigned_standalone_apk_path': '<(intermediate_dir)/<(apk_name)-standalone-unsigned.apk',
'conditions': [
['create_abi_split == 0', {
'unsigned_standalone_apk_path': '<(intermediate_dir)/<(apk_name)-standalone-unsigned.apk',
}, {
'unsigned_standalone_apk_path': '<(intermediate_dir)/<(apk_name)-abi-<(android_app_abi)-standalone-unsigned.apk',
}],
],
}, {
'unsigned_standalone_apk_path': '<(unsigned_apk_path)',
}],
......@@ -165,6 +177,13 @@
},{
'emma_instrument%': 0,
}],
# When using abi splits, the abi split is modified by
# gyp_managed_install rather than the main .apk
['create_abi_split == 1', {
'managed_input_apk_path': '<(unsigned_abi_split_apk_path)',
}, {
'managed_input_apk_path': '<(unsigned_apk_path)',
}],
],
},
'native_lib_target%': '',
......@@ -176,10 +195,15 @@
'emma_instrument%': '<(emma_instrument)',
'apk_package_native_libs_dir': '<(apk_package_native_libs_dir)',
'unsigned_standalone_apk_path': '<(unsigned_standalone_apk_path)',
'unsigned_apk_path': '<(unsigned_apk_path)',
'unsigned_abi_split_apk_path': '<(unsigned_abi_split_apk_path)',
'create_abi_split%': '<(create_abi_split)',
'managed_input_apk_path': '<(managed_input_apk_path)',
'libchromium_android_linker': 'libchromium_android_linker.>(android_product_extension)',
'extra_native_libs': [],
'native_lib_placeholder_stamp': '<(apk_package_native_libs_dir)/<(android_app_abi)/native_lib_placeholder.stamp',
'native_lib_placeholders': [],
'main_apk_name': '<(apk_name)',
},
# Pass the jar path to the apk's "fake" jar target. This would be better as
# direct_dependent_settings, but a variable set by a direct_dependent_settings
......@@ -483,9 +507,9 @@
'<(strip_additional_stamp)',
'<(pack_arm_relocations_stamp)',
],
'input_apk_path': '<(unsigned_apk_path)',
'output_apk_path': '<(unsigned_standalone_apk_path)',
'libraries_top_dir%': '<(libraries_top_dir)',
'input_apk_path': '<(managed_input_apk_path)',
},
'includes': [ 'android/create_standalone_apk_action.gypi' ],
},
......@@ -504,19 +528,87 @@
}],
],
}], # native_lib_target != ''
['gyp_managed_install == 0 or create_standalone_apk == 1', {
['gyp_managed_install == 0 or create_standalone_apk == 1 or create_abi_split == 1', {
'dependencies': [
'<(DEPTH)/build/android/rezip.gyp:rezip_apk_jar',
],
}],
['create_abi_split == 1 or gyp_managed_install == 0 or create_standalone_apk == 1', {
'actions': [
{
'action_name': 'finalize standalone apk',
'action_name': 'finalize_base',
'variables': {
'input_apk_path': '<(unsigned_standalone_apk_path)',
'output_apk_path': '<(final_apk_path)',
'conditions': [
['create_abi_split == 0', {
'input_apk_path': '<(unsigned_standalone_apk_path)',
'load_library_from_zip': '<(load_library_from_zip_file)',
}, {
'input_apk_path': '<(unsigned_apk_path)',
'load_library_from_zip': 0,
}]
],
},
'includes': [ 'android/finalize_apk_action.gypi']
},
],
'dependencies': [
'<(DEPTH)/build/android/rezip.gyp:rezip_apk_jar',
}],
['create_abi_split == 1', {
'actions': [
{
'action_name': 'generate_split_manifest_<(_target_name)',
'inputs': [
'<(DEPTH)/build/android/gyp/util/build_utils.py',
'<(DEPTH)/build/android/gyp/generate_split_manifest.py',
'<(android_manifest_path)',
],
'outputs': [
'<(split_android_manifest_path)',
],
'action': [
'python', '<(DEPTH)/build/android/gyp/generate_split_manifest.py',
'--main-manifest', '<(android_manifest_path)',
'--out-manifest', '<(split_android_manifest_path)',
'--split', 'abi_<(android_app_abi)',
],
},
{
'variables': {
'apk_name': '<(main_apk_name)-abi-<(android_app_abi)',
'asset_location': '',
'android_manifest_path': '<(split_android_manifest_path)',
},
'includes': [ 'android/package_resources_action.gypi' ],
},
{
'variables': {
'apk_name': '<(main_apk_name)-abi-<(android_app_abi)',
'apk_path': '<(unsigned_abi_split_apk_path)',
'has_code': 0,
'native_libs_dir': '<(apk_package_native_libs_dir)',
'extra_inputs': ['<(native_lib_placeholder_stamp)'],
},
'includes': ['android/apkbuilder_action.gypi'],
},
],
}],
['create_abi_split == 1 and (gyp_managed_install == 0 or create_standalone_apk == 1)', {
'actions': [
{
'action_name': 'finalize_split',
'variables': {
'load_library_from_zip': '<(load_library_from_zip_file)',
'output_apk_path': '<(final_abi_split_apk_path)',
'conditions': [
['gyp_managed_install == 1', {
'input_apk_path': '<(unsigned_standalone_apk_path)',
}, {
'input_apk_path': '<(unsigned_abi_split_apk_path)',
}],
],
},
'includes': [ 'android/finalize_apk_action.gypi']
},
],
}],
['gyp_managed_install == 1', {
......@@ -524,7 +616,8 @@
{
'action_name': 'finalize incomplete apk',
'variables': {
'input_apk_path': '<(unsigned_apk_path)',
'load_library_from_zip': 0,
'input_apk_path': '<(managed_input_apk_path)',
'output_apk_path': '<(incomplete_apk_path)',
},
'includes': [ 'android/finalize_apk_action.gypi']
......@@ -543,16 +636,27 @@
],
'action': [
'python', '<(DEPTH)/build/android/gyp/apk_install.py',
'--apk-path=<(incomplete_apk_path)',
'--build-device-configuration=<(build_device_config_path)',
'--install-record=<(apk_install_record)',
'--configuration-name=<(CONFIGURATION_NAME)',
],
'conditions': [
['create_abi_split == 1', {
'inputs': [
'<(final_apk_path)',
],
'action': [
'--apk-path=<(final_apk_path)',
'--split-apk-path=<(incomplete_apk_path)',
],
}, {
'action': [
'--apk-path=<(incomplete_apk_path)',
],
}]
],
},
],
'dependencies': [
'<(DEPTH)/build/android/rezip.gyp:rezip_apk_jar',
],
}],
['is_test_apk == 1', {
'dependencies': [
......@@ -878,11 +982,15 @@
{
'variables': {
'apk_path': '<(unsigned_apk_path)',
'native_libs_dir': '<(apk_package_native_libs_dir)',
'conditions': [
['native_lib_target != ""', {
'extra_inputs': ['<(native_lib_placeholder_stamp)'],
}],
['create_abi_split == 0', {
'native_libs_dir': '<(apk_package_native_libs_dir)',
}, {
'native_libs_dir': '<(DEPTH)/build/android/ant/empty/res',
}],
],
},
'includes': ['android/apkbuilder_action.gypi'],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment