summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2025-03-14 22:05:52 +0000
committer Jiakai Zhang <jiakaiz@google.com> 2025-03-21 16:38:33 +0000
commitd6e56a41da24eb8f6bd0b7a38289c7442421b648 (patch)
treea21fe66dcc984ffb78e4c17176a2606b194e714c
parent9126e6fb2137d43bf6363e82b38bbd3edf428f2c (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
-rw-r--r--libartservice/service/java/com/android/server/art/ArtFileManager.java7
-rw-r--r--libartservice/service/java/com/android/server/art/ArtManagerLocal.java21
-rw-r--r--libartservice/service/java/com/android/server/art/ArtShellCommand.java19
-rw-r--r--libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java19
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(