| Index: base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java
|
| diff --git a/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java b/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java
|
| index 3d036c2099be26d1f761f4e2ff9a7ade621a32c6..4bc956961f55b6cfa3617ce9b8b3c260c2bfb203 100644
|
| --- a/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java
|
| +++ b/base/android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java
|
| @@ -14,13 +14,14 @@ import android.support.multidex.MultiDex;
|
|
|
| import org.chromium.base.BuildConfig;
|
| import org.chromium.base.Log;
|
| +import org.chromium.base.Reflect;
|
| import org.chromium.base.VisibleForTesting;
|
|
|
| import java.lang.reflect.InvocationTargetException;
|
| import java.lang.reflect.Method;
|
|
|
| /**
|
| - * Performs multidex installation for non-isolated processes.
|
| + * Performs multidex installation for non-isolated processes.
|
| */
|
| public class ChromiumMultiDexInstaller {
|
|
|
| @@ -33,27 +34,36 @@ public class ChromiumMultiDexInstaller {
|
| private static final String IGNORE_MULTIDEX_KEY = ".ignore_multidex";
|
|
|
| /**
|
| - * Installs secondary dexes if possible/necessary.
|
| + * 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.
|
| + * 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).
|
| + * 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.
|
| + * @param context The application context.
|
| */
|
| @VisibleForTesting
|
| public static void install(Context context) {
|
| if (!BuildConfig.isMultidexEnabled()) return;
|
|
|
| + boolean isIsolatedProcess = isIsolatedProcess();
|
| + if (!BuildConfig.isOfficialBuild() && isIsolatedProcess) {
|
| + try {
|
| + disableSecondaryDexFileAccess(context);
|
| + } catch (Exception e) {
|
| + throw new RuntimeException("ChromiumMultidex installation failed", e);
|
| + }
|
| + }
|
| +
|
| // 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)) {
|
| + && !shouldInstallMultiDex(context, isIsolatedProcess)) {
|
| Log.i(TAG, "Skipping multidex installation: not needed for process.");
|
| } else {
|
| MultiDex.install(context);
|
| @@ -61,6 +71,29 @@ public class ChromiumMultiDexInstaller {
|
| }
|
| }
|
|
|
| + private static void disableSecondaryDexFileAccess(Context context)
|
| + throws ReflectiveOperationException {
|
| + ClassLoader classLoader = context.getClassLoader();
|
| + Object dexPathList = Reflect.getField(classLoader, "pathList");
|
| + Object[] oldDexElements = (Object[]) Reflect.getField(dexPathList, "dexElements");
|
| + Object[] newDexElements = Reflect.spliceArray(oldDexElements, 0, 1);
|
| + Reflect.setField(dexPathList, "dexElements", newDexElements);
|
| + }
|
| +
|
| + private static boolean isIsolatedProcess() {
|
| + try {
|
| + Method isIsolatedMethod = android.os.Process.class.getMethod("isIsolated");
|
| + Object retVal = isIsolatedMethod.invoke(null);
|
| + if (retVal != null && retVal instanceof Boolean && ((Boolean) retVal)) {
|
| + return true;
|
| + }
|
| + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
|
| + | NoSuchMethodException e) {
|
| + // Ignore and fall back to checking the app processes.
|
| + }
|
| + return false;
|
| + }
|
| +
|
| private static String getProcessName(Context context) {
|
| try {
|
| String currentProcessName = null;
|
| @@ -85,18 +118,8 @@ public class ChromiumMultiDexInstaller {
|
| // 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.
|
| - }
|
| + private static boolean shouldInstallMultiDex(Context context, boolean isIsolatedProcess) {
|
| + if (isIsolatedProcess) return false;
|
|
|
| String currentProcessName = getProcessName(context);
|
| if (currentProcessName == null) return true;
|
|
|