Change app selection policy for post-OTA verification
Changes the policy for selecting packages which will be pre-verified
during post-OTA boot animation.
For Nx to Ny, an app is pre-verified if used in the foreground in the
last 7 days, or if its APK was loaded by other apps.
For M to N (or early N builds without detailed stats), an app is
pre-verified if it has any recorded use in the last 7 days.
Bug: 27902702
Bug: 27350503
Change-Id: I2b38daf017ecd0e5aa5ed596ed9351cffa03dbcb
diff --git a/services/core/java/com/android/server/pm/PackageDexOptimizer.java b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
index b3ac05c..f620274 100644
--- a/services/core/java/com/android/server/pm/PackageDexOptimizer.java
+++ b/services/core/java/com/android/server/pm/PackageDexOptimizer.java
@@ -137,21 +137,14 @@
boolean isProfileGuidedFilter = DexFile.isProfileGuidedCompilerFilter(targetCompilerFilter);
// If any part of the app is used by other apps, we cannot use profile-guided
// compilation.
- // Skip the check for forward locked packages since they don't share their code.
- if (isProfileGuidedFilter && !pkg.isForwardLocked()) {
- for (String path : paths) {
- if (isUsedByOtherApps(path)) {
- checkProfiles = false;
+ if (isProfileGuidedFilter && isUsedByOtherApps(pkg)) {
+ checkProfiles = false;
- targetCompilerFilter = getNonProfileGuidedCompilerFilter(targetCompilerFilter);
- if (DexFile.isProfileGuidedCompilerFilter(targetCompilerFilter)) {
- throw new IllegalStateException(targetCompilerFilter);
- }
- isProfileGuidedFilter = false;
-
- break;
- }
+ targetCompilerFilter = getNonProfileGuidedCompilerFilter(targetCompilerFilter);
+ if (DexFile.isProfileGuidedCompilerFilter(targetCompilerFilter)) {
+ throw new IllegalStateException(targetCompilerFilter);
}
+ isProfileGuidedFilter = false;
}
// If we're asked to take profile updates into account, check now.
@@ -281,20 +274,34 @@
mSystemReady = true;
}
- private boolean isUsedByOtherApps(String apkPath) {
- try {
- apkPath = new File(apkPath).getCanonicalPath();
- } catch (IOException e) {
- // Log an error but continue without it.
- Slog.w(TAG, "Failed to get canonical path", e);
+ /**
+ * 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;
}
- 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;
+
+ for (String apkPath : pkg.getAllCodePathsExcludingResourceOnly()) {
+ try {
+ apkPath = new File(apkPath).getCanonicalPath();
+ } catch (IOException e) {
+ // Log an error but continue without it.
+ Slog.w(TAG, "Failed to get canonical path", e);
+ }
+ 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;