diff options
author | 2025-03-14 21:10:02 +0000 | |
---|---|---|
committer | 2025-03-21 09:37:10 -0700 | |
commit | 751ffe4a74b5b7aa11f8449ed5d48e5f1a23e0fa (patch) | |
tree | 7de736c8561280b3c34fb2f5e0c7c0c29bb79d92 | |
parent | 0f7d94bd99bb554d663a4a527155eee6192780ee (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.cc | 18 | ||||
-rw-r--r-- | artd/artd.h | 2 | ||||
-rw-r--r-- | artd/artd_test.cc | 49 | ||||
-rw-r--r-- | artd/binder/com/android/server/art/IArtd.aidl | 1 | ||||
-rw-r--r-- | artd/path_utils.cc | 1 | ||||
-rw-r--r-- | libartservice/service/java/com/android/server/art/ArtManagerLocal.java | 5 | ||||
-rw-r--r-- | libartservice/service/javatests/com/android/server/art/ArtManagerLocalTest.java | 55 |
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 */); } |