diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java index 2e86df89f63eb..f95f7bc0d165d 100644 --- a/services/core/java/com/android/server/pm/AppDataHelper.java +++ b/services/core/java/com/android/server/pm/AppDataHelper.java @@ -18,7 +18,6 @@ package com.android.server.pm; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; -import static com.android.server.pm.DexOptHelper.useArtService; import static com.android.server.pm.PackageManagerService.TAG; import static com.android.server.pm.PackageManagerServiceUtils.getPackageManagerLocal; import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; @@ -245,7 +244,7 @@ public class AppDataHelper { } } - if (!useArtService()) { // ART Service handles this on demand instead. + if (!DexOptHelper.useArtService()) { // ART Service handles this on demand instead. // Prepare the application profiles only for upgrades and // first boot (so that we don't repeat the same operation at // each boot). @@ -591,7 +590,7 @@ public class AppDataHelper { Slog.wtf(TAG, "Package was null!", new Throwable()); return; } - if (useArtService()) { + if (DexOptHelper.useArtService()) { destroyAppProfilesWithArtService(pkg); } else { try { @@ -637,7 +636,7 @@ public class AppDataHelper { } private void destroyAppProfilesLeafLIF(AndroidPackage pkg) { - if (useArtService()) { + if (DexOptHelper.useArtService()) { destroyAppProfilesWithArtService(pkg); } else { try { @@ -651,6 +650,15 @@ public class AppDataHelper { } private void destroyAppProfilesWithArtService(AndroidPackage pkg) { + if (!DexOptHelper.artManagerLocalIsInitialized()) { + // This function may get called while PackageManagerService is constructed (via e.g. + // InitAppsHelper.initSystemApps), and ART Service hasn't yet been started then (it + // requires a registered PackageManagerLocal instance). We can skip clearing any stale + // app profiles in this case, because ART Service and the runtime will ignore stale or + // otherwise invalid ref and cur profiles. + return; + } + try (PackageManagerLocal.FilteredSnapshot snapshot = getPackageManagerLocal().withFilteredSnapshot()) { try { diff --git a/services/core/java/com/android/server/pm/DexOptHelper.java b/services/core/java/com/android/server/pm/DexOptHelper.java index a9d4115b4b79f..064be7c5ddc7c 100644 --- a/services/core/java/com/android/server/pm/DexOptHelper.java +++ b/services/core/java/com/android/server/pm/DexOptHelper.java @@ -99,6 +99,8 @@ import java.util.function.Predicate; public final class DexOptHelper { private static final long SEVEN_DAYS_IN_MILLISECONDS = 7 * 24 * 60 * 60 * 1000; + private static boolean sArtManagerLocalIsInitialized = false; + private final PackageManagerService mPm; // Start time for the boot dexopt in performPackageDexOptUpgradeIfNeeded when ART Service is @@ -1035,6 +1037,7 @@ public final class DexOptHelper { artManager.addDexoptDoneCallback(false /* onlyIncludeUpdates */, Runnable::run, pm.getDexOptHelper().new DexoptDoneHandler()); LocalManagerRegistry.addManager(ArtManagerLocal.class, artManager); + sArtManagerLocalIsInitialized = true; // Schedule the background job when boot is complete. This decouples us from when // JobSchedulerService is initialized. @@ -1047,6 +1050,15 @@ public final class DexOptHelper { }, new IntentFilter(Intent.ACTION_BOOT_COMPLETED)); } + /** + * Returns true if an {@link ArtManagerLocal} instance has been created. + * + * Avoid this function if at all possible, because it may hide initialization order problems. + */ + public static boolean artManagerLocalIsInitialized() { + return sArtManagerLocalIsInitialized; + } + /** * Returns the registered {@link ArtManagerLocal} instance, or else throws an unchecked error. */