diff options
author | 2025-03-21 09:41:03 -0700 | |
---|---|---|
committer | 2025-03-21 09:41:03 -0700 | |
commit | 57e243af5acfe4a20e17d4c0712cf5b48423063d (patch) | |
tree | 714c3d1a5009e9777469d09cdbd3a322abe28ea1 | |
parent | 69982a895b80ce048a17a45216c3298ef091d354 (diff) | |
parent | 9126e6fb2137d43bf6363e82b38bbd3edf428f2c (diff) |
Delete SDM and SDC files on a successful dexopt. am: 9126e6fb21
Original change: https://android-review.googlesource.com/c/platform/art/+/3545383
Change-Id: I115177d643ab57b4ac3c8af27280f1feaa6ff2e0
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | artd/artd.cc | 11 | ||||
-rw-r--r-- | artd/artd.h | 4 | ||||
-rw-r--r-- | artd/artd_test.cc | 13 | ||||
-rw-r--r-- | artd/binder/com/android/server/art/IArtd.aidl | 10 | ||||
-rw-r--r-- | libartservice/service/java/com/android/server/art/Dexopter.java | 24 | ||||
-rw-r--r-- | libartservice/service/java/com/android/server/art/PrimaryDexopter.java | 13 | ||||
-rw-r--r-- | libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java | 22 |
7 files changed, 88 insertions, 9 deletions
diff --git a/artd/artd.cc b/artd/artd.cc index 4ef1036fe1..144b783a29 100644 --- a/artd/artd.cc +++ b/artd/artd.cc @@ -1432,6 +1432,17 @@ ScopedAStatus Artd::isInDalvikCache(const std::string& in_dexFile, bool* _aidl_r return NonFatal(ART_FORMAT("Fstab entries not found for '{}'", in_dexFile)); } +ScopedAStatus Artd::deleteSdmSdcFiles(const SecureDexMetadataWithCompanionPaths& in_SdmSdcPaths, + int64_t* _aidl_return) { + RETURN_FATAL_IF_PRE_REBOOT(options_); + + std::string sdm_path = OR_RETURN_FATAL(BuildSdmPath(in_SdmSdcPaths)); + std::string sdc_path = OR_RETURN_FATAL(BuildSdcPath(in_SdmSdcPaths)); + + *_aidl_return = GetSizeAndDeleteFile(sdm_path) + GetSizeAndDeleteFile(sdc_path); + return ScopedAStatus::ok(); +} + ScopedAStatus Artd::deleteRuntimeArtifacts(const RuntimeArtifactsPath& in_runtimeArtifactsPath, int64_t* _aidl_return) { RETURN_FATAL_IF_PRE_REBOOT(options_); diff --git a/artd/artd.h b/artd/artd.h index f515e84408..d48a209b0d 100644 --- a/artd/artd.h +++ b/artd/artd.h @@ -256,6 +256,10 @@ class Artd : public aidl::com::android::server::art::BnArtd { ndk::ScopedAStatus isInDalvikCache(const std::string& in_dexFile, bool* _aidl_return) override; + ndk::ScopedAStatus deleteSdmSdcFiles( + const aidl::com::android::server::art::SecureDexMetadataWithCompanionPaths& in_sdmSdcPaths, + int64_t* _aidl_return) override; + ndk::ScopedAStatus deleteRuntimeArtifacts( const aidl::com::android::server::art::RuntimeArtifactsPath& in_runtimeArtifactsPath, int64_t* _aidl_return) override; diff --git a/artd/artd_test.cc b/artd/artd_test.cc index b7244451fa..f6eeda7e57 100644 --- a/artd/artd_test.cc +++ b/artd/artd_test.cc @@ -2484,6 +2484,19 @@ TEST_F(ArtdTest, isInDalvikCache) { EXPECT_THAT(is_in_dalvik_cache("/foo"), HasValue(true)); } +TEST_F(ArtdTest, deleteSdmSdcFiles) { + CreateFile(scratch_path_ + "/a/b.arm64.sdm", "**"); // 2 bytes. + CreateFile(scratch_path_ + "/a/oat/arm64/b.sdc", "*"); // 1 byte. + + int64_t result = -1; + ASSERT_STATUS_OK(artd_->deleteSdmSdcFiles( + {.dexPath = scratch_path_ + "/a/b.apk", .isa = "arm64", .isInDalvikCache = false}, &result)); + EXPECT_EQ(result, 2 + 1); + + EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/b.arm64.sdm")); + EXPECT_FALSE(std::filesystem::exists(scratch_path_ + "/a/oat/arm64/b.sdc")); +} + TEST_F(ArtdTest, deleteRuntimeArtifacts) { std::vector<std::string> removed_files; std::vector<std::string> kept_files; diff --git a/artd/binder/com/android/server/art/IArtd.aidl b/artd/binder/com/android/server/art/IArtd.aidl index cf4db0341b..705076d0a6 100644 --- a/artd/binder/com/android/server/art/IArtd.aidl +++ b/artd/binder/com/android/server/art/IArtd.aidl @@ -231,6 +231,16 @@ interface IArtd { boolean isInDalvikCache(@utf8InCpp String dexFile); /** + * Deletes the SDM and SDC files and returns the released space, in bytes. + * + * Not supported in Pre-reboot Dexopt mode. + * + * Throws fatal errors. Logs and ignores non-fatal errors. + */ + long deleteSdmSdcFiles( + in com.android.server.art.SecureDexMetadataWithCompanionPaths sdmSdcPaths); + + /** * Deletes runtime artifacts and returns the released space, in bytes. * * Not supported in Pre-reboot Dexopt mode. diff --git a/libartservice/service/java/com/android/server/art/Dexopter.java b/libartservice/service/java/com/android/server/art/Dexopter.java index d3bcdbb270..1c6abe6c41 100644 --- a/libartservice/service/java/com/android/server/art/Dexopter.java +++ b/libartservice/service/java/com/android/server/art/Dexopter.java @@ -201,14 +201,15 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> { long sizeBeforeBytes = 0; Dex2OatResult dex2OatResult = Dex2OatResult.notRun(); @DexoptResult.DexoptResultExtendedStatusFlags int extendedStatusFlags = 0; + DexoptTarget<DexInfoType> target = null; try { - var target = DexoptTarget.<DexInfoType>builder() - .setDexInfo(dexInfo) - .setIsa(abi.isa()) - .setIsInDalvikCache(isInDalvikCache) - .setCompilerFilter(compilerFilter) - .setDmPath(dmInfo.dmPath()) - .build(); + target = DexoptTarget.<DexInfoType>builder() + .setDexInfo(dexInfo) + .setIsa(abi.isa()) + .setIsInDalvikCache(isInDalvikCache) + .setCompilerFilter(compilerFilter) + .setDmPath(dmInfo.dmPath()) + .build(); var options = GetDexoptNeededOptions.builder() .setProfileMerged(profileMerged) .setFlags(mParams.getFlags()) @@ -318,6 +319,9 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> { AsLog.i(String.format("Dexopt result: [packageName = %s] %s", mPkgState.getPackageName(), result)); results.add(result); + + onDexoptTargetResult(target, status); + if (status != DexoptResult.DEXOPT_SKIPPED && status != DexoptResult.DEXOPT_PERFORMED) { succeeded = false; @@ -745,6 +749,12 @@ public abstract class Dexopter<DexInfoType extends DetailedDexInfo> { */ protected void onDexoptStart(@NonNull DexInfoType dexInfo) throws RemoteException {} + /** + * Called once for every dex file and every ABI when dexopt has a result. + */ + protected void onDexoptTargetResult(@NonNull DexoptTarget<DexInfoType> target, + @DexoptResult.DexoptResultStatus int status) throws RemoteException {} + @AutoValue abstract static class DexoptTarget<DexInfoType extends DetailedDexInfo> { abstract @NonNull DexInfoType dexInfo(); diff --git a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java index 70b0713d6d..94ab94e213 100644 --- a/libartservice/service/java/com/android/server/art/PrimaryDexopter.java +++ b/libartservice/service/java/com/android/server/art/PrimaryDexopter.java @@ -38,6 +38,7 @@ import com.android.modules.utils.pm.PackageStateModulesUtils; import com.android.server.art.model.ArtFlags; import com.android.server.art.model.Config; import com.android.server.art.model.DexoptParams; +import com.android.server.art.model.DexoptResult; import com.android.server.pm.pkg.AndroidPackage; import com.android.server.pm.pkg.PackageState; @@ -204,6 +205,18 @@ public class PrimaryDexopter extends Dexopter<DetailedPrimaryDexInfo> { } } + @Override + protected void onDexoptTargetResult(@NonNull DexoptTarget<DetailedPrimaryDexInfo> target, + @DexoptResult.DexoptResultStatus int status) throws RemoteException { + // An optimization to release disk space as soon as possible. The SDM and SDC files would be + // deleted by the file GC anyway if not deleted here. + if (status == DexoptResult.DEXOPT_PERFORMED && !mInjector.isPreReboot()) { + mInjector.getArtd().deleteSdmSdcFiles( + AidlUtils.buildSecureDexMetadataWithCompanionPaths( + target.dexInfo().dexPath(), target.isa(), target.isInDalvikCache())); + } + } + private boolean isSharedLibrary() { return PackageStateModulesUtils.isLoadableInOtherProcesses(mPkgState, true /* codeOnly */); } diff --git a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java index 10f9f59e91..9c3f87e92e 100644 --- a/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java +++ b/libartservice/service/javatests/com/android/server/art/PrimaryDexopterParameterizedTest.java @@ -202,6 +202,7 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase { params.mIsPreReboot = true; params.mExpectedOutputIsPreReboot = true; params.mExpectedDeletesRuntimeArtifacts = false; + params.mExpectedDeletesSdmSdcFiles = false; list.add(params); params = new Params(); @@ -385,6 +386,17 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase { PKG_NAME, "/somewhere/app/foo/split_0.apk", "arm"))); } + if (mParams.mExpectedDeletesSdmSdcFiles) { + // Only delete SDM and SDC files for successful dexopt operations, namely the first one + // and the fourth one. + doReturn(1l).when(mArtd).deleteSdmSdcFiles( + deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/base.apk", "arm64", mParams.mIsInDalvikCache))); + doReturn(1l).when(mArtd).deleteSdmSdcFiles( + deepEq(AidlUtils.buildSecureDexMetadataWithCompanionPaths( + "/somewhere/app/foo/split_0.apk", "arm", mParams.mIsInDalvikCache))); + } + assertThat(mPrimaryDexopter.dexopt()) .comparingElementsUsing(TestingUtils.<DexContainerFileDexoptResult>deepEquality()) .containsExactly( @@ -416,6 +428,10 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase { if (!mParams.mExpectedDeletesRuntimeArtifacts) { verify(mArtd, times(0)).deleteRuntimeArtifacts(any()); } + + if (!mParams.mExpectedDeletesSdmSdcFiles) { + verify(mArtd, times(0)).deleteSdmSdcFiles(any()); + } } private static class Params { @@ -451,6 +467,7 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase { public boolean mExpectedIsHiddenApiPolicyEnabled = true; public boolean mExpectedOutputIsPreReboot = false; public boolean mExpectedDeletesRuntimeArtifacts = true; + public boolean mExpectedDeletesSdmSdcFiles = true; public String toString() { return String.format("isInDalvikCache=%b," @@ -477,7 +494,8 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase { + "expectedIsDebuggable=%b," + "expectedIsHiddenApiPolicyEnabled=%b," + "expectedOutputIsPreReboot=%b," - + "expectedDeleteRuntimeArtifacts=%b", + + "expectedDeletesRuntimeArtifacts=%b," + + "expectedDeletesSdmSdcFiles=%b", mIsInDalvikCache, mHiddenApiEnforcementPolicy, mIsVmSafeMode, mIsDebuggable, mIsSystemUi, mIsLauncher, mIsUseEmbeddedDex, mIsSanboxSdkLib, mRequestedCompilerFilter, mCallbackReturnedCompilerFilter, mForce, @@ -485,7 +503,7 @@ public class PrimaryDexopterParameterizedTest extends PrimaryDexopterTestBase { mForceCompilerFilter, mAlwaysDebuggable, mExpectedCallbackInputCompilerFilter, mExpectedCompilerFilter, mExpectedDexoptTrigger, mExpectedIsDebuggable, mExpectedIsHiddenApiPolicyEnabled, mExpectedOutputIsPreReboot, - mExpectedDeletesRuntimeArtifacts); + mExpectedDeletesRuntimeArtifacts, mExpectedDeletesSdmSdcFiles); } } } |