From f8afcdc7b7b39ddc7161b1be01eebf763e68c793 Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Tue, 14 Feb 2017 17:53:13 -0800 Subject: [PATCH 1/2] Skip class path checking for secondary dex files Pass '&' marker to dex2oat classpath when compiling secondary dex files. This will skip class path checking when loading the oat files. Test: adb shell cmd package compile -m speed -f --secondary-dex com.google.android.gms oatdump --header-only --oat- file=/data/user/0/com.google.android.gms/app_chimera/m/00000006/oat/arm64/DynamiteModulesC_GmsCore_prodmnc_alldpi_release check that the class path contains the special '&' marker Bug: 32871170 (cherry picked from commit aae35767b6bca6f872c906a0fd38d7adb61217bd) Change-Id: I7f3c6743e749316ee02e8586a525ad28ae1ef765 Merged-In: If0628aeb4e3f5717604bfc4a87a4b1d438e5fa65 --- .../core/java/com/android/server/pm/PackageDexOptimizer.java | 5 ++++- .../java/com/android/server/pm/PackageManagerService.java | 5 +---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java index db712aeba0cd3..b589057ada3e6 100644 --- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java +++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java @@ -66,6 +66,9 @@ public class PackageDexOptimizer { public static final int DEX_OPT_PERFORMED = 1; public static final int DEX_OPT_FAILED = -1; + /** Special library name that skips shared libraries check during compilation. */ + public static final String SKIP_SHARED_LIBRARY_CHECK = "&"; + private final Installer mInstaller; private final Object mInstallLock; @@ -274,7 +277,7 @@ public class PackageDexOptimizer { // TODO(calin): maybe add a separate call. mInstaller.dexopt(path, info.uid, info.packageName, isa, /*dexoptNeeded*/ 0, /*oatDir*/ null, dexoptFlags, - compilerFilter, info.volumeUuid, /*sharedLibrariesPath*/ null); + compilerFilter, info.volumeUuid, SKIP_SHARED_LIBRARY_CHECK); } return DEX_OPT_PERFORMED; diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 8ab76a78ed7d7..2b90a715574d3 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -524,9 +524,6 @@ public class PackageManagerService extends IPackageManager.Stub { public static final int REASON_LAST = REASON_CORE_APP; - /** Special library name that skips shared libraries check during compilation. */ - private static final String SKIP_SHARED_LIBRARY_CHECK = "&"; - final ServiceThread mHandlerThread; final PackageHandler mHandler; @@ -2260,7 +2257,7 @@ public class PackageManagerService extends IPackageManager.Stub { DEXOPT_PUBLIC, getCompilerFilterForReason(REASON_SHARED_APK), StorageManager.UUID_PRIVATE_INTERNAL, - SKIP_SHARED_LIBRARY_CHECK); + PackageDexOptimizer.SKIP_SHARED_LIBRARY_CHECK); } } catch (FileNotFoundException e) { Slog.w(TAG, "Library not found: " + lib); From c6494490939768ab86d88abd2e562e0e591d7a8e Mon Sep 17 00:00:00 2001 From: Calin Juravle Date: Wed, 1 Mar 2017 19:55:35 -0800 Subject: [PATCH 2/2] Use DexManager logic to decide if a package is used by other apps Stop relying on the file marker recorded by the runtime. We have the same data available from the DexManager. The clean up CL to remove the handling of the file markers will follow. Test: verify that "shared packages" (e.g. gmscore) are not compiled with speed-profile. Bug: 32871170 (cherry picked from commit 07b6eabe79261267ecd7114790e96e1f6828672a) Change-Id: I2969b75fa77d38dde0073ef67aa89b1dc91237b5 Merged-In: I6cc5834ac88489e69896cd5fba9ed9968aa7f5a2 --- .../android/server/pm/OtaDexoptService.java | 3 +- .../server/pm/PackageDexOptimizer.java | 43 +++---------------- .../server/pm/PackageManagerService.java | 9 ++-- .../server/pm/PackageManagerServiceUtils.java | 3 +- .../com/android/server/pm/dex/DexManager.java | 17 ++++++++ 5 files changed, 32 insertions(+), 43 deletions(-) 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. */