diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java index c27ec66b5db3e..63b56e0f92d4d 100644 --- a/services/core/java/android/content/pm/PackageManagerInternal.java +++ b/services/core/java/android/content/pm/PackageManagerInternal.java @@ -479,6 +479,12 @@ public abstract class PackageManagerInternal { */ public abstract void pruneInstantApps(); + /** + * Prunes the cache of the APKs in the given APEXes. + * @param apexPackages The list of APEX packages that may contain APK-in-APEX. + */ + public abstract void pruneCachedApksInApex(@NonNull List apexPackages); + /** * @return The SetupWizard package name. */ diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 9f543b4142549..5447bcb246e04 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -351,6 +351,7 @@ import com.android.server.pm.dex.DexManager; import com.android.server.pm.dex.DexoptOptions; import com.android.server.pm.dex.PackageDexUsage; import com.android.server.pm.dex.ViewCompiler; +import com.android.server.pm.parsing.PackageCacher; import com.android.server.pm.parsing.PackageInfoUtils; import com.android.server.pm.parsing.PackageParser2; import com.android.server.pm.parsing.library.PackageBackwardCompatibility; @@ -24231,6 +24232,25 @@ public class PackageManagerService extends IPackageManager.Stub mInstantAppRegistry.pruneInstantApps(); } + @Override + public void pruneCachedApksInApex(@NonNull List apexPackages) { + if (mCacheDir == null) { + return; + } + + final PackageCacher cacher = new PackageCacher(mCacheDir); + synchronized (mLock) { + for (int i = 0, size = apexPackages.size(); i < size; i++) { + final List apkNames = + mApexManager.getApksInApex(apexPackages.get(i).packageName); + for (int j = 0, apksInApex = apkNames.size(); j < apksInApex; j++) { + final AndroidPackage pkg = getPackage(apkNames.get(j)); + cacher.cleanCachedResult(new File(pkg.getCodePath())); + } + } + } + } + @Override public String getSetupWizardPackageName() { return mSetupWizardPackage; diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java index d1d98775c4b6e..1c1e64d70bbdc 100644 --- a/services/core/java/com/android/server/pm/StagingManager.java +++ b/services/core/java/com/android/server/pm/StagingManager.java @@ -1226,8 +1226,9 @@ public class StagingManager { // APEX checks. For single-package sessions, check if they contain an APEX. For // multi-package sessions, find all the child sessions that contain an APEX. if (hasApex) { + final List apexPackages; try { - final List apexPackages = submitSessionToApexService(session); + apexPackages = submitSessionToApexService(session); for (int i = 0, size = apexPackages.size(); i < size; i++) { validateApexSignature(apexPackages.get(i)); } @@ -1235,6 +1236,10 @@ public class StagingManager { session.setStagedSessionFailed(e.error, e.getMessage()); return; } + + final PackageManagerInternal packageManagerInternal = + LocalServices.getService(PackageManagerInternal.class); + packageManagerInternal.pruneCachedApksInApex(apexPackages); } notifyPreRebootVerification_Apex_Complete(session.sessionId); diff --git a/services/core/java/com/android/server/pm/parsing/PackageCacher.java b/services/core/java/com/android/server/pm/parsing/PackageCacher.java index e5e1b0b209556..99c6dd1f03128 100644 --- a/services/core/java/com/android/server/pm/parsing/PackageCacher.java +++ b/services/core/java/com/android/server/pm/parsing/PackageCacher.java @@ -18,6 +18,7 @@ package com.android.server.pm.parsing; import android.annotation.NonNull; import android.content.pm.PackageParserCacheHelper; +import android.os.FileUtils; import android.os.Parcel; import android.system.ErrnoException; import android.system.Os; @@ -197,4 +198,18 @@ public class PackageCacher { Slog.w(TAG, "Error saving package cache.", e); } } + + /** + * Delete the cache files for the given {@code packageFile}. + */ + public void cleanCachedResult(@NonNull File packageFile) { + final String packageName = packageFile.getName(); + final File[] files = FileUtils.listFilesOrEmpty(mCacheDir, + (dir, name) -> name.startsWith(packageName)); + for (File file : files) { + if (!file.delete()) { + Slog.e(TAG, "Unable to clean cache file: " + file); + } + } + } }