| OLD | NEW | 
|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 package org.chromium.base.multidex; | 5 package org.chromium.base.multidex; | 
| 6 | 6 | 
|  | 7 import android.app.ActivityManager; | 
|  | 8 import android.app.ActivityManager.RunningAppProcessInfo; | 
| 7 import android.content.Context; | 9 import android.content.Context; | 
|  | 10 import android.content.pm.ApplicationInfo; | 
|  | 11 import android.content.pm.PackageManager; | 
| 8 import android.os.Build; | 12 import android.os.Build; | 
| 9 import android.os.Process; | 13 import android.os.Process; | 
| 10 import android.support.multidex.MultiDex; | 14 import android.support.multidex.MultiDex; | 
| 11 | 15 | 
| 12 import org.chromium.base.Log; | 16 import org.chromium.base.Log; | 
| 13 import org.chromium.base.VisibleForTesting; | 17 import org.chromium.base.VisibleForTesting; | 
| 14 | 18 | 
| 15 import java.lang.reflect.InvocationTargetException; | 19 import java.lang.reflect.InvocationTargetException; | 
|  | 20 import java.lang.reflect.Method; | 
| 16 | 21 | 
| 17 /** | 22 /** | 
| 18  *  Performs multidex installation for non-isolated processes. | 23  *  Performs multidex installation for non-isolated processes. | 
| 19  */ | 24  */ | 
| 20 public class ChromiumMultiDex { | 25 public class ChromiumMultiDex { | 
| 21 | 26 | 
| 22     private static final String TAG = "base_multidex"; | 27     private static final String TAG = "base_multidex"; | 
| 23 | 28 | 
| 24     /** | 29     /** | 
|  | 30      * Suffix for the meta-data tag in the AndroidManifext.xml that determines w
     hether loading | 
|  | 31      * secondary dexes should be skipped for a given process name. | 
|  | 32      */ | 
|  | 33     private static final String IGNORE_MULTIDEX_KEY = ".ignore_multidex"; | 
|  | 34 | 
|  | 35     /** | 
| 25      *  Installs secondary dexes if possible/necessary. | 36      *  Installs secondary dexes if possible/necessary. | 
| 26      * | 37      * | 
| 27      *  Isolated processes (e.g. renderer processes) can't load secondary dex fi
     les on | 38      *  Isolated processes (e.g. renderer processes) can't load secondary dex fi
     les on | 
| 28      *  K and below, so we don't even try in that case. | 39      *  K and below, so we don't even try in that case. | 
| 29      * | 40      * | 
| 30      *  In release builds, this is a no-op because: | 41      *  In release builds, this is a no-op because: | 
| 31      *    - multidex isn't necessary in release builds because we run proguard t
     here and | 42      *    - multidex isn't necessary in release builds because we run proguard t
     here and | 
| 32      *      thus aren't threatening to hit the dex limit; and | 43      *      thus aren't threatening to hit the dex limit; and | 
| 33      *    - calling MultiDex.install, even in the absence of secondary dexes, ca
     uses a | 44      *    - calling MultiDex.install, even in the absence of secondary dexes, ca
     uses a | 
| 34      *      significant regression in start-up time (crbug.com/525695). | 45      *      significant regression in start-up time (crbug.com/525695). | 
| 35      * | 46      * | 
| 36      *  @param context The application context. | 47      *  @param context The application context. | 
| 37      */ | 48      */ | 
| 38     @VisibleForTesting | 49     @VisibleForTesting | 
| 39 #if defined(MULTIDEX_CONFIGURATION_Debug) | 50 #if defined(MULTIDEX_CONFIGURATION_Debug) | 
| 40     public static void install(Context context) { | 51     public static void install(Context context) { | 
| 41         try { | 52         // TODO(jbudorick): Back out this version check once support for K & bel
     ow works. | 
| 42             // TODO(jbudorick): Back out this version check once support for K &
      below works. | 53         // http://crbug.com/512357 | 
| 43             // http://crbug.com/512357 | 54         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP | 
| 44             if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP && processI
     sIsolated()) { | 55                 && !shouldInstallMultiDex(context)) { | 
| 45                 Log.i(TAG, "Skipping multidex installation: inside isolated proc
     ess."); | 56             Log.i(TAG, "Skipping multidex installation: not needed for process."
     ); | 
| 46             } else { | 57         } else { | 
| 47                 MultiDex.install(context); | 58             MultiDex.install(context); | 
| 48                 Log.i(TAG, "Completed multidex installation."); | 59             Log.i(TAG, "Completed multidex installation."); | 
| 49             } |  | 
| 50         } catch (NoSuchMethodException e) { |  | 
| 51             Log.wtf(TAG, "Failed multidex installation", e); |  | 
| 52         } catch (IllegalAccessException e) { |  | 
| 53             Log.wtf(TAG, "Failed multidex installation", e); |  | 
| 54         } catch (InvocationTargetException e) { |  | 
| 55             Log.wtf(TAG, "Failed multidex installation", e); |  | 
| 56         } | 60         } | 
| 57     } | 61     } | 
| 58 | 62 | 
| 59     // Calls Process.isIsolated, a private Android API. | 63     private static String getProcessName(Context context) { | 
| 60     private static boolean processIsIsolated() | 64         try { | 
| 61             throws NoSuchMethodException, IllegalAccessException, InvocationTarg
     etException { | 65             String currentProcessName = null; | 
| 62         return (boolean) Process.class.getMethod("isIsolated").invoke(null); | 66             int pid = android.os.Process.myPid(); | 
|  | 67 | 
|  | 68             ActivityManager manager = | 
|  | 69                     (ActivityManager) context.getSystemService(Context.ACTIVITY_
     SERVICE); | 
|  | 70             for (RunningAppProcessInfo processInfo : manager.getRunningAppProces
     ses()) { | 
|  | 71                 if (processInfo.pid == pid) { | 
|  | 72                     currentProcessName = processInfo.processName; | 
|  | 73                     break; | 
|  | 74                 } | 
|  | 75             } | 
|  | 76 | 
|  | 77             return currentProcessName; | 
|  | 78         } catch (SecurityException ex) { | 
|  | 79             return null; | 
|  | 80         } | 
|  | 81     } | 
|  | 82 | 
|  | 83     // Determines whether MultiDex should be installed for the current process. 
      Isolated | 
|  | 84     // Processes should skip MultiDex as they can not actually access the files 
     on disk. | 
|  | 85     // Privileged processes need ot have all of their dependencies in the MainDe
     x for | 
|  | 86     // performance reasons. | 
|  | 87     private static boolean shouldInstallMultiDex(Context context) { | 
|  | 88         try { | 
|  | 89             Method isIsolatedMethod = | 
|  | 90                     android.os.Process.class.getMethod("isIsolated"); | 
|  | 91             Object retVal = isIsolatedMethod.invoke(null); | 
|  | 92             if (retVal != null && retVal instanceof Boolean && ((Boolean) retVal
     )) { | 
|  | 93                 return false; | 
|  | 94             } | 
|  | 95         } catch (IllegalAccessException | IllegalArgumentException | 
|  | 96                 | InvocationTargetException | NoSuchMethodException e) { | 
|  | 97             // Ignore and fall back to checking the app processes. | 
|  | 98         } | 
|  | 99 | 
|  | 100         String currentProcessName = getProcessName(context); | 
|  | 101         if (currentProcessName == null) return true; | 
|  | 102 | 
|  | 103         PackageManager packageManager = context.getPackageManager(); | 
|  | 104         try { | 
|  | 105             ApplicationInfo appInfo = packageManager.getApplicationInfo(context.
     getPackageName(), | 
|  | 106                     PackageManager.GET_META_DATA); | 
|  | 107             return !appInfo.metaData.getBoolean(currentProcessName + IGNORE_MULT
     IDEX_KEY, false); | 
|  | 108         } catch (PackageManager.NameNotFoundException e) { | 
|  | 109             return true; | 
|  | 110         } | 
| 63     } | 111     } | 
| 64 #else | 112 #else | 
| 65     public static void install(Context context) { | 113     public static void install(Context context) { | 
| 66     } | 114     } | 
| 67 #endif | 115 #endif | 
| 68 | 116 | 
| 69 } | 117 } | 
| OLD | NEW | 
|---|