Loading services/core/java/com/android/server/pm/OtaDexoptService.java +1 −1 Original line number Diff line number Diff line Loading @@ -318,7 +318,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { optimizer.performDexOpt(pkg, libraryDependencies, null /* ISAs */, null /* CompilerStats.PackageStats */, mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName), new DexoptOptions(pkg.packageName, compilationReason, DexoptOptions.DEXOPT_BOOT_COMPLETE)); Loading services/core/java/com/android/server/pm/PackageDexOptimizer.java +15 −11 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.DexoptUtils; import com.android.server.pm.dex.PackageDexUsage; Loading Loading @@ -112,7 +113,7 @@ public class PackageDexOptimizer { */ int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, String[] instructionSets, CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps, DexoptOptions options) { PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) { if (!canOptimizePackage(pkg)) { return DEX_OPT_SKIPPED; } Loading @@ -120,7 +121,7 @@ public class PackageDexOptimizer { final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid); try { return performDexOptLI(pkg, sharedLibraries, instructionSets, packageStats, isUsedByOtherApps, options); packageStats, packageUseInfo, options); } finally { releaseWakeLockLI(acquireTime); } Loading @@ -134,21 +135,13 @@ public class PackageDexOptimizer { @GuardedBy("mInstallLock") private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, String[] targetInstructionSets, CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps, DexoptOptions options) { PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) { final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); final List<String> paths = pkg.getAllCodePaths(); final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, options.getCompilerFilter(), isUsedByOtherApps); final boolean profileUpdated = options.isCheckForProfileUpdates() && isProfileUpdated(pkg, sharedGid, compilerFilter); // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags. final int dexoptFlags = getDexFlags(pkg, compilerFilter, options.isBootComplete()); // Get the class loader context dependencies. // For each code path in the package, this array contains the class loader context that // needs to be passed to dexopt in order to ensure correct optimizations. Loading @@ -172,6 +165,17 @@ public class PackageDexOptimizer { } } final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, options.getCompilerFilter(), isUsedByOtherApps); final boolean profileUpdated = options.isCheckForProfileUpdates() && isProfileUpdated(pkg, sharedGid, compilerFilter); // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct // flags. final int dexoptFlags = getDexFlags(pkg, compilerFilter, options.isBootComplete()); for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter, profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid, Loading services/core/java/com/android/server/pm/PackageManagerService.java +9 −7 Original line number Diff line number Diff line Loading @@ -9887,17 +9887,19 @@ public class PackageManagerService extends IPackageManager.Stub Collection<PackageParser.Package> deps = findSharedNonSystemLibraries(p); final String[] instructionSets = getAppDexInstructionSets(p.applicationInfo); if (!deps.isEmpty()) { DexoptOptions libraryOptions = new DexoptOptions(options.getPackageName(), options.getCompilerFilter(), options.getSplitName(), options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY); for (PackageParser.Package depPackage : deps) { // TODO: Analyze and investigate if we (should) profile libraries. pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets, getOrCreateCompilerPackageStats(depPackage), true /* isUsedByOtherApps */, options); mDexManager.getPackageUseInfoOrDefault(depPackage.packageName), libraryOptions); } } return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, getOrCreateCompilerPackageStats(p), mDexManager.isUsedByOtherApps(p.packageName), options); mDexManager.getPackageUseInfoOrDefault(p.packageName), options); } /** Loading Loading @@ -10023,7 +10025,7 @@ public class PackageManagerService extends IPackageManager.Stub public void shutdown() { mPackageUsage.writeNow(mPackages); mCompilerStats.writeNow(); mDexManager.savePackageDexUsageNow(); mDexManager.writePackageDexUsageNow(); } @Override Loading Loading @@ -18587,7 +18589,7 @@ public class PackageManagerService extends IPackageManager.Stub mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, null /* instructionSets */, getOrCreateCompilerPackageStats(pkg), mDexManager.isUsedByOtherApps(pkg.packageName), mDexManager.getPackageUseInfoOrDefault(pkg.packageName), dexoptOptions); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Loading Loading @@ -25424,8 +25426,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); if (ps == null) { continue; } PackageDexUsage.PackageUseInfo packageUseInfo = getDexManager().getPackageUseInfo( pkg.packageName); PackageDexUsage.PackageUseInfo packageUseInfo = getDexManager().getPackageUseInfoOrDefault(pkg.packageName); if (PackageManagerServiceUtils .isUnusedSinceTimeInMillis(ps.firstInstallTime, currentTimeInMillis, downgradeTimeThresholdMillis, packageUseInfo, services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +5 −6 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.app.AppGlobals; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageParser; import android.content.pm.ResolveInfo; import android.os.Build; Loading Loading @@ -137,9 +136,11 @@ public class PackageManagerServiceUtils { sortTemp, packageManagerService); // Give priority to apps used by other apps. DexManager dexManager = packageManagerService.getDexManager(); applyPackageFilter((pkg) -> packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result, remainingPkgs, sortTemp, packageManagerService); dexManager.getPackageUseInfoOrDefault(pkg.packageName) .isAnyCodePathUsedByOtherApps(), result, remainingPkgs, sortTemp, packageManagerService); // Filter out packages that aren't recently used, add all remaining apps. // TODO: add a property to control this? Loading Loading @@ -209,12 +210,10 @@ public class PackageManagerServiceUtils { // If the app was active in background during the threshold period and was used // by other packages. // If packageUseInfo is null, it can be said that the package was not used by other // packages. boolean isActiveInBackgroundAndUsedByOtherPackages = ((currentTimeInMillis - latestPackageUseTimeInMillis) < thresholdTimeinMillis) && (packageUseInfo != null && packageUseInfo.isUsedByOtherApps()); && packageUseInfo.isAnyCodePathUsedByOtherApps(); return !isActiveInBackgroundAndUsedByOtherPackages; } Loading services/core/java/com/android/server/pm/dex/DexManager.java +54 −26 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ import com.android.server.pm.PackageManagerServiceCompilerMapping; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.HashMap; import java.util.HashSet; Loading Loading @@ -81,6 +83,19 @@ public class DexManager { private static int DEX_SEARCH_FOUND_SPLIT = 2; // dex file is a split apk private static int DEX_SEARCH_FOUND_SECONDARY = 3; // dex file is a secondary dex /** * We do not record packages that have no secondary dex files or that are not used by other * apps. This is an optimization to reduce the amount of data that needs to be written to * disk (apps will not usually be shared so this trims quite a bit the number we record). * * To make this behaviour transparent to the callers which need use information on packages, * DexManager will return this DEFAULT instance from * {@link DexManager#getPackageUseInfoOrDefault}. It has no data about secondary dex files and * is marked as not being used by other apps. This reflects the intended behaviour when we don't * find the package in the underlying data file. */ private final static PackageUseInfo DEFAULT_USE_INFO = new PackageUseInfo(); public DexManager(IPackageManager pms, PackageDexOptimizer pdo, Installer installer, Object installLock) { mPackageCodeLocationsCache = new HashMap<>(); Loading Loading @@ -297,6 +312,8 @@ public class DexManager { private void loadInternal(Map<Integer, List<PackageInfo>> existingPackages) { Map<String, Set<Integer>> packageToUsersMap = new HashMap<>(); Map<String, Set<String>> packageToCodePaths = new HashMap<>(); // Cache the code locations for the installed packages. This allows for // faster lookups (no locks) when finding what package owns the dex file. for (Map.Entry<Integer, List<PackageInfo>> entry : existingPackages.entrySet()) { Loading @@ -306,25 +323,53 @@ public class DexManager { // Cache the code locations. cachePackageInfo(pi, userId); // Cache a map from package name to the set of user ids who installed the package. // Cache two maps: // - from package name to the set of user ids who installed the package. // - from package name to the set of code paths. // We will use it to sync the data and remove obsolete entries from // mPackageDexUsage. Set<Integer> users = putIfAbsent( packageToUsersMap, pi.packageName, new HashSet<>()); users.add(userId); Set<String> codePaths = putIfAbsent( packageToCodePaths, pi.packageName, new HashSet<>()); codePaths.add(pi.applicationInfo.sourceDir); if (pi.applicationInfo.splitSourceDirs != null) { Collections.addAll(codePaths, pi.applicationInfo.splitSourceDirs); } } } mPackageDexUsage.read(); mPackageDexUsage.syncData(packageToUsersMap); mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths); } /** * Get the package dex usage for the given package name. * @return the package data or null if there is no data available for this package. * If there is no usage info the method will return a default {@code PackageUseInfo} with * no data about secondary dex files and marked as not being used by other apps. * * Note that no use info means the package was not used or it was used but not by other apps. * Also, note that right now we might prune packages which are not used by other apps. * TODO(calin): maybe we should not (prune) so we can have an accurate view when we try * to access the package use. */ public PackageUseInfo getPackageUseInfoOrDefault(String packageName) { PackageUseInfo useInfo = mPackageDexUsage.getPackageUseInfo(packageName); return useInfo == null ? DEFAULT_USE_INFO : useInfo; } /** * Return whether or not the manager has usage information on the give package. * * Note that no use info means the package was not used or it was used but not by other apps. * Also, note that right now we might prune packages which are not used by other apps. * TODO(calin): maybe we should not (prune) so we can have an accurate view when we try * to access the package use. */ public PackageUseInfo getPackageUseInfo(String packageName) { return mPackageDexUsage.getPackageUseInfo(packageName); /*package*/ boolean hasInfoOnPackage(String packageName) { return mPackageDexUsage.getPackageUseInfo(packageName) != null; } /** Loading @@ -343,7 +388,7 @@ public class DexManager { ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; String packageName = options.getPackageName(); PackageUseInfo useInfo = getPackageUseInfo(packageName); PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName); if (useInfo == null || useInfo.getDexUseInfoMap().isEmpty()) { if (DEBUG) { Slog.d(TAG, "No secondary dex use for package:" + packageName); Loading Loading @@ -387,7 +432,7 @@ public class DexManager { * deleted, update the internal records and delete any generated oat files. */ public void reconcileSecondaryDexFiles(String packageName) { PackageUseInfo useInfo = getPackageUseInfo(packageName); PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName); if (useInfo == null || useInfo.getDexUseInfoMap().isEmpty()) { if (DEBUG) { Slog.d(TAG, "No secondary dex use for package:" + packageName); Loading Loading @@ -518,23 +563,6 @@ public class DexManager { return mPackageDexUsage.getAllPackagesWithSecondaryDexFiles(); } /** * Return true if the profiling data collected for the given app indicate * that the apps's APK has been loaded by another app. * Note that this returns false for all apps without any collected profiling data. */ public boolean isUsedByOtherApps(String packageName) { PackageUseInfo useInfo = getPackageUseInfo(packageName); if (useInfo == null) { // No use info, means the package was not used or it was used but not by other apps. // Note that right now we might prune packages which are not used by other apps. // TODO(calin): maybe we should not (prune) so we can have an accurate view when we try // to access the package use. return false; } return useInfo.isUsedByOtherApps(); } /** * Retrieves the package which owns the given dexPath. */ Loading Loading @@ -593,9 +621,9 @@ public class DexManager { } /** * Saves the in-memory package dex usage to disk right away. * Writes the in-memory package dex usage to disk right away. */ public void savePackageDexUsageNow() { public void writePackageDexUsageNow() { mPackageDexUsage.writeNow(); } Loading Loading
services/core/java/com/android/server/pm/OtaDexoptService.java +1 −1 Original line number Diff line number Diff line Loading @@ -318,7 +318,7 @@ public class OtaDexoptService extends IOtaDexopt.Stub { optimizer.performDexOpt(pkg, libraryDependencies, null /* ISAs */, null /* CompilerStats.PackageStats */, mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), mPackageManagerService.getDexManager().getPackageUseInfoOrDefault(pkg.packageName), new DexoptOptions(pkg.packageName, compilationReason, DexoptOptions.DEXOPT_BOOT_COMPLETE)); Loading
services/core/java/com/android/server/pm/PackageDexOptimizer.java +15 −11 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.util.IndentingPrintWriter; import com.android.server.pm.Installer.InstallerException; import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.DexoptUtils; import com.android.server.pm.dex.PackageDexUsage; Loading Loading @@ -112,7 +113,7 @@ public class PackageDexOptimizer { */ int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, String[] instructionSets, CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps, DexoptOptions options) { PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) { if (!canOptimizePackage(pkg)) { return DEX_OPT_SKIPPED; } Loading @@ -120,7 +121,7 @@ public class PackageDexOptimizer { final long acquireTime = acquireWakeLockLI(pkg.applicationInfo.uid); try { return performDexOptLI(pkg, sharedLibraries, instructionSets, packageStats, isUsedByOtherApps, options); packageStats, packageUseInfo, options); } finally { releaseWakeLockLI(acquireTime); } Loading @@ -134,21 +135,13 @@ public class PackageDexOptimizer { @GuardedBy("mInstallLock") private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, String[] targetInstructionSets, CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps, DexoptOptions options) { PackageDexUsage.PackageUseInfo packageUseInfo, DexoptOptions options) { final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); final List<String> paths = pkg.getAllCodePaths(); final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, options.getCompilerFilter(), isUsedByOtherApps); final boolean profileUpdated = options.isCheckForProfileUpdates() && isProfileUpdated(pkg, sharedGid, compilerFilter); // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct flags. final int dexoptFlags = getDexFlags(pkg, compilerFilter, options.isBootComplete()); // Get the class loader context dependencies. // For each code path in the package, this array contains the class loader context that // needs to be passed to dexopt in order to ensure correct optimizations. Loading @@ -172,6 +165,17 @@ public class PackageDexOptimizer { } } final boolean isUsedByOtherApps = options.isDexoptAsSharedLibrary() || packageUseInfo.isUsedByOtherApps(path); final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, options.getCompilerFilter(), isUsedByOtherApps); final boolean profileUpdated = options.isCheckForProfileUpdates() && isProfileUpdated(pkg, sharedGid, compilerFilter); // Get the dexopt flags after getRealCompilerFilter to make sure we get the correct // flags. final int dexoptFlags = getDexFlags(pkg, compilerFilter, options.isBootComplete()); for (String dexCodeIsa : dexCodeInstructionSets) { int newResult = dexOptPath(pkg, path, dexCodeIsa, compilerFilter, profileUpdated, classLoaderContexts[i], dexoptFlags, sharedGid, Loading
services/core/java/com/android/server/pm/PackageManagerService.java +9 −7 Original line number Diff line number Diff line Loading @@ -9887,17 +9887,19 @@ public class PackageManagerService extends IPackageManager.Stub Collection<PackageParser.Package> deps = findSharedNonSystemLibraries(p); final String[] instructionSets = getAppDexInstructionSets(p.applicationInfo); if (!deps.isEmpty()) { DexoptOptions libraryOptions = new DexoptOptions(options.getPackageName(), options.getCompilerFilter(), options.getSplitName(), options.getFlags() | DexoptOptions.DEXOPT_AS_SHARED_LIBRARY); for (PackageParser.Package depPackage : deps) { // TODO: Analyze and investigate if we (should) profile libraries. pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets, getOrCreateCompilerPackageStats(depPackage), true /* isUsedByOtherApps */, options); mDexManager.getPackageUseInfoOrDefault(depPackage.packageName), libraryOptions); } } return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, getOrCreateCompilerPackageStats(p), mDexManager.isUsedByOtherApps(p.packageName), options); mDexManager.getPackageUseInfoOrDefault(p.packageName), options); } /** Loading Loading @@ -10023,7 +10025,7 @@ public class PackageManagerService extends IPackageManager.Stub public void shutdown() { mPackageUsage.writeNow(mPackages); mCompilerStats.writeNow(); mDexManager.savePackageDexUsageNow(); mDexManager.writePackageDexUsageNow(); } @Override Loading Loading @@ -18587,7 +18589,7 @@ public class PackageManagerService extends IPackageManager.Stub mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, null /* instructionSets */, getOrCreateCompilerPackageStats(pkg), mDexManager.isUsedByOtherApps(pkg.packageName), mDexManager.getPackageUseInfoOrDefault(pkg.packageName), dexoptOptions); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } Loading Loading @@ -25424,8 +25426,8 @@ Slog.v(TAG, ":: stepped forward, applying functor at tag " + parser.getName()); if (ps == null) { continue; } PackageDexUsage.PackageUseInfo packageUseInfo = getDexManager().getPackageUseInfo( pkg.packageName); PackageDexUsage.PackageUseInfo packageUseInfo = getDexManager().getPackageUseInfoOrDefault(pkg.packageName); if (PackageManagerServiceUtils .isUnusedSinceTimeInMillis(ps.firstInstallTime, currentTimeInMillis, downgradeTimeThresholdMillis, packageUseInfo,
services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +5 −6 Original line number Diff line number Diff line Loading @@ -25,7 +25,6 @@ import static com.android.server.pm.PackageManagerService.TAG; import android.annotation.NonNull; import android.app.AppGlobals; import android.content.Intent; import android.content.pm.PackageInfo; import android.content.pm.PackageParser; import android.content.pm.ResolveInfo; import android.os.Build; Loading Loading @@ -137,9 +136,11 @@ public class PackageManagerServiceUtils { sortTemp, packageManagerService); // Give priority to apps used by other apps. DexManager dexManager = packageManagerService.getDexManager(); applyPackageFilter((pkg) -> packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result, remainingPkgs, sortTemp, packageManagerService); dexManager.getPackageUseInfoOrDefault(pkg.packageName) .isAnyCodePathUsedByOtherApps(), result, remainingPkgs, sortTemp, packageManagerService); // Filter out packages that aren't recently used, add all remaining apps. // TODO: add a property to control this? Loading Loading @@ -209,12 +210,10 @@ public class PackageManagerServiceUtils { // If the app was active in background during the threshold period and was used // by other packages. // If packageUseInfo is null, it can be said that the package was not used by other // packages. boolean isActiveInBackgroundAndUsedByOtherPackages = ((currentTimeInMillis - latestPackageUseTimeInMillis) < thresholdTimeinMillis) && (packageUseInfo != null && packageUseInfo.isUsedByOtherApps()); && packageUseInfo.isAnyCodePathUsedByOtherApps(); return !isActiveInBackgroundAndUsedByOtherPackages; } Loading
services/core/java/com/android/server/pm/dex/DexManager.java +54 −26 Original line number Diff line number Diff line Loading @@ -36,6 +36,8 @@ import com.android.server.pm.PackageManagerServiceCompilerMapping; import java.io.File; import java.io.IOException; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.HashMap; import java.util.HashSet; Loading Loading @@ -81,6 +83,19 @@ public class DexManager { private static int DEX_SEARCH_FOUND_SPLIT = 2; // dex file is a split apk private static int DEX_SEARCH_FOUND_SECONDARY = 3; // dex file is a secondary dex /** * We do not record packages that have no secondary dex files or that are not used by other * apps. This is an optimization to reduce the amount of data that needs to be written to * disk (apps will not usually be shared so this trims quite a bit the number we record). * * To make this behaviour transparent to the callers which need use information on packages, * DexManager will return this DEFAULT instance from * {@link DexManager#getPackageUseInfoOrDefault}. It has no data about secondary dex files and * is marked as not being used by other apps. This reflects the intended behaviour when we don't * find the package in the underlying data file. */ private final static PackageUseInfo DEFAULT_USE_INFO = new PackageUseInfo(); public DexManager(IPackageManager pms, PackageDexOptimizer pdo, Installer installer, Object installLock) { mPackageCodeLocationsCache = new HashMap<>(); Loading Loading @@ -297,6 +312,8 @@ public class DexManager { private void loadInternal(Map<Integer, List<PackageInfo>> existingPackages) { Map<String, Set<Integer>> packageToUsersMap = new HashMap<>(); Map<String, Set<String>> packageToCodePaths = new HashMap<>(); // Cache the code locations for the installed packages. This allows for // faster lookups (no locks) when finding what package owns the dex file. for (Map.Entry<Integer, List<PackageInfo>> entry : existingPackages.entrySet()) { Loading @@ -306,25 +323,53 @@ public class DexManager { // Cache the code locations. cachePackageInfo(pi, userId); // Cache a map from package name to the set of user ids who installed the package. // Cache two maps: // - from package name to the set of user ids who installed the package. // - from package name to the set of code paths. // We will use it to sync the data and remove obsolete entries from // mPackageDexUsage. Set<Integer> users = putIfAbsent( packageToUsersMap, pi.packageName, new HashSet<>()); users.add(userId); Set<String> codePaths = putIfAbsent( packageToCodePaths, pi.packageName, new HashSet<>()); codePaths.add(pi.applicationInfo.sourceDir); if (pi.applicationInfo.splitSourceDirs != null) { Collections.addAll(codePaths, pi.applicationInfo.splitSourceDirs); } } } mPackageDexUsage.read(); mPackageDexUsage.syncData(packageToUsersMap); mPackageDexUsage.syncData(packageToUsersMap, packageToCodePaths); } /** * Get the package dex usage for the given package name. * @return the package data or null if there is no data available for this package. * If there is no usage info the method will return a default {@code PackageUseInfo} with * no data about secondary dex files and marked as not being used by other apps. * * Note that no use info means the package was not used or it was used but not by other apps. * Also, note that right now we might prune packages which are not used by other apps. * TODO(calin): maybe we should not (prune) so we can have an accurate view when we try * to access the package use. */ public PackageUseInfo getPackageUseInfoOrDefault(String packageName) { PackageUseInfo useInfo = mPackageDexUsage.getPackageUseInfo(packageName); return useInfo == null ? DEFAULT_USE_INFO : useInfo; } /** * Return whether or not the manager has usage information on the give package. * * Note that no use info means the package was not used or it was used but not by other apps. * Also, note that right now we might prune packages which are not used by other apps. * TODO(calin): maybe we should not (prune) so we can have an accurate view when we try * to access the package use. */ public PackageUseInfo getPackageUseInfo(String packageName) { return mPackageDexUsage.getPackageUseInfo(packageName); /*package*/ boolean hasInfoOnPackage(String packageName) { return mPackageDexUsage.getPackageUseInfo(packageName) != null; } /** Loading @@ -343,7 +388,7 @@ public class DexManager { ? new PackageDexOptimizer.ForcedUpdatePackageDexOptimizer(mPackageDexOptimizer) : mPackageDexOptimizer; String packageName = options.getPackageName(); PackageUseInfo useInfo = getPackageUseInfo(packageName); PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName); if (useInfo == null || useInfo.getDexUseInfoMap().isEmpty()) { if (DEBUG) { Slog.d(TAG, "No secondary dex use for package:" + packageName); Loading Loading @@ -387,7 +432,7 @@ public class DexManager { * deleted, update the internal records and delete any generated oat files. */ public void reconcileSecondaryDexFiles(String packageName) { PackageUseInfo useInfo = getPackageUseInfo(packageName); PackageUseInfo useInfo = getPackageUseInfoOrDefault(packageName); if (useInfo == null || useInfo.getDexUseInfoMap().isEmpty()) { if (DEBUG) { Slog.d(TAG, "No secondary dex use for package:" + packageName); Loading Loading @@ -518,23 +563,6 @@ public class DexManager { return mPackageDexUsage.getAllPackagesWithSecondaryDexFiles(); } /** * Return true if the profiling data collected for the given app indicate * that the apps's APK has been loaded by another app. * Note that this returns false for all apps without any collected profiling data. */ public boolean isUsedByOtherApps(String packageName) { PackageUseInfo useInfo = getPackageUseInfo(packageName); if (useInfo == null) { // No use info, means the package was not used or it was used but not by other apps. // Note that right now we might prune packages which are not used by other apps. // TODO(calin): maybe we should not (prune) so we can have an accurate view when we try // to access the package use. return false; } return useInfo.isUsedByOtherApps(); } /** * Retrieves the package which owns the given dexPath. */ Loading Loading @@ -593,9 +621,9 @@ public class DexManager { } /** * Saves the in-memory package dex usage to disk right away. * Writes the in-memory package dex usage to disk right away. */ public void savePackageDexUsageNow() { public void writePackageDexUsageNow() { mPackageDexUsage.writeNow(); } Loading