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; ...@@ -7,11 +7,29 @@ package org.chromium.base;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
/** /**
* This class provides package checking related methods. * This class provides package checking related methods.
*/ */
public class PackageUtils { 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. * Retrieves the version of the given package installed on the device.
* *
......
...@@ -4,14 +4,19 @@ ...@@ -4,14 +4,19 @@
package org.chromium.base.library_loader; package org.chromium.base.library_loader;
import android.annotation.TargetApi;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build;
import android.os.SystemClock; import android.os.SystemClock;
import android.util.Log; import android.util.Log;
import org.chromium.base.CalledByNative; import org.chromium.base.CalledByNative;
import org.chromium.base.CommandLine; import org.chromium.base.CommandLine;
import org.chromium.base.JNINamespace; import org.chromium.base.JNINamespace;
import org.chromium.base.PackageUtils;
import org.chromium.base.TraceEvent; import org.chromium.base.TraceEvent;
import org.chromium.base.VisibleForTesting; import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
...@@ -250,7 +255,7 @@ public class LibraryLoader { ...@@ -250,7 +255,7 @@ public class LibraryLoader {
// Check if the device supports memory mapping the APK file // Check if the device supports memory mapping the APK file
// with executable permissions. // with executable permissions.
if (context != null) { if (context != null) {
apkFilePath = context.getApplicationInfo().sourceDir; apkFilePath = getLibraryApkPath(context);
if (mProbeMapApkWithExecPermission) { if (mProbeMapApkWithExecPermission) {
mMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath); mMapApkWithExecPermission = Linker.checkMapExecSupport(apkFilePath);
} else { } else {
...@@ -367,6 +372,31 @@ public class LibraryLoader { ...@@ -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 // 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. // path is not null, the library is loaded directly from the zip file.
private void loadLibrary(@Nullable String zipFilePath, String libFilePath) { private void loadLibrary(@Nullable String zipFilePath, String libFilePath) {
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
'keystore_password%': 'chromium', 'keystore_password%': 'chromium',
'zipalign_path%': '<(android_sdk_tools)/zipalign', 'zipalign_path%': '<(android_sdk_tools)/zipalign',
'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar', 'rezip_apk_jar_path%': '<(PRODUCT_DIR)/lib.java/rezip_apk.jar',
'load_library_from_zip%': 0,
}, },
'inputs': [ 'inputs': [
'<(DEPTH)/build/android/gyp/finalize_apk.py', '<(DEPTH)/build/android/gyp/finalize_apk.py',
...@@ -42,7 +43,7 @@ ...@@ -42,7 +43,7 @@
'--key-path=<(keystore_path)', '--key-path=<(keystore_path)',
'--key-name=<(keystore_name)', '--key-name=<(keystore_name)',
'--key-passwd=<(keystore_password)', '--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)', '--rezip-apk-jar-path=<(rezip_apk_jar_path)',
], ],
} }
...@@ -1203,7 +1203,7 @@ template("android_apk") { ...@@ -1203,7 +1203,7 @@ template("android_apk") {
base_path = "$gen_dir/$target_name" base_path = "$gen_dir/$target_name"
_build_config = "$target_gen_dir/$target_name.build_config" _build_config = "$target_gen_dir/$target_name.build_config"
resources_zip_path = "$base_path.resources.zip" 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" jar_path = "$base_path.jar"
final_dex_path = "$gen_dir/classes.dex" final_dex_path = "$gen_dir/classes.dex"
_template_name = target_name _template_name = target_name
...@@ -1221,6 +1221,15 @@ template("android_apk") { ...@@ -1221,6 +1221,15 @@ template("android_apk") {
_native_libs = [] _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_path = android_default_keystore_path
_keystore_name = android_default_keystore_name _keystore_name = android_default_keystore_name
_keystore_password = android_default_keystore_password _keystore_password = android_default_keystore_password
...@@ -1286,6 +1295,11 @@ template("android_apk") { ...@@ -1286,6 +1295,11 @@ template("android_apk") {
_android_manifest = invoker.android_manifest _android_manifest = invoker.android_manifest
_rebased_build_config = rebase_path(_build_config, root_build_dir) _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") { write_build_config("${_template_name}__build_config") {
type = "android_apk" type = "android_apk"
...@@ -1314,6 +1328,7 @@ template("android_apk") { ...@@ -1314,6 +1328,7 @@ template("android_apk") {
android_manifest = _android_manifest android_manifest = _android_manifest
resource_dirs = [ "//build/android/ant/empty/res" ] resource_dirs = [ "//build/android/ant/empty/res" ]
zip_path = resources_zip_path zip_path = resources_zip_path
all_resources_zip_path = _all_resources_zip_path
generate_constant_ids = true generate_constant_ids = true
build_config = _build_config build_config = _build_config
...@@ -1470,19 +1485,12 @@ template("android_apk") { ...@@ -1470,19 +1485,12 @@ template("android_apk") {
create_apk("${_template_name}__create") { create_apk("${_template_name}__create") {
apk_path = _final_apk_path apk_path = _final_apk_path
android_manifest = _android_manifest android_manifest = _android_manifest
resources_zip = all_resources_zip_path resources_zip = _all_resources_zip_path
dex_path = final_dex_path dex_path = final_dex_path
load_library_from_apk = _load_library_from_apk load_library_from_apk = _load_library_from_apk
version_code = "1" version_code = _version_code
if (defined(invoker.version_code)) { version_name = _version_name
version_code = invoker.version_code
}
version_name = "Developer Build"
if (defined(invoker.version_name)) {
version_name = invoker.version_name
}
keystore_name = _keystore_name keystore_name = _keystore_name
keystore_path = _keystore_path keystore_path = _keystore_path
...@@ -1500,12 +1508,48 @@ template("android_apk") { ...@@ -1500,12 +1508,48 @@ template("android_apk") {
} }
} }
if (_native_libs != []) { if (_native_libs != [] && !_create_abi_split) {
native_libs_dir = _native_libs_dir native_libs_dir = _native_libs_dir
deps += [ ":${_template_name}__prepare_native" ] 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) { group(target_name) {
deps = final_deps deps = final_deps
if (defined(invoker.datadeps)) { if (defined(invoker.datadeps)) {
......
...@@ -126,12 +126,13 @@ ...@@ -126,12 +126,13 @@
'dex_path': '<(intermediate_dir)/classes.dex', 'dex_path': '<(intermediate_dir)/classes.dex',
'emma_device_jar': '<(android_sdk_root)/tools/lib/emma_device.jar', 'emma_device_jar': '<(android_sdk_root)/tools/lib/emma_device.jar',
'android_manifest_path%': '<(java_in_dir)/AndroidManifest.xml', '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', 'push_stamp': '<(intermediate_dir)/push.stamp',
'link_stamp': '<(intermediate_dir)/link.stamp', 'link_stamp': '<(intermediate_dir)/link.stamp',
'resource_zip_path': '<(intermediate_dir)/<(_target_name).resources.zip', 'resource_zip_path': '<(intermediate_dir)/<(_target_name).resources.zip',
'shared_resources%': 0, 'shared_resources%': 0,
'unsigned_apk_path': '<(intermediate_dir)/<(apk_name)-unsigned.apk',
'final_apk_path%': '<(PRODUCT_DIR)/apks/<(apk_name).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', 'incomplete_apk_path': '<(intermediate_dir)/<(apk_name)-incomplete.apk',
'apk_install_record': '<(intermediate_dir)/apk_install.record.stamp', 'apk_install_record': '<(intermediate_dir)/apk_install.record.stamp',
'device_intermediate_dir': '/data/data/org.chromium.gyp_managed_install/<(_target_name)/<(CONFIGURATION_NAME)', 'device_intermediate_dir': '/data/data/org.chromium.gyp_managed_install/<(_target_name)/<(CONFIGURATION_NAME)',
...@@ -144,14 +145,25 @@ ...@@ -144,14 +145,25 @@
'native_lib_target%': '', 'native_lib_target%': '',
'native_lib_version_name%': '', 'native_lib_version_name%': '',
'use_chromium_linker%' : 0, 'use_chromium_linker%' : 0,
'load_library_from_zip_file%' : 0,
'use_relocation_packer%' : 0, 'use_relocation_packer%' : 0,
'enable_chromium_linker_tests%': 0, 'enable_chromium_linker_tests%': 0,
'is_test_apk%': 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': [ 'conditions': [
['gyp_managed_install == 1 and native_lib_target != ""', { ['gyp_managed_install == 1 and native_lib_target != ""', {
'conditions': [
['create_abi_split == 0', {
'unsigned_standalone_apk_path': '<(intermediate_dir)/<(apk_name)-standalone-unsigned.apk', '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)', 'unsigned_standalone_apk_path': '<(unsigned_apk_path)',
}], }],
...@@ -165,6 +177,13 @@ ...@@ -165,6 +177,13 @@
},{ },{
'emma_instrument%': 0, '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%': '', 'native_lib_target%': '',
...@@ -176,10 +195,15 @@ ...@@ -176,10 +195,15 @@
'emma_instrument%': '<(emma_instrument)', 'emma_instrument%': '<(emma_instrument)',
'apk_package_native_libs_dir': '<(apk_package_native_libs_dir)', 'apk_package_native_libs_dir': '<(apk_package_native_libs_dir)',
'unsigned_standalone_apk_path': '<(unsigned_standalone_apk_path)', '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)', 'libchromium_android_linker': 'libchromium_android_linker.>(android_product_extension)',
'extra_native_libs': [], 'extra_native_libs': [],
'native_lib_placeholder_stamp': '<(apk_package_native_libs_dir)/<(android_app_abi)/native_lib_placeholder.stamp', 'native_lib_placeholder_stamp': '<(apk_package_native_libs_dir)/<(android_app_abi)/native_lib_placeholder.stamp',
'native_lib_placeholders': [], 'native_lib_placeholders': [],
'main_apk_name': '<(apk_name)',
}, },
# Pass the jar path to the apk's "fake" jar target. This would be better as # 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 # direct_dependent_settings, but a variable set by a direct_dependent_settings
...@@ -483,9 +507,9 @@ ...@@ -483,9 +507,9 @@
'<(strip_additional_stamp)', '<(strip_additional_stamp)',
'<(pack_arm_relocations_stamp)', '<(pack_arm_relocations_stamp)',
], ],
'input_apk_path': '<(unsigned_apk_path)',
'output_apk_path': '<(unsigned_standalone_apk_path)', 'output_apk_path': '<(unsigned_standalone_apk_path)',
'libraries_top_dir%': '<(libraries_top_dir)', 'libraries_top_dir%': '<(libraries_top_dir)',
'input_apk_path': '<(managed_input_apk_path)',
}, },
'includes': [ 'android/create_standalone_apk_action.gypi' ], 'includes': [ 'android/create_standalone_apk_action.gypi' ],
}, },
...@@ -504,19 +528,87 @@ ...@@ -504,19 +528,87 @@
}], }],
], ],
}], # native_lib_target != '' }], # 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': [ 'actions': [
{ {
'action_name': 'finalize standalone apk', 'action_name': 'finalize_base',
'variables': { 'variables': {
'input_apk_path': '<(unsigned_standalone_apk_path)',
'output_apk_path': '<(final_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'] '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', { ['gyp_managed_install == 1', {
...@@ -524,7 +616,8 @@ ...@@ -524,7 +616,8 @@
{ {
'action_name': 'finalize incomplete apk', 'action_name': 'finalize incomplete apk',
'variables': { '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)', 'output_apk_path': '<(incomplete_apk_path)',
}, },
'includes': [ 'android/finalize_apk_action.gypi'] 'includes': [ 'android/finalize_apk_action.gypi']
...@@ -543,15 +636,26 @@ ...@@ -543,15 +636,26 @@
], ],
'action': [ 'action': [
'python', '<(DEPTH)/build/android/gyp/apk_install.py', 'python', '<(DEPTH)/build/android/gyp/apk_install.py',
'--apk-path=<(incomplete_apk_path)',
'--build-device-configuration=<(build_device_config_path)', '--build-device-configuration=<(build_device_config_path)',
'--install-record=<(apk_install_record)', '--install-record=<(apk_install_record)',
'--configuration-name=<(CONFIGURATION_NAME)', '--configuration-name=<(CONFIGURATION_NAME)',
], ],
}, 'conditions': [
['create_abi_split == 1', {
'inputs': [
'<(final_apk_path)',
], ],
'dependencies': [ 'action': [
'<(DEPTH)/build/android/rezip.gyp:rezip_apk_jar', '--apk-path=<(final_apk_path)',
'--split-apk-path=<(incomplete_apk_path)',
],
}, {
'action': [
'--apk-path=<(incomplete_apk_path)',
],
}]
],
},
], ],
}], }],
['is_test_apk == 1', { ['is_test_apk == 1', {
...@@ -878,11 +982,15 @@ ...@@ -878,11 +982,15 @@
{ {
'variables': { 'variables': {
'apk_path': '<(unsigned_apk_path)', 'apk_path': '<(unsigned_apk_path)',
'native_libs_dir': '<(apk_package_native_libs_dir)',
'conditions': [ 'conditions': [
['native_lib_target != ""', { ['native_lib_target != ""', {
'extra_inputs': ['<(native_lib_placeholder_stamp)'], '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'], '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