Loading core/java/android/app/DexLoadReporter.java +29 −10 Original line number Diff line number Diff line Loading @@ -28,8 +28,9 @@ import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; /** Loading Loading @@ -86,32 +87,50 @@ import java.util.Set; } @Override public void report(Map<String, String> classLoaderContextMap) { if (classLoaderContextMap.isEmpty()) { Slog.wtf(TAG, "Bad call to DexLoadReporter: empty classLoaderContextMap"); public void report(List<ClassLoader> classLoadersChain, List<String> classPaths) { if (classLoadersChain.size() != classPaths.size()) { Slog.wtf(TAG, "Bad call to DexLoadReporter: argument size mismatch"); return; } if (classPaths.isEmpty()) { Slog.wtf(TAG, "Bad call to DexLoadReporter: empty dex paths"); return; } // The first element of classPaths is the list of dex files that should be registered. // The classpath is represented as a list of dex files separated by File.pathSeparator. String[] dexPathsForRegistration = classPaths.get(0).split(File.pathSeparator); if (dexPathsForRegistration.length == 0) { // No dex files to register. return; } // Notify the package manager about the dex loads unconditionally. // The load might be for either a primary or secondary dex file. notifyPackageManager(classLoaderContextMap); notifyPackageManager(classLoadersChain, classPaths); // Check for secondary dex files and register them for profiling if possible. // Note that we only register the dex paths belonging to the first class loader. registerSecondaryDexForProfiling(classLoaderContextMap.keySet()); registerSecondaryDexForProfiling(dexPathsForRegistration); } private void notifyPackageManager(Map<String, String> classLoaderContextMap) { private void notifyPackageManager(List<ClassLoader> classLoadersChain, List<String> classPaths) { // Get the class loader names for the binder call. List<String> classLoadersNames = new ArrayList<>(classPaths.size()); for (ClassLoader classLoader : classLoadersChain) { classLoadersNames.add(classLoader.getClass().getName()); } String packageName = ActivityThread.currentPackageName(); try { ActivityThread.getPackageManager().notifyDexLoad(packageName, classLoaderContextMap, VMRuntime.getRuntime().vmInstructionSet()); ActivityThread.getPackageManager().notifyDexLoad( packageName, classLoadersNames, classPaths, VMRuntime.getRuntime().vmInstructionSet()); } catch (RemoteException re) { Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re); } } private void registerSecondaryDexForProfiling(Set<String> dexPaths) { private void registerSecondaryDexForProfiling(String[] dexPaths) { if (!SystemProperties.getBoolean("dalvik.vm.dexopt.secondary", false)) { return; } Loading core/java/android/content/pm/IPackageManager.aidl +11 −4 Original line number Diff line number Diff line Loading @@ -529,12 +529,19 @@ interface IPackageManager { * Notify the package manager that a list of dex files have been loaded. * * @param loadingPackageName the name of the package who performs the load * @param classLoaderContextMap a map from file paths to dex files that have been loaded to * the class loader context that was used to load them. * @param classLoadersNames the names of the class loaders present in the loading chain. The * list encodes the class loader chain in the natural order. The first class loader has * the second one as its parent and so on. The dex files present in the class path of the * first class loader will be recorded in the usage file. * @param classPaths the class paths corresponding to the class loaders names from * {@param classLoadersNames}. The the first element corresponds to the first class loader * and so on. A classpath is represented as a list of dex files separated by * {@code File.pathSeparator}, or null if the class loader's classpath is not known. * The dex files found in the first class path will be recorded in the usage file. * @param loaderIsa the ISA of the loader process */ oneway void notifyDexLoad(String loadingPackageName, in Map<String, String> classLoaderContextMap, String loaderIsa); oneway void notifyDexLoad(String loadingPackageName, in List<String> classLoadersNames, in List<String> classPaths, String loaderIsa); /** * Register an application dex module with the package manager. Loading services/core/java/com/android/server/pm/PackageManagerService.java +3 −3 Original line number Diff line number Diff line Loading @@ -9764,8 +9764,8 @@ public class PackageManagerService extends IPackageManager.Stub } @Override public void notifyDexLoad(String loadingPackageName, Map<String, String> classLoaderContextMap, String loaderIsa) { public void notifyDexLoad(String loadingPackageName, List<String> classLoaderNames, List<String> classPaths, String loaderIsa) { int userId = UserHandle.getCallingUserId(); ApplicationInfo ai = getApplicationInfo(loadingPackageName, /*flags*/ 0, userId); if (ai == null) { Loading @@ -9773,7 +9773,7 @@ public class PackageManagerService extends IPackageManager.Stub + loadingPackageName + ", user=" + userId); return; } mDexManager.notifyDexLoad(ai, classLoaderContextMap, loaderIsa, userId); mDexManager.notifyDexLoad(ai, classLoaderNames, classPaths, loaderIsa, userId); } @Override services/core/java/com/android/server/pm/dex/DexManager.java +47 −17 Original line number Diff line number Diff line Loading @@ -44,8 +44,6 @@ import com.android.server.pm.PackageDexOptimizer; import com.android.server.pm.PackageManagerService; import com.android.server.pm.PackageManagerServiceUtils; import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; import java.util.Arrays; Loading Loading @@ -145,15 +143,22 @@ public class DexManager { * return as fast as possible. * * @param loadingAppInfo the package performing the load * @param classLoaderContextMap a map from file paths to dex files that have been loaded to * the class loader context that was used to load them. * @param classLoadersNames the names of the class loaders present in the loading chain. The * list encodes the class loader chain in the natural order. The first class loader has * the second one as its parent and so on. The dex files present in the class path of the * first class loader will be recorded in the usage file. * @param classPaths the class paths corresponding to the class loaders names from * {@param classLoadersNames}. The the first element corresponds to the first class loader * and so on. A classpath is represented as a list of dex files separated by * {@code File.pathSeparator}, or null if the class loader's classpath is not known. * The dex files found in the first class path will be recorded in the usage file. * @param loaderIsa the ISA of the app loading the dex files * @param loaderUserId the user id which runs the code loading the dex files */ public void notifyDexLoad(ApplicationInfo loadingAppInfo, Map<String, String> classLoaderContextMap, String loaderIsa, int loaderUserId) { public void notifyDexLoad(ApplicationInfo loadingAppInfo, List<String> classLoadersNames, List<String> classPaths, String loaderIsa, int loaderUserId) { try { notifyDexLoadInternal(loadingAppInfo, classLoaderContextMap, loaderIsa, notifyDexLoadInternal(loadingAppInfo, classLoadersNames, classPaths, loaderIsa, loaderUserId); } catch (Exception e) { Slog.w(TAG, "Exception while notifying dex load for package " + Loading @@ -163,23 +168,46 @@ public class DexManager { @VisibleForTesting /*package*/ void notifyDexLoadInternal(ApplicationInfo loadingAppInfo, Map<String, String> classLoaderContextMap, String loaderIsa, List<String> classLoaderNames, List<String> classPaths, String loaderIsa, int loaderUserId) { if (classLoaderContextMap == null) { if (classLoaderNames.size() != classPaths.size()) { Slog.wtf(TAG, "Bad call to noitfyDexLoad: args have different size"); return; } if (classLoaderContextMap.isEmpty()) { if (classLoaderNames.isEmpty()) { Slog.wtf(TAG, "Bad call to notifyDexLoad: class loaders list is empty"); return; } if (!PackageManagerServiceUtils.checkISA(loaderIsa)) { Slog.w(TAG, "Loading dex files " + classLoaderContextMap.keySet() + " in unsupported ISA: " + loaderIsa + "?"); Slog.w(TAG, "Loading dex files " + classPaths + " in unsupported ISA: " + loaderIsa + "?"); return; } for (Map.Entry<String, String> mapping : classLoaderContextMap.entrySet()) { String dexPath = mapping.getKey(); // The first classpath should never be null because the first classloader // should always be an instance of BaseDexClassLoader. String firstClassPath = classPaths.get(0); if (firstClassPath == null) { return; } // The classpath is represented as a list of dex files separated by File.pathSeparator. String[] dexPathsToRegister = firstClassPath.split(File.pathSeparator); // Encode the class loader contexts for the dexPathsToRegister. String[] classLoaderContexts = DexoptUtils.processContextForDexLoad( classLoaderNames, classPaths); // A null classLoaderContexts means that there are unsupported class loaders in the // chain. if (classLoaderContexts == null) { if (DEBUG) { Slog.i(TAG, loadingAppInfo.packageName + " uses unsupported class loader in " + classLoaderNames); } } int dexPathIndex = 0; for (String dexPath : dexPathsToRegister) { // Find the owning package name. DexSearchResult searchResult = getDexPackage(loadingAppInfo, dexPath, loaderUserId); Loading @@ -201,6 +229,7 @@ public class DexManager { // If the dex file is the primary apk (or a split) and not isUsedByOtherApps // do not record it. This case does not bring any new usable information // and can be safely skipped. dexPathIndex++; continue; } Loading @@ -210,13 +239,13 @@ public class DexManager { searchResult.mOwningPackageName, loadingAppInfo.packageName); } String classLoaderContext = mapping.getValue(); if (classLoaderContext != null && VMRuntime.isValidClassLoaderContext(classLoaderContext)) { if (classLoaderContexts != null) { // Record dex file usage. If the current usage is a new pattern (e.g. new // secondary, or UsedByOtherApps), record will return true and we trigger an // async write to disk to make sure we don't loose the data in case of a reboot. String classLoaderContext = classLoaderContexts[dexPathIndex]; if (mPackageDexUsage.record(searchResult.mOwningPackageName, dexPath, loaderUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit, loadingAppInfo.packageName, classLoaderContext)) { Loading @@ -230,6 +259,7 @@ public class DexManager { Slog.i(TAG, "Could not find owning package for dex file: " + dexPath); } } dexPathIndex++; } } Loading services/core/java/com/android/server/pm/dex/PackageDexUsage.java +5 −17 Original line number Diff line number Diff line Loading @@ -83,9 +83,8 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { "=UnknownClassLoaderContext="; // The marker used for unsupported class loader contexts (no longer written, may occur in old // files so discarded on read). Note: this matches // ClassLoaderContext::kUnsupportedClassLoaderContextEncoding in the runtime. /*package*/ static final String UNSUPPORTED_CLASS_LOADER_CONTEXT = // files so discarded on read). private static final String UNSUPPORTED_CLASS_LOADER_CONTEXT = "=UnsupportedClassLoaderContext="; /** Loading Loading @@ -134,9 +133,6 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { if (classLoaderContext == null) { throw new IllegalArgumentException("Null classLoaderContext"); } if (classLoaderContext.equals(UNSUPPORTED_CLASS_LOADER_CONTEXT)) { return false; } synchronized (mPackageUseInfoMap) { PackageUseInfo packageUseInfo = mPackageUseInfoMap.get(owningPackageName); Loading Loading @@ -847,11 +843,10 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages); String oldClassLoaderContext = mClassLoaderContext; if (isUnknownOrUnsupportedContext(mClassLoaderContext)) { if (UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext)) { // Can happen if we read a previous version. mClassLoaderContext = dexUseInfo.mClassLoaderContext; } else if (!isUnknownOrUnsupportedContext(dexUseInfo.mClassLoaderContext) && !Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) { } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) { // We detected a context change. mClassLoaderContext = VARIABLE_CLASS_LOADER_CONTEXT; } Loading @@ -862,13 +857,6 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { || !Objects.equals(oldClassLoaderContext, mClassLoaderContext); } private static boolean isUnknownOrUnsupportedContext(String context) { // TODO: Merge UNKNOWN_CLASS_LOADER_CONTEXT & UNSUPPORTED_CLASS_LOADER_CONTEXT cases // into UNSUPPORTED_CLASS_LOADER_CONTEXT. return UNKNOWN_CLASS_LOADER_CONTEXT.equals(context) || UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(context); } public boolean isUsedByOtherApps() { return mIsUsedByOtherApps; } Loading @@ -890,7 +878,7 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { public boolean isUnknownClassLoaderContext() { // The class loader context may be unknown if we loaded the data from a previous version // which didn't save the context. return isUnknownOrUnsupportedContext(mClassLoaderContext); return UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext); } public boolean isVariableClassLoaderContext() { Loading Loading
core/java/android/app/DexLoadReporter.java +29 −10 Original line number Diff line number Diff line Loading @@ -28,8 +28,9 @@ import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.HashSet; import java.util.Map; import java.util.List; import java.util.Set; /** Loading Loading @@ -86,32 +87,50 @@ import java.util.Set; } @Override public void report(Map<String, String> classLoaderContextMap) { if (classLoaderContextMap.isEmpty()) { Slog.wtf(TAG, "Bad call to DexLoadReporter: empty classLoaderContextMap"); public void report(List<ClassLoader> classLoadersChain, List<String> classPaths) { if (classLoadersChain.size() != classPaths.size()) { Slog.wtf(TAG, "Bad call to DexLoadReporter: argument size mismatch"); return; } if (classPaths.isEmpty()) { Slog.wtf(TAG, "Bad call to DexLoadReporter: empty dex paths"); return; } // The first element of classPaths is the list of dex files that should be registered. // The classpath is represented as a list of dex files separated by File.pathSeparator. String[] dexPathsForRegistration = classPaths.get(0).split(File.pathSeparator); if (dexPathsForRegistration.length == 0) { // No dex files to register. return; } // Notify the package manager about the dex loads unconditionally. // The load might be for either a primary or secondary dex file. notifyPackageManager(classLoaderContextMap); notifyPackageManager(classLoadersChain, classPaths); // Check for secondary dex files and register them for profiling if possible. // Note that we only register the dex paths belonging to the first class loader. registerSecondaryDexForProfiling(classLoaderContextMap.keySet()); registerSecondaryDexForProfiling(dexPathsForRegistration); } private void notifyPackageManager(Map<String, String> classLoaderContextMap) { private void notifyPackageManager(List<ClassLoader> classLoadersChain, List<String> classPaths) { // Get the class loader names for the binder call. List<String> classLoadersNames = new ArrayList<>(classPaths.size()); for (ClassLoader classLoader : classLoadersChain) { classLoadersNames.add(classLoader.getClass().getName()); } String packageName = ActivityThread.currentPackageName(); try { ActivityThread.getPackageManager().notifyDexLoad(packageName, classLoaderContextMap, VMRuntime.getRuntime().vmInstructionSet()); ActivityThread.getPackageManager().notifyDexLoad( packageName, classLoadersNames, classPaths, VMRuntime.getRuntime().vmInstructionSet()); } catch (RemoteException re) { Slog.e(TAG, "Failed to notify PM about dex load for package " + packageName, re); } } private void registerSecondaryDexForProfiling(Set<String> dexPaths) { private void registerSecondaryDexForProfiling(String[] dexPaths) { if (!SystemProperties.getBoolean("dalvik.vm.dexopt.secondary", false)) { return; } Loading
core/java/android/content/pm/IPackageManager.aidl +11 −4 Original line number Diff line number Diff line Loading @@ -529,12 +529,19 @@ interface IPackageManager { * Notify the package manager that a list of dex files have been loaded. * * @param loadingPackageName the name of the package who performs the load * @param classLoaderContextMap a map from file paths to dex files that have been loaded to * the class loader context that was used to load them. * @param classLoadersNames the names of the class loaders present in the loading chain. The * list encodes the class loader chain in the natural order. The first class loader has * the second one as its parent and so on. The dex files present in the class path of the * first class loader will be recorded in the usage file. * @param classPaths the class paths corresponding to the class loaders names from * {@param classLoadersNames}. The the first element corresponds to the first class loader * and so on. A classpath is represented as a list of dex files separated by * {@code File.pathSeparator}, or null if the class loader's classpath is not known. * The dex files found in the first class path will be recorded in the usage file. * @param loaderIsa the ISA of the loader process */ oneway void notifyDexLoad(String loadingPackageName, in Map<String, String> classLoaderContextMap, String loaderIsa); oneway void notifyDexLoad(String loadingPackageName, in List<String> classLoadersNames, in List<String> classPaths, String loaderIsa); /** * Register an application dex module with the package manager. Loading
services/core/java/com/android/server/pm/PackageManagerService.java +3 −3 Original line number Diff line number Diff line Loading @@ -9764,8 +9764,8 @@ public class PackageManagerService extends IPackageManager.Stub } @Override public void notifyDexLoad(String loadingPackageName, Map<String, String> classLoaderContextMap, String loaderIsa) { public void notifyDexLoad(String loadingPackageName, List<String> classLoaderNames, List<String> classPaths, String loaderIsa) { int userId = UserHandle.getCallingUserId(); ApplicationInfo ai = getApplicationInfo(loadingPackageName, /*flags*/ 0, userId); if (ai == null) { Loading @@ -9773,7 +9773,7 @@ public class PackageManagerService extends IPackageManager.Stub + loadingPackageName + ", user=" + userId); return; } mDexManager.notifyDexLoad(ai, classLoaderContextMap, loaderIsa, userId); mDexManager.notifyDexLoad(ai, classLoaderNames, classPaths, loaderIsa, userId); } @Override
services/core/java/com/android/server/pm/dex/DexManager.java +47 −17 Original line number Diff line number Diff line Loading @@ -44,8 +44,6 @@ import com.android.server.pm.PackageDexOptimizer; import com.android.server.pm.PackageManagerService; import com.android.server.pm.PackageManagerServiceUtils; import dalvik.system.VMRuntime; import java.io.File; import java.io.IOException; import java.util.Arrays; Loading Loading @@ -145,15 +143,22 @@ public class DexManager { * return as fast as possible. * * @param loadingAppInfo the package performing the load * @param classLoaderContextMap a map from file paths to dex files that have been loaded to * the class loader context that was used to load them. * @param classLoadersNames the names of the class loaders present in the loading chain. The * list encodes the class loader chain in the natural order. The first class loader has * the second one as its parent and so on. The dex files present in the class path of the * first class loader will be recorded in the usage file. * @param classPaths the class paths corresponding to the class loaders names from * {@param classLoadersNames}. The the first element corresponds to the first class loader * and so on. A classpath is represented as a list of dex files separated by * {@code File.pathSeparator}, or null if the class loader's classpath is not known. * The dex files found in the first class path will be recorded in the usage file. * @param loaderIsa the ISA of the app loading the dex files * @param loaderUserId the user id which runs the code loading the dex files */ public void notifyDexLoad(ApplicationInfo loadingAppInfo, Map<String, String> classLoaderContextMap, String loaderIsa, int loaderUserId) { public void notifyDexLoad(ApplicationInfo loadingAppInfo, List<String> classLoadersNames, List<String> classPaths, String loaderIsa, int loaderUserId) { try { notifyDexLoadInternal(loadingAppInfo, classLoaderContextMap, loaderIsa, notifyDexLoadInternal(loadingAppInfo, classLoadersNames, classPaths, loaderIsa, loaderUserId); } catch (Exception e) { Slog.w(TAG, "Exception while notifying dex load for package " + Loading @@ -163,23 +168,46 @@ public class DexManager { @VisibleForTesting /*package*/ void notifyDexLoadInternal(ApplicationInfo loadingAppInfo, Map<String, String> classLoaderContextMap, String loaderIsa, List<String> classLoaderNames, List<String> classPaths, String loaderIsa, int loaderUserId) { if (classLoaderContextMap == null) { if (classLoaderNames.size() != classPaths.size()) { Slog.wtf(TAG, "Bad call to noitfyDexLoad: args have different size"); return; } if (classLoaderContextMap.isEmpty()) { if (classLoaderNames.isEmpty()) { Slog.wtf(TAG, "Bad call to notifyDexLoad: class loaders list is empty"); return; } if (!PackageManagerServiceUtils.checkISA(loaderIsa)) { Slog.w(TAG, "Loading dex files " + classLoaderContextMap.keySet() + " in unsupported ISA: " + loaderIsa + "?"); Slog.w(TAG, "Loading dex files " + classPaths + " in unsupported ISA: " + loaderIsa + "?"); return; } for (Map.Entry<String, String> mapping : classLoaderContextMap.entrySet()) { String dexPath = mapping.getKey(); // The first classpath should never be null because the first classloader // should always be an instance of BaseDexClassLoader. String firstClassPath = classPaths.get(0); if (firstClassPath == null) { return; } // The classpath is represented as a list of dex files separated by File.pathSeparator. String[] dexPathsToRegister = firstClassPath.split(File.pathSeparator); // Encode the class loader contexts for the dexPathsToRegister. String[] classLoaderContexts = DexoptUtils.processContextForDexLoad( classLoaderNames, classPaths); // A null classLoaderContexts means that there are unsupported class loaders in the // chain. if (classLoaderContexts == null) { if (DEBUG) { Slog.i(TAG, loadingAppInfo.packageName + " uses unsupported class loader in " + classLoaderNames); } } int dexPathIndex = 0; for (String dexPath : dexPathsToRegister) { // Find the owning package name. DexSearchResult searchResult = getDexPackage(loadingAppInfo, dexPath, loaderUserId); Loading @@ -201,6 +229,7 @@ public class DexManager { // If the dex file is the primary apk (or a split) and not isUsedByOtherApps // do not record it. This case does not bring any new usable information // and can be safely skipped. dexPathIndex++; continue; } Loading @@ -210,13 +239,13 @@ public class DexManager { searchResult.mOwningPackageName, loadingAppInfo.packageName); } String classLoaderContext = mapping.getValue(); if (classLoaderContext != null && VMRuntime.isValidClassLoaderContext(classLoaderContext)) { if (classLoaderContexts != null) { // Record dex file usage. If the current usage is a new pattern (e.g. new // secondary, or UsedByOtherApps), record will return true and we trigger an // async write to disk to make sure we don't loose the data in case of a reboot. String classLoaderContext = classLoaderContexts[dexPathIndex]; if (mPackageDexUsage.record(searchResult.mOwningPackageName, dexPath, loaderUserId, loaderIsa, isUsedByOtherApps, primaryOrSplit, loadingAppInfo.packageName, classLoaderContext)) { Loading @@ -230,6 +259,7 @@ public class DexManager { Slog.i(TAG, "Could not find owning package for dex file: " + dexPath); } } dexPathIndex++; } } Loading
services/core/java/com/android/server/pm/dex/PackageDexUsage.java +5 −17 Original line number Diff line number Diff line Loading @@ -83,9 +83,8 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { "=UnknownClassLoaderContext="; // The marker used for unsupported class loader contexts (no longer written, may occur in old // files so discarded on read). Note: this matches // ClassLoaderContext::kUnsupportedClassLoaderContextEncoding in the runtime. /*package*/ static final String UNSUPPORTED_CLASS_LOADER_CONTEXT = // files so discarded on read). private static final String UNSUPPORTED_CLASS_LOADER_CONTEXT = "=UnsupportedClassLoaderContext="; /** Loading Loading @@ -134,9 +133,6 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { if (classLoaderContext == null) { throw new IllegalArgumentException("Null classLoaderContext"); } if (classLoaderContext.equals(UNSUPPORTED_CLASS_LOADER_CONTEXT)) { return false; } synchronized (mPackageUseInfoMap) { PackageUseInfo packageUseInfo = mPackageUseInfoMap.get(owningPackageName); Loading Loading @@ -847,11 +843,10 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { boolean updateLoadingPackages = mLoadingPackages.addAll(dexUseInfo.mLoadingPackages); String oldClassLoaderContext = mClassLoaderContext; if (isUnknownOrUnsupportedContext(mClassLoaderContext)) { if (UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext)) { // Can happen if we read a previous version. mClassLoaderContext = dexUseInfo.mClassLoaderContext; } else if (!isUnknownOrUnsupportedContext(dexUseInfo.mClassLoaderContext) && !Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) { } else if (!Objects.equals(mClassLoaderContext, dexUseInfo.mClassLoaderContext)) { // We detected a context change. mClassLoaderContext = VARIABLE_CLASS_LOADER_CONTEXT; } Loading @@ -862,13 +857,6 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { || !Objects.equals(oldClassLoaderContext, mClassLoaderContext); } private static boolean isUnknownOrUnsupportedContext(String context) { // TODO: Merge UNKNOWN_CLASS_LOADER_CONTEXT & UNSUPPORTED_CLASS_LOADER_CONTEXT cases // into UNSUPPORTED_CLASS_LOADER_CONTEXT. return UNKNOWN_CLASS_LOADER_CONTEXT.equals(context) || UNSUPPORTED_CLASS_LOADER_CONTEXT.equals(context); } public boolean isUsedByOtherApps() { return mIsUsedByOtherApps; } Loading @@ -890,7 +878,7 @@ public class PackageDexUsage extends AbstractStatsBase<Void> { public boolean isUnknownClassLoaderContext() { // The class loader context may be unknown if we loaded the data from a previous version // which didn't save the context. return isUnknownOrUnsupportedContext(mClassLoaderContext); return UNKNOWN_CLASS_LOADER_CONTEXT.equals(mClassLoaderContext); } public boolean isVariableClassLoaderContext() { Loading