diff --git a/base/BUILD.gn b/base/BUILD.gn index 5d8510f1b49da..1265df839b53b 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -2057,9 +2057,10 @@ if (is_android) { DEPRECATED_java_in_dir = "android/java/src" - # A new version of NativeLibraries.java (with the actual correct values) - # will be created when creating an apk. + # New versions of ChromiumMultiDex.java and NativeLibraries.java + # (with the actual correct values) will be created when creating an apk. jar_excluded_patterns = [ + "*/ChromiumMultiDex.class", "*/NativeLibraries.class", "*/NativeLibraries##*.class", ] @@ -2094,6 +2095,7 @@ if (is_android) { "//third_party/robolectric:android-all-4.3_r2-robolectric-0", "//third_party/robolectric:robolectric_java", ] + srcjar_deps = [ ":base_multidex_gen" ] } # GYP: //base.gyp:base_junit_tests @@ -2128,9 +2130,6 @@ if (is_android) { sources = [ "android/java/templates/ChromiumMultiDex.template", ] - if (is_debug) { - defines = [ "MULTIDEX_CONFIGURATION_Debug" ] - } package_name = "org/chromium/base/multidex" } diff --git a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java index e4e6e201e0559..f842a18f4baec 100644 --- a/base/android/java/src/org/chromium/base/BaseChromiumApplication.java +++ b/base/android/java/src/org/chromium/base/BaseChromiumApplication.java @@ -10,7 +10,7 @@ import android.os.Bundle; import android.view.Window; -import org.chromium.base.multidex.ChromiumMultiDex; +import org.chromium.base.multidex.ChromiumMultiDexInstaller; /** * Basic application functionality that should be shared among all browser applications. @@ -31,7 +31,7 @@ protected BaseChromiumApplication(boolean shouldInitializeApplicationStatusTrack @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); - ChromiumMultiDex.install(this); + ChromiumMultiDexInstaller.install(this); } /** diff --git a/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java b/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java new file mode 100644 index 0000000000000..e4b30b94685fc --- /dev/null +++ b/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java @@ -0,0 +1,114 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +package org.chromium.base.multidex; + +import android.app.ActivityManager; +import android.app.ActivityManager.RunningAppProcessInfo; +import android.content.Context; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Build; +import android.support.multidex.MultiDex; + +import org.chromium.base.Log; +import org.chromium.base.VisibleForTesting; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +/** + * Performs multidex installation for non-isolated processes. + */ +public class ChromiumMultiDexInstaller { + + private static final String TAG = "base_multidex"; + + /** + * Suffix for the meta-data tag in the AndroidManifext.xml that determines whether loading + * secondary dexes should be skipped for a given process name. + */ + private static final String IGNORE_MULTIDEX_KEY = ".ignore_multidex"; + + /** + * Installs secondary dexes if possible/necessary. + * + * Isolated processes (e.g. renderer processes) can't load secondary dex files on + * K and below, so we don't even try in that case. + * + * In release builds of app apks (as opposed to test apks), this is a no-op because: + * - multidex isn't necessary in release builds because we run proguard there and + * thus aren't threatening to hit the dex limit; and + * - calling MultiDex.install, even in the absence of secondary dexes, causes a + * significant regression in start-up time (crbug.com/525695). + * + * @param context The application context. + */ + @VisibleForTesting + public static void install(Context context) { + if (!ChromiumMultiDex.isMultidexEnabled()) return; + + // TODO(jbudorick): Back out this version check once support for K & below works. + // http://crbug.com/512357 + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP + && !shouldInstallMultiDex(context)) { + Log.i(TAG, "Skipping multidex installation: not needed for process."); + } else { + MultiDex.install(context); + Log.i(TAG, "Completed multidex installation."); + } + } + + private static String getProcessName(Context context) { + try { + String currentProcessName = null; + int pid = android.os.Process.myPid(); + + ActivityManager manager = + (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); + for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { + if (processInfo.pid == pid) { + currentProcessName = processInfo.processName; + break; + } + } + + return currentProcessName; + } catch (SecurityException ex) { + return null; + } + } + + // Determines whether MultiDex should be installed for the current process. Isolated + // Processes should skip MultiDex as they can not actually access the files on disk. + // Privileged processes need ot have all of their dependencies in the MainDex for + // performance reasons. + private static boolean shouldInstallMultiDex(Context context) { + try { + Method isIsolatedMethod = + android.os.Process.class.getMethod("isIsolated"); + Object retVal = isIsolatedMethod.invoke(null); + if (retVal != null && retVal instanceof Boolean && ((Boolean) retVal)) { + return false; + } + } catch (IllegalAccessException | IllegalArgumentException + | InvocationTargetException | NoSuchMethodException e) { + // Ignore and fall back to checking the app processes. + } + + String currentProcessName = getProcessName(context); + if (currentProcessName == null) return true; + + PackageManager packageManager = context.getPackageManager(); + try { + ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), + PackageManager.GET_META_DATA); + if (appInfo == null || appInfo.metaData == null) return true; + return !appInfo.metaData.getBoolean(currentProcessName + IGNORE_MULTIDEX_KEY, false); + } catch (PackageManager.NameNotFoundException e) { + return true; + } + } + +} diff --git a/base/android/java/templates/ChromiumMultiDex.template b/base/android/java/templates/ChromiumMultiDex.template index 5580489cd5398..7e70701c76a94 100644 --- a/base/android/java/templates/ChromiumMultiDex.template +++ b/base/android/java/templates/ChromiumMultiDex.template @@ -4,115 +4,22 @@ package org.chromium.base.multidex; -import android.app.ActivityManager; -import android.app.ActivityManager.RunningAppProcessInfo; -import android.content.Context; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; -import android.os.Build; -import android.os.Process; -import android.support.multidex.MultiDex; - -import org.chromium.base.Log; -import org.chromium.base.VisibleForTesting; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - /** - * Performs multidex installation for non-isolated processes. + * Multidex configuration. Generated on a per-target basis. */ -public class ChromiumMultiDex { +class ChromiumMultiDex { - private static final String TAG = "base_multidex"; - - /** - * Suffix for the meta-data tag in the AndroidManifext.xml that determines whether loading - * secondary dexes should be skipped for a given process name. - */ - private static final String IGNORE_MULTIDEX_KEY = ".ignore_multidex"; - - /** - * Installs secondary dexes if possible/necessary. - * - * Isolated processes (e.g. renderer processes) can't load secondary dex files on - * K and below, so we don't even try in that case. + /** Whether multidex is enabled for this target. * - * In release builds, this is a no-op because: - * - multidex isn't necessary in release builds because we run proguard there and - * thus aren't threatening to hit the dex limit; and - * - calling MultiDex.install, even in the absence of secondary dexes, causes a - * significant regression in start-up time (crbug.com/525695). - * - * @param context The application context. + * This has to be a function instead of a static final boolean s.t. the initial false value + * doesn't get optimized into {@link ChromiumMultiDexInstaller} at base_java compile time. */ - @VisibleForTesting -#if defined(MULTIDEX_CONFIGURATION_Debug) - public static void install(Context context) { - // TODO(jbudorick): Back out this version check once support for K & below works. - // http://crbug.com/512357 - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP - && !shouldInstallMultiDex(context)) { - Log.i(TAG, "Skipping multidex installation: not needed for process."); - } else { - MultiDex.install(context); - Log.i(TAG, "Completed multidex installation."); - } - } - - private static String getProcessName(Context context) { - try { - String currentProcessName = null; - int pid = android.os.Process.myPid(); - - ActivityManager manager = - (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - for (RunningAppProcessInfo processInfo : manager.getRunningAppProcesses()) { - if (processInfo.pid == pid) { - currentProcessName = processInfo.processName; - break; - } - } - - return currentProcessName; - } catch (SecurityException ex) { - return null; - } - } - - // Determines whether MultiDex should be installed for the current process. Isolated - // Processes should skip MultiDex as they can not actually access the files on disk. - // Privileged processes need ot have all of their dependencies in the MainDex for - // performance reasons. - private static boolean shouldInstallMultiDex(Context context) { - try { - Method isIsolatedMethod = - android.os.Process.class.getMethod("isIsolated"); - Object retVal = isIsolatedMethod.invoke(null); - if (retVal != null && retVal instanceof Boolean && ((Boolean) retVal)) { - return false; - } - } catch (IllegalAccessException | IllegalArgumentException - | InvocationTargetException | NoSuchMethodException e) { - // Ignore and fall back to checking the app processes. - } - - String currentProcessName = getProcessName(context); - if (currentProcessName == null) return true; - - PackageManager packageManager = context.getPackageManager(); - try { - ApplicationInfo appInfo = packageManager.getApplicationInfo(context.getPackageName(), - PackageManager.GET_META_DATA); - if (appInfo == null || appInfo.metaData == null) return true; - return !appInfo.metaData.getBoolean(currentProcessName + IGNORE_MULTIDEX_KEY, false); - } catch (PackageManager.NameNotFoundException e) { - return true; - } - } + static boolean isMultidexEnabled() { +#if defined(ENABLE_MULTIDEX) + return true; #else - public static void install(Context context) { - } + return false; #endif + } } diff --git a/base/base.gyp b/base/base.gyp index dc484f4a4a62b..94a1d49258572 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -1489,9 +1489,6 @@ 'variables': { 'package_name': 'org/chromium/base/multidex', 'template_deps': [], - 'additional_gcc_preprocess_options': [ - '--defines', 'MULTIDEX_CONFIGURATION_<(CONFIGURATION_NAME)', - ], }, 'includes': ['../build/android/java_cpp_template.gypi'], }, @@ -1510,7 +1507,10 @@ 'type': 'none', 'variables': { 'java_in_dir': 'android/java', - 'jar_excluded_classes': [ '*/NativeLibraries.class' ], + 'jar_excluded_classes': [ + '*/ChromiumMultiDex.class', + '*/NativeLibraries.class', + ], }, 'dependencies': [ 'base_java_application_state', @@ -1522,6 +1522,11 @@ '../third_party/android_tools/android_tools.gyp:android_support_multidex_javalib', '../third_party/jsr-305/jsr-305.gyp:jsr_305_javalib', ], + 'all_dependent_settings': { + 'variables': { + 'generate_multidex_config': 1, + }, + }, 'includes': [ '../build/java.gypi' ], }, { @@ -1583,6 +1588,7 @@ 'target_name': 'base_junit_test_support', 'type': 'none', 'dependencies': [ + 'base_multidex_gen', '../testing/android/junit/junit_test.gyp:junit_test_support', '../third_party/android_tools/android_tools.gyp:android_support_multidex_javalib', ], diff --git a/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java b/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java index 8bf3d0fb454b9..669307c82b43c 100644 --- a/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java +++ b/base/test/android/javatests/src/org/chromium/base/test/BaseInstrumentationTestRunner.java @@ -18,7 +18,7 @@ import org.chromium.base.Log; import org.chromium.base.SysUtils; -import org.chromium.base.multidex.ChromiumMultiDex; +import org.chromium.base.multidex.ChromiumMultiDexInstaller; import org.chromium.base.test.util.CommandLineFlags; import org.chromium.base.test.util.DisableIfSkipCheck; import org.chromium.base.test.util.MinAndroidSdkLevel; @@ -37,7 +37,7 @@ public class BaseInstrumentationTestRunner extends InstrumentationTestRunner { @Override public void onCreate(Bundle arguments) { - ChromiumMultiDex.install(getTargetContext()); + ChromiumMultiDexInstaller.install(getTargetContext()); super.onCreate(arguments); } diff --git a/build/android/gyp/configure_multidex.py b/build/android/gyp/configure_multidex.py index aa85d2ffb1655..9f3b7360f7132 100755 --- a/build/android/gyp/configure_multidex.py +++ b/build/android/gyp/configure_multidex.py @@ -6,23 +6,33 @@ import argparse import json +import os import sys from util import build_utils +_GCC_PREPROCESS_PATH = os.path.join( + os.path.dirname(__file__), 'gcc_preprocess.py') + + def ParseArgs(): parser = argparse.ArgumentParser() parser.add_argument('--configuration-name', required=True, help='The build CONFIGURATION_NAME.') + parser.add_argument('--enable-multidex', action='store_true', default=False, + help='If passed, multidex may be enabled.') parser.add_argument('--enabled-configurations', default=[], help='The configuration(s) for which multidex should be ' 'enabled. If not specified and --enable-multidex is ' 'passed, multidex will be enabled for all ' - 'configurations.') + 'configurations.') parser.add_argument('--multidex-configuration-path', required=True, help='The path to which the multidex configuration JSON ' 'should be saved.') + parser.add_argument('--multidex-config-java-file', required=True) + parser.add_argument('--multidex-config-java-stamp', required=True) + parser.add_argument('--multidex-config-java-template', required=True) args = parser.parse_args() @@ -33,20 +43,42 @@ def ParseArgs(): return args -def main(): - args = ParseArgs() - - multidex_enabled = ( - (not args.enabled_configurations - or args.configuration_name in args.enabled_configurations)) - +def _WriteConfigJson(multidex_enabled, multidex_configuration_path): config = { 'enabled': multidex_enabled, } - with open(args.multidex_configuration_path, 'w') as f: + with open(multidex_configuration_path, 'w') as f: f.write(json.dumps(config)) + +def _GenerateMultidexConfigJava(multidex_enabled, args): + gcc_preprocess_cmd = [ + sys.executable, _GCC_PREPROCESS_PATH, + '--include-path=', + '--template', args.multidex_config_java_template, + '--stamp', args.multidex_config_java_stamp, + '--output', args.multidex_config_java_file, + ] + if multidex_enabled: + gcc_preprocess_cmd += [ + '--defines', 'ENABLE_MULTIDEX', + ] + + build_utils.CheckOutput(gcc_preprocess_cmd) + + +def main(): + args = ParseArgs() + + multidex_enabled = ( + args.enable_multidex + and (not args.enabled_configurations + or args.configuration_name in args.enabled_configurations)) + + _WriteConfigJson(multidex_enabled, args.multidex_configuration_path) + _GenerateMultidexConfigJava(multidex_enabled, args) + return 0 diff --git a/build/android/java_cpp_template.gypi b/build/android/java_cpp_template.gypi index f4ea0a9195d38..3296659240b57 100644 --- a/build/android/java_cpp_template.gypi +++ b/build/android/java_cpp_template.gypi @@ -34,7 +34,6 @@ { # Location where all generated Java sources will be placed. 'variables': { - 'additional_gcc_preprocess_options': [], 'include_path%': '<(DEPTH)', 'output_dir': '<(SHARED_INTERMEDIATE_DIR)/templates/<(_target_name)/<(package_name)', }, @@ -75,7 +74,6 @@ '--include-path=<(include_path)', '--output=<(output_path)', '--template=<(RULE_INPUT_PATH)', - '<@(additional_gcc_preprocess_options)', ], 'message': 'Generating Java from cpp template <(RULE_INPUT_PATH)', } diff --git a/build/android/pylib/remote/device/dummy/dummy.gyp b/build/android/pylib/remote/device/dummy/dummy.gyp index b003edcd86950..46e2d484f1510 100644 --- a/build/android/pylib/remote/device/dummy/dummy.gyp +++ b/build/android/pylib/remote/device/dummy/dummy.gyp @@ -7,13 +7,18 @@ # APK, so we build a dummy APK to upload as the app. { + 'variables': { + 'remote_device_dummy_apk_name': 'remote_device_dummy', + 'remote_device_dummy_apk_path': '<(PRODUCT_DIR)/apks/<(remote_device_dummy_apk_name).apk', + }, 'targets': [ { # GN: //build/android/pylib/remote/device/dummy:remote_device_dummy_apk 'target_name': 'remote_device_dummy_apk', 'type': 'none', 'variables': { - 'apk_name': 'remote_device_dummy', + 'apk_name': '<(remote_device_dummy_apk_name)', + 'final_apk_path': '<(remote_device_dummy_apk_path)', 'java_in_dir': '.', 'android_manifest_path': '../../../../../../build/android/AndroidManifest.xml', }, @@ -21,5 +26,22 @@ '../../../../../../build/java_apk.gypi', ] }, + { + 'target_name': 'require_remote_device_dummy_apk', + 'message': 'Making sure <(remote_device_dummy_apk_path) has been built.', + 'type': 'none', + 'variables': { + 'required_file': '<(PRODUCT_DIR)/remote_device_dummy_apk/<(remote_device_dummy_apk_name).apk.required', + }, + 'inputs': [ + '<(remote_device_dummy_apk_path)', + ], + 'outputs': [ + '<(required_file)', + ], + 'action': [ + 'python', '../../build/android/gyp/touch.py', '<(required_file)', + ], + } ] } diff --git a/build/apk_browsertest.gypi b/build/apk_browsertest.gypi index 8cbc4137f597b..52cb9e0ca68f0 100644 --- a/build/apk_browsertest.gypi +++ b/build/apk_browsertest.gypi @@ -21,7 +21,7 @@ 'dependencies': [ '<(DEPTH)/base/base.gyp:base_java', '<(DEPTH)/build/android/pylib/device/commands/commands.gyp:chromium_commands', - '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:remote_device_dummy_apk', + '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:require_remote_device_dummy_apk', '<(DEPTH)/testing/android/appurify_support.gyp:appurify_support_java', '<(DEPTH)/testing/android/native_test.gyp:native_test_java', '<(DEPTH)/tools/android/android_tools.gyp:android_tools', diff --git a/build/apk_test.gypi b/build/apk_test.gypi index e0d323f74a36b..6512b6d9f6557 100644 --- a/build/apk_test.gypi +++ b/build/apk_test.gypi @@ -21,7 +21,7 @@ 'dependencies': [ '<(DEPTH)/base/base.gyp:base_java', '<(DEPTH)/build/android/pylib/device/commands/commands.gyp:chromium_commands', - '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:remote_device_dummy_apk', + '<(DEPTH)/build/android/pylib/remote/device/dummy/dummy.gyp:require_remote_device_dummy_apk', '<(DEPTH)/testing/android/appurify_support.gyp:appurify_support_java', '<(DEPTH)/testing/android/on_device_instrumentation.gyp:reporter_java', '<(DEPTH)/tools/android/android_tools.gyp:android_tools', diff --git a/build/config/android/rules.gni b/build/config/android/rules.gni index da9a8536f3ed4..1c65d215314c8 100644 --- a/build/config/android/rules.gni +++ b/build/config/android/rules.gni @@ -1484,6 +1484,21 @@ template("android_apk") { _srcjar_deps += [ ":${_template_name}__native_libraries_java" ] } + if (!defined(invoker.apk_under_test)) { + java_cpp_template("${_template_name}__multidex_config_java") { + package_name = "org/chromium/base/multidex" + sources = [ + "//base/android/java/templates/ChromiumMultiDex.template", + ] + + defines = [] + if (enable_multidex) { + defines += [ "ENABLE_MULTIDEX" ] + } + } + _srcjar_deps += [ ":${_template_name}__multidex_config_java" ] + } + java_target = "${_template_name}__java" java_library_impl(java_target) { forward_variables_from(invoker, [ "run_findbugs" ]) @@ -2018,11 +2033,13 @@ template("unittest_apk") { native_libs = [ unittests_binary ] deps += [ "//base:base_java", - "//build/android/pylib/remote/device/dummy:remote_device_dummy_apk", "//testing/android/appurify_support:appurify_support_java", "//testing/android/reporter:reporter_java", ] - data_deps += [ "//tools/android/md5sum" ] + data_deps += [ + "//build/android/pylib/remote/device/dummy:remote_device_dummy_apk", + "//tools/android/md5sum", + ] if (host_os == "linux") { data_deps += [ "//tools/android/forwarder2" ] } diff --git a/build/java_apk.gypi b/build/java_apk.gypi index ab49dc6ab1b79..f8e523177fc59 100644 --- a/build/java_apk.gypi +++ b/build/java_apk.gypi @@ -77,6 +77,7 @@ 'tested_apk_obfuscated_jar_path%': '/', 'tested_apk_dex_path%': '/', 'tested_apk_is_multidex%': 0, + 'tested_apk_generated_multidex_config%': 0, 'additional_input_paths': [], 'additional_locale_input_paths': [], 'create_density_splits%': 0, @@ -121,6 +122,11 @@ 'native_libraries_template_data_dir': '<(intermediate_dir)/native_libraries/', 'native_libraries_template_data_file': '<(native_libraries_template_data_dir)/native_libraries_array.h', 'native_libraries_template_version_file': '<(native_libraries_template_data_dir)/native_libraries_version.h', + 'generate_multidex_config%': 0, + 'multidex_config_template': '<(DEPTH)/base/android/java/templates/ChromiumMultiDex.template', + 'multidex_config_java_dir': '<(intermediate_dir)/multidex_config/', + 'multidex_config_java_file': '<(multidex_config_java_dir)/ChromiumMultiDex.java', + 'multidex_config_java_stamp': '<(intermediate_dir)/multidex_config_java.stamp', 'compile_stamp': '<(intermediate_dir)/compile.stamp', 'lint_stamp': '<(intermediate_dir)/lint.stamp', 'lint_result': '<(intermediate_dir)/lint_result.xml', @@ -266,6 +272,7 @@ 'tested_apk_obfuscated_jar_path': '<(obfuscated_jar_path)', 'tested_apk_dex_path': '<(dex_path)', 'tested_apk_is_multidex': '<(enable_multidex)', + 'tested_apk_generated_multidex_config': '>(generate_multidex_config)', } }] ], @@ -794,37 +801,58 @@ }, ], }], - ['enable_multidex == 1', { + ], + 'target_conditions': [ + ['generate_multidex_config == 1 and tested_apk_generated_multidex_config == 0', { + 'variables': { + 'generated_src_dirs': ['<(multidex_config_java_dir)'], + }, 'actions': [ - { - 'action_name': 'main_dex_list_for_<(_target_name)', - 'variables': { - 'jar_paths': ['>@(input_jars_paths)', '<(javac_jar_path)'], - 'output_path': '<(main_dex_list_path)', - }, - 'includes': [ 'android/main_dex_action.gypi' ], - }, { 'action_name': 'configure_multidex_for_<(_target_name)', 'inputs': [ '<(DEPTH)/build/android/gyp/configure_multidex.py', + '<(multidex_config_template)', ], 'outputs': [ '<(multidex_configuration_path)', + '<(multidex_config_java_stamp)', ], 'variables': { 'additional_multidex_config_options': [], - 'enabled_configurations': ['>@(enable_multidex_configurations)'], + 'enabled_configurations': '>(enable_multidex_configurations)', + 'conditions': [ + ['enable_multidex == 1', { + 'additional_multidex_config_options': ['--enable-multidex'], + }], + ], }, 'action': [ 'python', '<(DEPTH)/build/android/gyp/configure_multidex.py', '--configuration-name', '<(CONFIGURATION_NAME)', '--enabled-configurations', '<(enabled_configurations)', '--multidex-configuration-path', '<(multidex_configuration_path)', + '--multidex-config-java-template', '<(multidex_config_template)', + '--multidex-config-java-file', '<(multidex_config_java_file)', + '--multidex-config-java-stamp', '<(multidex_config_java_stamp)', '>@(additional_multidex_config_options)', ], }, ], + 'conditions': [ + ['enable_multidex == 1', { + 'actions': [ + { + 'action_name': 'main_dex_list_for_<(_target_name)', + 'variables': { + 'jar_paths': ['>@(input_jars_paths)', '<(javac_jar_path)'], + 'output_path': '<(main_dex_list_path)', + }, + 'includes': [ 'android/main_dex_action.gypi' ], + }, + ] + }] + ], }], ], 'dependencies': [ @@ -956,6 +984,11 @@ 'inputs': [ '<(native_libraries_java_stamp)' ], }], ], + 'target_conditions': [ + ['generate_multidex_config == 1 and tested_apk_generated_multidex_config == 0', { + 'inputs': [ '<(multidex_config_java_stamp)' ], + }], + ], 'outputs': [ '<(compile_stamp)', '<(javac_jar_path)', diff --git a/chrome/chrome_tests_unit.gypi b/chrome/chrome_tests_unit.gypi index 2a8b57cf1ba75..a476f9aaceb64 100644 --- a/chrome/chrome_tests_unit.gypi +++ b/chrome/chrome_tests_unit.gypi @@ -2983,6 +2983,7 @@ 'test_suite_name': 'unit_tests', 'isolate_file': 'unit_tests.isolate', 'android_manifest_path': 'test/android/unit_tests_apk/AndroidManifest.xml', + 'enable_multidex': 1, 'conditions': [ ['v8_use_external_startup_data==1', { 'asset_location': '<(PRODUCT_DIR)/unit_tests_apk/assets', diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn index 04badd31e5faf..28460c7dcb715 100644 --- a/chrome/test/BUILD.gn +++ b/chrome/test/BUILD.gn @@ -1636,6 +1636,7 @@ test("unit_tests") { android_manifest = "//chrome/test/android/unit_tests_apk/AndroidManifest.xml" + enable_multidex = true isolate_file = "../unit_tests.isolate" # Some android targets still depend on --gc-sections to link. diff --git a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java index bdba1e059bb5a..00d5c7899f63c 100644 --- a/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java +++ b/testing/android/native_test/java/src/org/chromium/native_test/NativeTestActivity.java @@ -15,6 +15,7 @@ import org.chromium.base.CommandLine; import org.chromium.base.Log; import org.chromium.base.annotations.JNINamespace; +import org.chromium.base.multidex.ChromiumMultiDexInstaller; import org.chromium.test.reporter.TestStatusReporter; import java.io.File; @@ -50,7 +51,9 @@ public class NativeTestActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { + ChromiumMultiDexInstaller.install(this); super.onCreate(savedInstanceState); + CommandLine.init(new String[]{}); parseArgumentsFromIntent(getIntent()); diff --git a/testing/test.gni b/testing/test.gni index 7ce5d85acd27f..6739bfebb21ce 100644 --- a/testing/test.gni +++ b/testing/test.gni @@ -66,6 +66,7 @@ template("test") { [ "android_manifest", "deps", + "enable_multidex", "use_default_launcher", "write_asset_list", ])