diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java index 60c83b404739e..9418e742f7280 100644 --- a/services/core/java/com/android/server/pm/OtaDexoptService.java +++ b/services/core/java/com/android/server/pm/OtaDexoptService.java @@ -313,7 +313,8 @@ public class OtaDexoptService extends IOtaDexopt.Stub { optimizer.performDexOpt(pkg, libraryDependencies, null /* ISAs */, false /* checkProfiles */, getCompilerFilterForReason(compilationReason), - null /* CompilerStats.PackageStats */); + null /* CompilerStats.PackageStats */, + mPackageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName)); return commands; } diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index b589057ada3e6..d9ea7284616d2 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -104,7 +104,7 @@ public class PackageDexOptimizer { */ int performDexOpt(PackageParser.Package pkg, String[] sharedLibraries, String[] instructionSets, boolean checkProfiles, String targetCompilationFilter, - CompilerStats.PackageStats packageStats) { + CompilerStats.PackageStats packageStats, boolean isUsedByOtherApps) { if (!canOptimizePackage(pkg)) { return DEX_OPT_SKIPPED; } @@ -119,7 +119,7 @@ public class PackageDexOptimizer { } try { return performDexOptLI(pkg, sharedLibraries, instructionSets, checkProfiles, - targetCompilationFilter, packageStats); + targetCompilationFilter, packageStats, isUsedByOtherApps); } finally { if (useLock) { mDexoptWakeLock.release(); @@ -135,7 +135,8 @@ public class PackageDexOptimizer { @GuardedBy("mInstallLock") private int performDexOptLI(PackageParser.Package pkg, String[] sharedLibraries, String[] targetInstructionSets, boolean checkForProfileUpdates, - String targetCompilerFilter, CompilerStats.PackageStats packageStats) { + String targetCompilerFilter, CompilerStats.PackageStats packageStats, + boolean isUsedByOtherApps) { final String[] instructionSets = targetInstructionSets != null ? targetInstructionSets : getAppDexInstructionSets(pkg.applicationInfo); final String[] dexCodeInstructionSets = getDexCodeInstructionSets(instructionSets); @@ -143,7 +144,7 @@ public class PackageDexOptimizer { final int sharedGid = UserHandle.getSharedAppGid(pkg.applicationInfo.uid); final String compilerFilter = getRealCompilerFilter(pkg.applicationInfo, - targetCompilerFilter, isUsedByOtherApps(pkg)); + targetCompilerFilter, isUsedByOtherApps); final boolean profileUpdated = checkForProfileUpdates && isProfileUpdated(pkg, sharedGid, compilerFilter); @@ -477,40 +478,6 @@ public class PackageDexOptimizer { mSystemReady = true; } - /** - * Returns 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 forward-locked apps and apps without - * any collected profiling data. - */ - public static boolean isUsedByOtherApps(PackageParser.Package pkg) { - if (pkg.isForwardLocked()) { - // Skip the check for forward locked packages since they don't share their code. - return false; - } - - for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) { - try { - apkPath = PackageManagerServiceUtils.realpath(new File(apkPath)); - } catch (IOException e) { - // Log an error but continue without it. - Slog.w(TAG, "Failed to get canonical path", e); - continue; - } - String useMarker = apkPath.replace('/', '@'); - final int[] currentUserIds = UserManagerService.getInstance().getUserIds(); - for (int i = 0; i < currentUserIds.length; i++) { - File profileDir = - Environment.getDataProfilesDeForeignDexDirectory(currentUserIds[i]); - File foreignUseMark = new File(profileDir, useMarker); - if (foreignUseMark.exists()) { - return true; - } - } - } - return false; - } - private String printDexoptFlags(int flags) { ArrayList flagsList = new ArrayList<>(); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2b90a715574d3..76f5a23f2be5b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -7498,11 +7498,13 @@ public class PackageManagerService extends IPackageManager.Stub { pdo.performDexOpt(depPackage, null /* sharedLibraries */, instructionSets, false /* checkProfiles */, getCompilerFilterForReason(REASON_NON_SYSTEM_LIBRARY), - getOrCreateCompilerPackageStats(depPackage)); + getOrCreateCompilerPackageStats(depPackage), + mDexManager.isUsedByOtherApps(p.packageName)); } } return pdo.performDexOpt(p, p.usesLibraryFiles, instructionSets, checkProfiles, - targetCompilerFilter, getOrCreateCompilerPackageStats(p)); + targetCompilerFilter, getOrCreateCompilerPackageStats(p), + mDexManager.isUsedByOtherApps(p.packageName)); } // Performs dexopt on the used secondary dex files belonging to the given package. @@ -15321,7 +15323,8 @@ public class PackageManagerService extends IPackageManager.Stub { mPackageDexOptimizer.performDexOpt(pkg, pkg.usesLibraryFiles, null /* instructionSets */, false /* checkProfiles */, getCompilerFilterForReason(REASON_INSTALL), - getOrCreateCompilerPackageStats(pkg)); + getOrCreateCompilerPackageStats(pkg), + mDexManager.isUsedByOtherApps(pkg.packageName)); Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); // Notify BackgroundDexOptService that the package has been changed. diff --git a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java index 45887e1c8a3fd..9feee8c97c0dd 100644 --- a/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java +++ b/services/core/java/com/android/server/pm/PackageManagerServiceUtils.java @@ -133,7 +133,8 @@ public class PackageManagerServiceUtils { sortTemp, packageManagerService); // Give priority to apps used by other apps. - applyPackageFilter((pkg) -> PackageDexOptimizer.isUsedByOtherApps(pkg), result, + applyPackageFilter((pkg) -> + packageManagerService.getDexManager().isUsedByOtherApps(pkg.packageName), result, remainingPkgs, sortTemp, packageManagerService); // Filter out packages that aren't recently used, add all remaining apps. diff --git a/services/core/java/com/android/server/pm/dex/DexManager.java b/services/core/java/com/android/server/pm/dex/DexManager.java index 00f3711c70387..01124e2ee8358 100644 --- a/services/core/java/com/android/server/pm/dex/DexManager.java +++ b/services/core/java/com/android/server/pm/dex/DexManager.java @@ -358,6 +358,23 @@ 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. */