diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java index d8be2b6dcc4c4..93fc13c78b5ac 100644 --- a/core/java/android/os/Environment.java +++ b/core/java/android/os/Environment.java @@ -285,6 +285,11 @@ public class Environment { return buildPath(getDataDirectory(), "misc", "profiles", "cur", String.valueOf(userId)); } + /** {@hide} */ + public static File getReferenceProfile(String packageName) { + return buildPath(getDataDirectory(), "misc", "profiles", "ref", packageName); + } + /** {@hide} */ public static File getDataProfilesDePackageDirectory(int userId, String packageName) { return buildPath(getDataProfilesDeDirectory(userId), packageName); diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 7124135030f16..4c2ec346a3d7f 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -95,6 +95,7 @@ import static com.android.server.pm.InstructionSets.getPreferredInstructionSet; import static com.android.server.pm.InstructionSets.getPrimaryInstructionSet; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getCompilerFilterForReason; import static com.android.server.pm.PackageManagerServiceCompilerMapping.getFullCompilerFilter; +import static com.android.server.pm.PackageManagerServiceCompilerMapping.getNonProfileGuidedCompilerFilter; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_FAILURE; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS; import static com.android.server.pm.PermissionsState.PERMISSION_OPERATION_SUCCESS_GIDS_CHANGED; @@ -2793,7 +2794,7 @@ public class PackageManagerService extends IPackageManager.Stub { } } - int[] stats = performDexOpt(coreApps, false, + int[] stats = performDexOptUpgrade(coreApps, false, getCompilerFilterForReason(REASON_CORE_APP)); final int elapsedTimeSeconds = @@ -7300,7 +7301,7 @@ public class PackageManagerService extends IPackageManager.Stub { } final long startTime = System.nanoTime(); - final int[] stats = performDexOpt(pkgs, mIsPreNUpgrade /* showDialog */, + final int[] stats = performDexOptUpgrade(pkgs, mIsPreNUpgrade /* showDialog */, getCompilerFilterForReason(causeFirstBoot ? REASON_FIRST_BOOT : REASON_BOOT)); final int elapsedTimeSeconds = @@ -7319,7 +7320,7 @@ public class PackageManagerService extends IPackageManager.Stub { * which are (in order) {@code numberOfPackagesOptimized}, {@code numberOfPackagesSkipped} * and {@code numberOfPackagesFailed}. */ - private int[] performDexOpt(List pkgs, boolean showDialog, + private int[] performDexOptUpgrade(List pkgs, boolean showDialog, String compilerFilter) { int numberOfPackagesVisited = 0; @@ -7353,6 +7354,19 @@ public class PackageManagerService extends IPackageManager.Stub { } } + // If the OTA updates a system app which was previously preopted to a non-preopted state + // the app might end up being verified at runtime. That's because by default the apps + // are verify-profile but for preopted apps there's no profile. + // Do a hacky check to ensure that if we have no profiles (a reasonable indication + // that before the OTA the app was preopted) the app gets compiled with a non-profile + // filter (by default interpret-only). + // Note that at this stage unused apps are already filtered. + if (isSystemApp(pkg) && + DexFile.isProfileGuidedCompilerFilter(compilerFilter) && + !Environment.getReferenceProfile(pkg.packageName).exists()) { + compilerFilter = getNonProfileGuidedCompilerFilter(compilerFilter); + } + // checkProfiles is false to avoid merging profiles during boot which // might interfere with background compilation (b/28612421). // Unfortunately this will also means that "pm.dexopt.boot=speed-profile" will