summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2025-03-14 21:10:02 +0000
committer Jiakai Zhang <jiakaiz@google.com> 2025-03-21 09:37:10 -0700
commit751ffe4a74b5b7aa11f8449ed5d48e5f1a23e0fa (patch)
tree7de736c8561280b3c34fb2f5e0c7c0c29bb79d92
parent0f7d94bd99bb554d663a4a527155eee6192780ee (diff)
Update the file GC to clean up SDM files.
If the best compilation artifacts are the ones generated on device, the file GC should delete the SDM files. Bug: 377474232 Test: atest ArtServiceTests Test: atest art_standalone_artd_tests Change-Id: If2f7c31525ff9a8a03cc16fefc16a6ebcf9fad96
-rw-r--r--artd/artd.cc18
-rw-r--r--artd/artd.h2
-rw-r--r--artd/artd_test.cc49
-rw-r--r--artd/binder/com/android/server/art/IArtd.aidl1
-rw-r--r--artd/path_utils.cc1
-rw-r--r--libartservice/service/java/com/android/server/art/ArtManagerLocal.java5
-rw-r--r--libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java55
7 files changed, 124 insertions, 7 deletions
diff --git a/artd/artd.cc b/artd/artd.cc
index 68574b2ce8..59f6b88d9f 100644
--- a/artd/artd.cc
+++ b/artd/artd.cc
@@ -1336,12 +1336,14 @@ ScopedAStatus Artd::createCancellationSignal(
return ScopedAStatus::ok();
}
-ScopedAStatus Artd::cleanup(const std::vector<ProfilePath>& in_profilesToKeep,
- const std::vector<ArtifactsPath>& in_artifactsToKeep,
- const std::vector<VdexPath>& in_vdexFilesToKeep,
- const std::vector<RuntimeArtifactsPath>& in_runtimeArtifactsToKeep,
- bool in_keepPreRebootStagedFiles,
- int64_t* _aidl_return) {
+ScopedAStatus Artd::cleanup(
+ const std::vector<ProfilePath>& in_profilesToKeep,
+ const std::vector<ArtifactsPath>& in_artifactsToKeep,
+ const std::vector<VdexPath>& in_vdexFilesToKeep,
+ const std::vector<SecureDexMetadataWithCompanionPaths>& in_SdmSdcFilesToKeep,
+ const std::vector<RuntimeArtifactsPath>& in_runtimeArtifactsToKeep,
+ bool in_keepPreRebootStagedFiles,
+ int64_t* _aidl_return) {
RETURN_FATAL_IF_PRE_REBOOT(options_);
std::unordered_set<std::string> files_to_keep;
for (const ProfilePath& profile : in_profilesToKeep) {
@@ -1359,6 +1361,10 @@ ScopedAStatus Artd::cleanup(const std::vector<ProfilePath>& in_profilesToKeep,
RETURN_FATAL_IF_ARG_IS_PRE_REBOOT(vdex, "vdexFilesToKeep");
files_to_keep.insert(OR_RETURN_FATAL(BuildVdexPath(vdex)));
}
+ for (const SecureDexMetadataWithCompanionPaths& sdm_sdc : in_SdmSdcFilesToKeep) {
+ files_to_keep.insert(OR_RETURN_FATAL(BuildSdmPath(sdm_sdc)));
+ files_to_keep.insert(OR_RETURN_FATAL(BuildSdcPath(sdm_sdc)));
+ }
std::string android_data = OR_RETURN_NON_FATAL(GetAndroidDataOrError());
std::string android_expand = OR_RETURN_NON_FATAL(GetAndroidExpandOrError());
for (const RuntimeArtifactsPath& runtime_image_path : in_runtimeArtifactsToKeep) {
diff --git a/artd/artd.h b/artd/artd.h
index affb180b08..f515e84408 100644
--- a/artd/artd.h
+++ b/artd/artd.h
@@ -245,6 +245,8 @@ class Artd : public aidl::com::android::server::art::BnArtd {
const std::vector<aidl::com::android::server::art::ProfilePath>& in_profilesToKeep,
const std::vector<aidl::com::android::server::art::ArtifactsPath>& in_artifactsToKeep,
const std::vector<aidl::com::android::server::art::VdexPath>& in_vdexFilesToKeep,
+ const std::vector<aidl::com::android::server::art::SecureDexMetadataWithCompanionPaths>&
+ in_SdmSdcFilesToKeep,
const std::vector<aidl::com::android::server::art::RuntimeArtifactsPath>&
in_runtimeArtifactsToKeep,
bool in_keepPreRebootStagedFiles,
diff --git a/artd/artd_test.cc b/artd/artd_test.cc
index d6e383daf3..b7244451fa 100644
--- a/artd/artd_test.cc
+++ b/artd/artd_test.cc
@@ -2230,15 +2230,23 @@ TEST_F(ArtdTest, mergeProfilesWithOptionsDumpClassesAndMethods) {
CheckContent(output_profile.profilePath.tmpPath, "dump");
}
+static std::string EncodeLocationForDalvikCache(const std::string& location) {
+ std::string encoded = location.substr(/*pos=*/1); // Remove the leading '/';
+ std::replace(encoded.begin(), encoded.end(), '/', '@');
+ return encoded;
+}
+
class ArtdCleanupTest : public ArtdTest {
protected:
void SetUpForCleanup() {
// Unmanaged files.
CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/1.odex");
+ CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/1.arm64.sdm");
CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/1.odex");
CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/1.txt");
CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.txt");
CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.tmp");
+ CreateGcKeptFile(android_data_ + "/user_de/0/com.android.foo/oat/arm64/1.sdc");
// Files to keep.
CreateGcKeptFile(android_data_ + "/misc/profiles/cur/1/com.android.foo/primary.prof");
@@ -2266,6 +2274,15 @@ class ArtdCleanupTest : public ArtdTest {
"/123456-7890/user/1/com.android.foo/cache/oat_primary/arm64/base.art");
CreateGcKeptFile(android_data_ +
"/user/0/com.android.foo/cache/not_oat_dir/oat_primary/arm64/base.art");
+ CreateGcKeptFile(android_data_ +
+ "/app/~~fadsfgadg==/com.android.baz-fadsfgadg==/base.arm64.sdm");
+ CreateGcKeptFile(android_data_ +
+ "/app/~~fadsfgadg==/com.android.baz-fadsfgadg==/oat/arm64/base.sdc");
+ CreateGcKeptFile(android_data_ +
+ "/app/~~jhrwafasr==/com.android.qux-bredcweff==/base.arm64.sdm");
+ CreateGcKeptFile(android_data_ + "/dalvik-cache/arm64/" +
+ EncodeLocationForDalvikCache(android_data_) +
+ "@app@~~jhrwafasr==@com.android.qux-bredcweff==@base.apk@classes.sdc");
// Files to remove.
CreateGcRemovedFile(android_data_ + "/misc/profiles/ref/com.android.foo/primary.prof");
@@ -2307,6 +2324,26 @@ class ArtdCleanupTest : public ArtdTest {
"/user/0/com.android.foo/cache/oat_primary/arm64/different_dex.art");
CreateGcRemovedFile(android_data_ +
"/user/0/com.android.foo/cache/oat_primary/different_isa/base.art");
+ CreateGcRemovedFile(android_data_ +
+ "/app/~~fadsfgadg==/com.android.baz-fadsfgadg==/different_dex.arm64.sdm");
+ CreateGcRemovedFile(
+ android_data_ +
+ "/app/~~fadsfgadg==/com.android.baz-fadsfgadg==/oat/arm64/different_dex.sdc");
+ CreateGcRemovedFile(android_data_ +
+ "/app/~~fadsfgadg==/com.android.baz-fadsfgadg==/base.different_isa.sdm");
+ CreateGcRemovedFile(
+ android_data_ +
+ "/app/~~fadsfgadg==/com.android.baz-fadsfgadg==/oat/different_isa/base.sdc");
+ CreateGcRemovedFile(android_data_ +
+ "/app/~~jhrwafasr==/com.android.qux-bredcweff==/different_dex.arm64.sdm");
+ CreateGcRemovedFile(
+ android_data_ + "/dalvik-cache/arm64/" + EncodeLocationForDalvikCache(android_data_) +
+ "@app@~~jhrwafasr==@com.android.qux-bredcweff==@different_dex.apk@classes.sdc");
+ CreateGcRemovedFile(android_data_ +
+ "/app/~~jhrwafasr==/com.android.qux-bredcweff==/base.different_isa.sdm");
+ CreateGcRemovedFile(android_data_ + "/dalvik-cache/different_isa/" +
+ EncodeLocationForDalvikCache(android_data_) +
+ "@app@~~jhrwafasr==@com.android.qux-bredcweff==@base.apk@classes.sdc");
}
void CreateGcRemovedFile(const std::string& path) {
@@ -2347,6 +2384,18 @@ class ArtdCleanupTest : public ArtdTest {
.isInDalvikCache = false}},
},
{
+ SecureDexMetadataWithCompanionPaths{
+ .dexPath =
+ android_data_ + "/app/~~fadsfgadg==/com.android.baz-fadsfgadg==/base.apk",
+ .isa = "arm64",
+ .isInDalvikCache = false},
+ SecureDexMetadataWithCompanionPaths{
+ .dexPath =
+ android_data_ + "/app/~~jhrwafasr==/com.android.qux-bredcweff==/base.apk",
+ .isa = "arm64",
+ .isInDalvikCache = true},
+ },
+ {
RuntimeArtifactsPath{
.packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "arm64"},
},
diff --git a/artd/binder/com/android/server/art/IArtd.aidl b/artd/binder/com/android/server/art/IArtd.aidl
index 8b6ba8b94c..cf4db0341b 100644
--- a/artd/binder/com/android/server/art/IArtd.aidl
+++ b/artd/binder/com/android/server/art/IArtd.aidl
@@ -209,6 +209,7 @@ interface IArtd {
long cleanup(in List<com.android.server.art.ProfilePath> profilesToKeep,
in List<com.android.server.art.ArtifactsPath> artifactsToKeep,
in List<com.android.server.art.VdexPath> vdexFilesToKeep,
+ in List<com.android.server.art.SecureDexMetadataWithCompanionPaths> SdmSdcFilesToKeep,
in List<com.android.server.art.RuntimeArtifactsPath> runtimeArtifactsToKeep,
boolean keepPreRebootStagedFiles);
diff --git a/artd/path_utils.cc b/artd/path_utils.cc
index bb752d00c8..0f269e2dbb 100644
--- a/artd/path_utils.cc
+++ b/artd/path_utils.cc
@@ -108,6 +108,7 @@ std::vector<std::string> ListManagedFiles(const std::string& android_data,
for (const std::string& data_root : {android_data, android_expand + "/*"}) {
// Artifacts for primary dex files.
patterns.push_back(data_root + "/app/*/*/oat/**");
+ patterns.push_back(data_root + "/app/*/*/*.sdm");
for (const char* user_dir : {"/user", "/user_de"}) {
std::string data_dir = data_root + user_dir + "/*/*";
diff --git a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
index acd6063f11..e74a49c337 100644
--- a/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
+++ b/libartservice/service/java/com/android/server/art/ArtManagerLocal.java
@@ -1123,6 +1123,7 @@ public final class ArtManagerLocal {
// - The dexopt artifacts, if they are up-to-date and the app is not hibernating.
// - Only the VDEX part of the dexopt artifacts, if the dexopt artifacts are outdated
// but the VDEX part is still usable and the app is not hibernating.
+ // - The SDM and SDC files, if they are up-to-date and the app is not hibernating.
// - The runtime artifacts, if dexopt artifacts are fully or partially usable and the
// usable parts don't contain AOT-compiled code. (This logic must be aligned with the
// one that determines when runtime images can be loaded in
@@ -1130,6 +1131,7 @@ public final class ArtManagerLocal {
List<ProfilePath> profilesToKeep = new ArrayList<>();
List<ArtifactsPath> artifactsToKeep = new ArrayList<>();
List<VdexPath> vdexFilesToKeep = new ArrayList<>();
+ List<SecureDexMetadataWithCompanionPaths> sdmSdcFilesToKeep = new ArrayList<>();
List<RuntimeArtifactsPath> runtimeArtifactsToKeep = new ArrayList<>();
for (PackageState pkgState : snapshot.getPackageStates().values()) {
@@ -1150,11 +1152,12 @@ public final class ArtManagerLocal {
mInjector.getArtFileManager().getUsableArtifacts(pkgState, pkg);
artifactsToKeep.addAll(artifactLists.artifacts());
vdexFilesToKeep.addAll(artifactLists.vdexFiles());
+ sdmSdcFilesToKeep.addAll(artifactLists.sdmFiles());
runtimeArtifactsToKeep.addAll(artifactLists.runtimeArtifacts());
}
}
return mInjector.getArtd().cleanup(profilesToKeep, artifactsToKeep, vdexFilesToKeep,
- runtimeArtifactsToKeep,
+ sdmSdcFilesToKeep, runtimeArtifactsToKeep,
SdkLevel.isAtLeastV() && mInjector.getPreRebootDexoptJob().hasStarted());
} catch (RemoteException e) {
Utils.logArtdException(e);
diff --git a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
index b17475480e..567de0acdc 100644
--- a/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
+++ b/libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java
@@ -1268,6 +1268,7 @@ public class ArtManagerLocalTest {
"arm64", true /* isInDalvikCache */)),
inAnyOrderDeepEquals(VdexPath.artifactsPath(AidlUtils.buildArtifactsPathAsInput(
"/somewhere/app/foo/split_0.apk", "arm", false /* isInDalvikCache */))),
+ inAnyOrderDeepEquals() /* sdmSdcFilesToKeep */,
inAnyOrderDeepEquals(AidlUtils.buildRuntimeArtifactsPath(
PKG_NAME_1, "/somewhere/app/foo/split_0.apk", "arm64"),
AidlUtils.buildRuntimeArtifactsPath(
@@ -1276,6 +1277,60 @@ public class ArtManagerLocalTest {
}
@Test
+ public void testCleanupDmAndSdm() throws Exception {
+ when(mPreRebootDexoptJob.hasStarted()).thenReturn(false);
+
+ // It should keep the SDM file, but not runtime images.
+ doReturn(createGetDexoptStatusResult(
+ "speed-profile", "cloud", "location", ArtifactsLocation.SDM_NEXT_TO_DEX))
+ .when(mArtd)
+ .getDexoptStatus(eq("/somewhere/app/foo/base.apk"), eq("arm64"), any());
+
+ // It should keep the SDM file, but not runtime images.
+ doReturn(createGetDexoptStatusResult(
+ "speed-profile", "cloud", "location", ArtifactsLocation.SDM_DALVIK_CACHE))
+ .when(mArtd)
+ .getDexoptStatus(eq("/somewhere/app/foo/base.apk"), eq("arm"), any());
+
+ // It should keep the SDM file and runtime images.
+ doReturn(createGetDexoptStatusResult(
+ "verify", "cloud", "location", ArtifactsLocation.SDM_NEXT_TO_DEX))
+ .when(mArtd)
+ .getDexoptStatus(eq("/somewhere/app/foo/split_0.apk"), eq("arm64"), any());
+
+ // It should only keep runtime images.
+ doReturn(createGetDexoptStatusResult("verify", "vdex", "location", ArtifactsLocation.DM))
+ .when(mArtd)
+ .getDexoptStatus(eq("/somewhere/app/foo/split_0.apk"), eq("arm"), any());
+
+ // This file is uninteresting in this test.
+ doReturn(createGetDexoptStatusResult(
+ "run-from-apk", "unknown", "unknown", ArtifactsLocation.NONE_OR_ERROR))
+ .when(mArtd)
+ .getDexoptStatus(eq("/data/user/0/foo/1.apk"), eq("arm64"), any());
+
+ when(mSnapshot.getPackageStates()).thenReturn(Map.of(PKG_NAME_1, mPkgState1));
+ mArtManagerLocal.cleanup(mSnapshot);
+
+ verify(mArtd).cleanup(any() /* profilesToKeep */,
+ inAnyOrderDeepEquals() /* artifactsToKeep */,
+ inAnyOrderDeepEquals() /* vdexFilesToKeep */,
+ inAnyOrderDeepEquals(AidlUtils.buildSecureDexMetadataWithCompanionPaths(
+ "/somewhere/app/foo/base.apk", "arm64",
+ false /* isInDalvikCache */),
+ AidlUtils.buildSecureDexMetadataWithCompanionPaths(
+ "/somewhere/app/foo/base.apk", "arm", true /* isInDalvikCache */),
+ AidlUtils.buildSecureDexMetadataWithCompanionPaths(
+ "/somewhere/app/foo/split_0.apk", "arm64",
+ false /* isInDalvikCache */)),
+ inAnyOrderDeepEquals(AidlUtils.buildRuntimeArtifactsPath(
+ PKG_NAME_1, "/somewhere/app/foo/split_0.apk", "arm64"),
+ AidlUtils.buildRuntimeArtifactsPath(
+ PKG_NAME_1, "/somewhere/app/foo/split_0.apk", "arm")),
+ eq(false) /* keepPreRebootStagedFiles */);
+ }
+
+ @Test
public void testGetArtManagedFileStatsSystem() throws Exception {
testGetArtManagedFileStats(true /* isSystemOrRootOrShell */);
}