diff options
author | 2025-03-14 22:05:52 +0000 | |
---|---|---|
committer | 2025-03-21 16:38:33 +0000 | |
commit | d6e56a41da24eb8f6bd0b7a38289c7442421b648 (patch) | |
tree | a21fe66dcc984ffb78e4c17176a2606b194e714c /libartservice | |
parent | 9126e6fb2137d43bf6363e82b38bbd3edf428f2c (diff) |
Delete SDM files on "pm delete-dexopt" and "pm compile --reset".
If SDM files are installed and then cleaned up after becoming obsolete,
"pm delete-dexopt" will put the app in a state where there is not dexopt
artifacts to use. Therefore, for consistency in terms of app
performance, we should delete SDM files on "pm delete-dexopt" even if
they are not obsolete.
"pm compile --reset" has a similar situation. If SDM files are installed
and then cleaned up after becoming obsolete, "pm compile --reset" will
put the app in a state where its dexopt artifacts are generated on
device with the cloud profile (ideally, the behavior should be restoring
the SDM files, but that's impossible). Therefore, for consistency in
terms of app performance (assuming locally generated artifacts and cloud
artifacts have different performance), we should delete SDM files and
regenerate dexopt artifacts on device on "pm compile --reset".
Bug: 377474232
Test: atest ArtServiceTests
Change-Id: If1934b6c7da19ad346f4962241bbdab13fa12ce6
Diffstat (limited to 'libartservice')
4 files changed, 50 insertions, 16 deletions
diff --git a/libartservice/service/java/com/android/server/art/ArtFileManager.java b/libartservice/service/java/com/android/server/art/ArtFileManager.java index 8e382aa1d8..534952a304 100644 --- a/libartservice/service/java/com/android/server/art/ArtFileManager.java +++ b/libartservice/service/java/com/android/server/art/ArtFileManager.java @@ -101,6 +101,7 @@ public class ArtFileManager { public WritableArtifactLists getWritableArtifacts(@NonNull PackageState pkgState, @NonNull AndroidPackage pkg, @NonNull Options options) throws RemoteException { List<ArtifactsPath> artifacts = new ArrayList<>(); + List<SecureDexMetadataWithCompanionPaths> sdmFiles = new ArrayList<>(); List<RuntimeArtifactsPath> runtimeArtifacts = new ArrayList<>(); if (options.forPrimaryDex()) { @@ -109,6 +110,9 @@ public class ArtFileManager { for (Abi abi : Utils.getAllAbis(pkgState)) { artifacts.add(AidlUtils.buildArtifactsPathAsInput( dexInfo.dexPath(), abi.isa(), isInDalvikCache)); + // SDM files are only for primary dex files. + sdmFiles.add(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + dexInfo.dexPath(), abi.isa(), isInDalvikCache)); // Runtime images are only generated for primary dex files. runtimeArtifacts.add(AidlUtils.buildRuntimeArtifactsPath( pkgState.getPackageName(), dexInfo.dexPath(), abi.isa())); @@ -125,7 +129,7 @@ public class ArtFileManager { } } - return new WritableArtifactLists(artifacts, runtimeArtifacts); + return new WritableArtifactLists(artifacts, sdmFiles, runtimeArtifacts); } /** Returns artifacts that are usable, regardless of whether they are writable. */ @@ -243,6 +247,7 @@ public class ArtFileManager { } public record WritableArtifactLists(@NonNull List<ArtifactsPath> artifacts, + @NonNull List<SecureDexMetadataWithCompanionPaths> sdmFiles, @NonNull List<RuntimeArtifactsPath> runtimeArtifacts) {} public record UsableArtifactLists(@NonNull List<ArtifactsPath> artifacts, diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java index e74a49c337..993cb2c558 100644 --- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java +++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java @@ -202,8 +202,8 @@ public final class ArtManagerLocal { } /** - * Deletes dexopt artifacts of a package, including the artifacts for primary dex files and the - * ones for secondary dex files. This includes VDEX, ODEX, and ART files. + * Deletes dexopt artifacts (including cloud dexopt artifacts) of a package, for primary dex + * files and for secondary dex files. This includes VDEX, ODEX, ART, SDM, and SDC files. * * Also deletes runtime artifacts of the package, though they are not dexopt artifacts. * @@ -232,6 +232,9 @@ public final class ArtManagerLocal { for (RuntimeArtifactsPath runtimeArtifacts : list.runtimeArtifacts()) { freedBytes += mInjector.getArtd().deleteRuntimeArtifacts(runtimeArtifacts); } + for (SecureDexMetadataWithCompanionPaths sdmSdcFiles : list.sdmFiles()) { + freedBytes += mInjector.getArtd().deleteSdmSdcFiles(sdmSdcFiles); + } return DeleteResult.create(freedBytes); } catch (RemoteException e) { Utils.logArtdException(e); @@ -390,13 +393,17 @@ public final class ArtManagerLocal { } /** - * Resets the dexopt state of the package as if the package is newly installed. + * Resets the dexopt state of the package as if the package is newly installed without cloud + * dexopt artifacts (SDM files). * - * More specifically, it clears reference profiles, current profiles, any code compiled from - * those local profiles, and runtime artifacts. If there is an external profile (e.g., a cloud - * profile), the code compiled from that profile will be kept. + * More specifically, + * - It clears current profiles, reference profiles, and all dexopt artifacts (including cloud + * dexopt artifacts). + * - If there is an external profile (e.g., a cloud profile), the reference profile will be + * re-created from that profile, and dexopt artifacts will be regenerated for that profile. * - * For secondary dex files, it also clears all dexopt artifacts. + * For secondary dex files, it clears all profiles and dexopt artifacts without regeneration + * because secondary dex files are supposed to be unknown at install time. * * @hide */ diff --git a/libartservice/service/java/com/android/server/art/ArtShellCommand.java b/libartservice/service/java/com/android/server/art/ArtShellCommand.java index f83f5cf083..a3b2fba42a 100644 --- a/libartservice/service/java/com/android/server/art/ArtShellCommand.java +++ b/libartservice/service/java/com/android/server/art/ArtShellCommand.java @@ -967,13 +967,16 @@ public final class ArtShellCommand extends BasicShellCommandHandler { pw.println(" -f Force dexopt, also when the compiler filter being applied is not"); pw.println(" better than that of the current dexopt artifacts for a package."); pw.println(" --reset Reset the dexopt state of the package as if the package is newly"); - pw.println(" installed."); - pw.println(" More specifically, it clears current profiles, reference profiles"); - pw.println(" from local profiles, and any code compiled from those local profiles."); - pw.println(" If there is an external profile (e.g., a cloud profile), the reference"); - pw.println(" profile from that profile and the code compiled from that profile will"); - pw.println(" be kept."); - pw.println(" For secondary dex files, it also clears all dexopt artifacts."); + pw.println(" installed without cloud dexopt artifacts (SDM files)."); + pw.println(" More specifically,"); + pw.println(" - It clears current profiles, reference profiles, and all dexopt"); + pw.println(" artifacts (including cloud dexopt artifacts)."); + pw.println(" - If there is an external profile (e.g., a cloud profile), the"); + pw.println(" reference profile will be re-created from that profile, and dexopt"); + pw.println(" artifacts will be regenerated for that profile."); + pw.println(" For secondary dex files, it clears all profiles and dexopt artifacts"); + pw.println(" without regeneration because secondary dex files are supposed to be"); + pw.println(" unknown at install time."); pw.println(" When this flag is set, all the other flags are ignored."); pw.println(" -v Verbose mode. This mode prints detailed results."); pw.println(" --force-merge-profile Force merge profiles even if the difference between"); @@ -1000,7 +1003,7 @@ public final class ArtShellCommand extends BasicShellCommandHandler { pw.println(); pw.println("delete-dexopt PACKAGE_NAME"); pw.println(" Delete the dexopt artifacts of both primary dex files and secondary dex"); - pw.println(" files of a package."); + pw.println(" files of a package, including cloud dexopt artifacts (SDM files)."); pw.println(); pw.println("bg-dexopt-job [--cancel | --disable | --enable]"); pw.println(" Control the background dexopt job."); diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java index 567de0acdc..754208a05f 100644 --- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java +++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java @@ -333,6 +333,15 @@ public class ArtManagerLocalTest { verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPathAsInput( "/data/user/0/foo/not_found.apk", "arm64", false /* isInDalvikCache */))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/base.apk", "arm64", mIsInDalvikCache))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/base.apk", "arm", mIsInDalvikCache))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/split_0.apk", "arm64", mIsInDalvikCache))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/split_0.apk", "arm", mIsInDalvikCache))); + verify(mArtd).deleteRuntimeArtifacts(deepEq(AidlUtils.buildRuntimeArtifactsPath( PKG_NAME_1, "/somewhere/app/foo/base.apk", "arm64"))); verify(mArtd).deleteRuntimeArtifacts(deepEq(AidlUtils.buildRuntimeArtifactsPath( @@ -344,6 +353,7 @@ public class ArtManagerLocalTest { // Verify that there are no more calls than the ones above. verify(mArtd, times(6)).deleteArtifacts(any()); + verify(mArtd, times(4)).deleteSdmSdcFiles(any()); verify(mArtd, times(4)).deleteRuntimeArtifacts(any()); } @@ -572,6 +582,15 @@ public class ArtManagerLocalTest { verify(mArtd).deleteArtifacts(deepEq(AidlUtils.buildArtifactsPathAsInput( "/somewhere/app/foo/split_0.apk", "arm", mIsInDalvikCache))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/base.apk", "arm64", mIsInDalvikCache))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/base.apk", "arm", mIsInDalvikCache))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/split_0.apk", "arm64", mIsInDalvikCache))); + verify(mArtd).deleteSdmSdcFiles(deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/split_0.apk", "arm", mIsInDalvikCache))); + verify(mArtd).deleteRuntimeArtifacts(deepEq(AidlUtils.buildRuntimeArtifactsPath( PKG_NAME_1, "/somewhere/app/foo/base.apk", "arm64"))); verify(mArtd).deleteRuntimeArtifacts(deepEq(AidlUtils.buildRuntimeArtifactsPath( |