diff options
author | 2023-09-07 19:05:10 +0100 | |
---|---|---|
committer | 2023-10-10 19:01:06 +0000 | |
commit | 356505949dc46612f64b13424d2496f4e9ef9ace (patch) | |
tree | 5bdc185e46dd1397ca09199965f41ac8c82c03c4 /artd | |
parent | 6ab6ca740ec15717d8ebbbfcdea72f9f7a1c0731 (diff) |
Add an artd method to delete runtime image files.
Bug: 299442352
Test: atest art_standalone_artd_tests
Change-Id: Ibc31bd5c0ad2d5d3ea1cfa427f76e1dc6fc93b11
Merged-In: Ibc31bd5c0ad2d5d3ea1cfa427f76e1dc6fc93b11
Diffstat (limited to 'artd')
-rw-r--r-- | artd/artd.cc | 11 | ||||
-rw-r--r-- | artd/artd.h | 4 | ||||
-rw-r--r-- | artd/artd_test.cc | 103 | ||||
-rw-r--r-- | artd/binder/com/android/server/art/IArtd.aidl | 13 | ||||
-rw-r--r-- | artd/binder/com/android/server/art/RuntimeArtifactsPath.aidl | 32 | ||||
-rw-r--r-- | artd/path_utils.cc | 31 | ||||
-rw-r--r-- | artd/path_utils.h | 6 |
7 files changed, 199 insertions, 1 deletions
diff --git a/artd/artd.cc b/artd/artd.cc index a4e0f324fc..89156c28f8 100644 --- a/artd/artd.cc +++ b/artd/artd.cc @@ -96,6 +96,7 @@ using ::aidl::com::android::server::art::OutputArtifacts; using ::aidl::com::android::server::art::OutputProfile; using ::aidl::com::android::server::art::PriorityClass; using ::aidl::com::android::server::art::ProfilePath; +using ::aidl::com::android::server::art::RuntimeArtifactsPath; using ::aidl::com::android::server::art::VdexPath; using ::android::base::Dirname; using ::android::base::Error; @@ -1154,6 +1155,16 @@ ScopedAStatus Artd::isInDalvikCache(const std::string& in_dexFile, bool* _aidl_r return NonFatal(ART_FORMAT("Fstab entries not found for '{}'", in_dexFile)); } +ScopedAStatus Artd::deleteRuntimeArtifacts(const RuntimeArtifactsPath& in_runtimeArtifactsPath, + int64_t* _aidl_return) { + OR_RETURN_FATAL(ValidateRuntimeArtifactsPath(in_runtimeArtifactsPath)); + for (const std::string& file : + OR_RETURN_NON_FATAL(ListRuntimeArtifactsFiles(in_runtimeArtifactsPath))) { + *_aidl_return += GetSizeAndDeleteFile(file); + } + return ScopedAStatus::ok(); +} + ScopedAStatus Artd::validateDexPath(const std::string& in_dexPath, std::optional<std::string>* _aidl_return) { if (Result<void> result = ValidateDexPath(in_dexPath); !result.ok()) { diff --git a/artd/artd.h b/artd/artd.h index 774f11a1d1..c6bce721a7 100644 --- a/artd/artd.h +++ b/artd/artd.h @@ -166,6 +166,10 @@ class Artd : public aidl::com::android::server::art::BnArtd { ndk::ScopedAStatus isInDalvikCache(const std::string& in_dexFile, bool* _aidl_return) override; + ndk::ScopedAStatus deleteRuntimeArtifacts( + const aidl::com::android::server::art::RuntimeArtifactsPath& in_runtimeArtifactsPath, + int64_t* _aidl_return) override; + ndk::ScopedAStatus validateDexPath(const std::string& in_dexPath, std::optional<std::string>* _aidl_return) override; diff --git a/artd/artd_test.cc b/artd/artd_test.cc index ae18b1af91..41c175543c 100644 --- a/artd/artd_test.cc +++ b/artd/artd_test.cc @@ -81,6 +81,7 @@ using ::aidl::com::android::server::art::OutputArtifacts; using ::aidl::com::android::server::art::OutputProfile; using ::aidl::com::android::server::art::PriorityClass; using ::aidl::com::android::server::art::ProfilePath; +using ::aidl::com::android::server::art::RuntimeArtifactsPath; using ::aidl::com::android::server::art::VdexPath; using ::android::base::Append; using ::android::base::Error; @@ -2118,6 +2119,108 @@ TEST_F(ArtdTest, isInDalvikCache) { EXPECT_THAT(is_in_dalvik_cache("/foo"), HasValue(true)); } +TEST_F(ArtdTest, deleteRuntimeArtifacts) { + // TODO(b/289037540): Fix this. + if (getuid() != kRootUid) { + GTEST_SKIP() << "This test requires root access"; + } + + std::vector<std::string> removed_files; + std::vector<std::string> kept_files; + + auto CreateRemovedFile = [&](const std::string& path) { + CreateFile(path); + removed_files.push_back(path); + }; + + auto CreateKeptFile = [&](const std::string& path) { + CreateFile(path); + kept_files.push_back(path); + }; + + CreateKeptFile(android_data_ + + "/user/0/com.android.different_package/cache/oat_primary/arm64/base.art"); + CreateKeptFile(android_data_ + + "/user/0/com.android.foo/cache/oat_primary/arm64/different_dex.art"); + CreateKeptFile(android_data_ + + "/user/0/com.android.foo/cache/oat_primary/different_isa/base.art"); + CreateKeptFile(android_data_ + + "/user/0/com.android.foo/cache/not_oat_dir/oat_primary/arm64/base.art"); + + CreateRemovedFile(android_data_ + "/user_de/0/com.android.foo/cache/oat_primary/arm64/base.art"); + CreateRemovedFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/base.art"); + CreateRemovedFile(android_data_ + "/user/1/com.android.foo/cache/oat_primary/arm64/base.art"); + CreateRemovedFile(android_expand_ + + "/123456-7890/user/1/com.android.foo/cache/oat_primary/arm64/base.art"); + + int64_t aidl_return; + ASSERT_TRUE( + artd_ + ->deleteRuntimeArtifacts( + {.packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "arm64"}, + &aidl_return) + .isOk()); + + for (const std::string& path : removed_files) { + EXPECT_FALSE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be removed", path); + } + + for (const std::string& path : kept_files) { + EXPECT_TRUE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be kept", path); + } +} + +TEST_F(ArtdTest, deleteRuntimeArtifactsSpecialChars) { + // TODO(b/289037540): Fix this. + if (getuid() != kRootUid) { + GTEST_SKIP() << "This test requires root access"; + } + + std::vector<std::string> removed_files; + std::vector<std::string> kept_files; + + auto CreateRemovedFile = [&](const std::string& path) { + CreateFile(path); + removed_files.push_back(path); + }; + + auto CreateKeptFile = [&](const std::string& path) { + CreateFile(path); + kept_files.push_back(path); + }; + + CreateKeptFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/base.art"); + + CreateRemovedFile(android_data_ + "/user/0/*/cache/oat_primary/arm64/base.art"); + CreateRemovedFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/*/base.art"); + CreateRemovedFile(android_data_ + "/user/0/com.android.foo/cache/oat_primary/arm64/*.art"); + + int64_t aidl_return; + ASSERT_TRUE( + artd_ + ->deleteRuntimeArtifacts({.packageName = "*", .dexPath = "/a/b/base.apk", .isa = "arm64"}, + &aidl_return) + .isOk()); + ASSERT_TRUE(artd_ + ->deleteRuntimeArtifacts( + {.packageName = "com.android.foo", .dexPath = "/a/b/*.apk", .isa = "arm64"}, + &aidl_return) + .isOk()); + ASSERT_TRUE(artd_ + ->deleteRuntimeArtifacts( + {.packageName = "com.android.foo", .dexPath = "/a/b/base.apk", .isa = "*"}, + &aidl_return) + .isOk()); + + for (const std::string& path : removed_files) { + EXPECT_FALSE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be removed", path); + } + + for (const std::string& path : kept_files) { + EXPECT_TRUE(std::filesystem::exists(path)) << ART_FORMAT("'{}' should be kept", path); + } +} + } // namespace } // namespace artd } // namespace art diff --git a/artd/binder/com/android/server/art/IArtd.aidl b/artd/binder/com/android/server/art/IArtd.aidl index 3b55297ab2..f7b2251917 100644 --- a/artd/binder/com/android/server/art/IArtd.aidl +++ b/artd/binder/com/android/server/art/IArtd.aidl @@ -22,7 +22,10 @@ interface IArtd { boolean isAlive(); /** - * Deletes artifacts and returns the released space, in bytes. + * Deletes dexopt artifacts and returns the released space, in bytes. + * + * Note that this method doesn't delete runtime artifacts. To delete them, call + * `deleteRuntimeArtifacts`. * * Throws fatal errors. Logs and ignores non-fatal errors. */ @@ -180,6 +183,14 @@ interface IArtd { boolean isInDalvikCache(@utf8InCpp String dexFile); /** + * Deletes runtime artifacts and returns the released space, in bytes. + * + * Throws fatal errors. Logs and ignores non-fatal errors. + */ + long deleteRuntimeArtifacts( + in com.android.server.art.RuntimeArtifactsPath runtimeArtifactsPath); + + /** * Returns an error message if the given dex path is invalid, or null if the validation * passes. */ diff --git a/artd/binder/com/android/server/art/RuntimeArtifactsPath.aidl b/artd/binder/com/android/server/art/RuntimeArtifactsPath.aidl new file mode 100644 index 0000000000..4096ea90ab --- /dev/null +++ b/artd/binder/com/android/server/art/RuntimeArtifactsPath.aidl @@ -0,0 +1,32 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.art; + +/** + * Represents the path to the runtime artifacts of a dex file (i.e., ART files generated by the + * runtime, not by dexopt). + * + * @hide + */ +parcelable RuntimeArtifactsPath { + /** The name of the package. */ + @utf8InCpp String packageName; + /** The absolute path starting with '/' to the dex file (i.e., APK or JAR file). */ + @utf8InCpp String dexPath; + /** The instruction set of the dexopt artifacts. */ + @utf8InCpp String isa; +} diff --git a/artd/path_utils.cc b/artd/path_utils.cc index 6ff9b95bc1..0a77d9d0c6 100644 --- a/artd/path_utils.cc +++ b/artd/path_utils.cc @@ -30,6 +30,7 @@ #include "file_utils.h" #include "fstab/fstab.h" #include "oat_file_assistant.h" +#include "runtime_image.h" #include "tools/tools.h" namespace art { @@ -40,6 +41,7 @@ namespace { using ::aidl::com::android::server::art::ArtifactsPath; using ::aidl::com::android::server::art::DexMetadataPath; using ::aidl::com::android::server::art::ProfilePath; +using ::aidl::com::android::server::art::RuntimeArtifactsPath; using ::aidl::com::android::server::art::VdexPath; using ::android::base::Error; using ::android::base::Result; @@ -155,6 +157,35 @@ Result<std::vector<std::string>> ListManagedFiles() { return tools::Glob(patterns); } +Result<std::vector<std::string>> ListRuntimeArtifactsFiles( + const RuntimeArtifactsPath& runtime_artifacts_path) { + std::string android_data = OR_RETURN(GetAndroidDataOrError()); + std::string android_expand = OR_RETURN(GetAndroidExpandOrError()); + + // See `art::tools::Glob` for the syntax. + std::vector<std::string> patterns; + + for (const std::string& data_root : {android_data, android_expand + "/*"}) { + for (const char* user_dir : {"/user", "/user_de"}) { + std::string data_dir = + data_root + user_dir + "/*/" + tools::EscapeGlob(runtime_artifacts_path.packageName); + patterns.push_back( + RuntimeImage::GetRuntimeImagePath(data_dir, + tools::EscapeGlob(runtime_artifacts_path.dexPath), + tools::EscapeGlob(runtime_artifacts_path.isa))); + } + } + + return tools::Glob(patterns); +} + +Result<void> ValidateRuntimeArtifactsPath(const RuntimeArtifactsPath& runtime_artifacts_path) { + OR_RETURN(ValidatePathElement(runtime_artifacts_path.packageName, "packageName")); + OR_RETURN(ValidatePathElement(runtime_artifacts_path.isa, "isa")); + OR_RETURN(ValidateDexPath(runtime_artifacts_path.dexPath)); + return {}; +} + Result<void> ValidateDexPath(const std::string& dex_path) { OR_RETURN(ValidateAbsoluteNormalPath(dex_path)); return {}; diff --git a/artd/path_utils.h b/artd/path_utils.h index a126118137..48640d0348 100644 --- a/artd/path_utils.h +++ b/artd/path_utils.h @@ -31,6 +31,12 @@ namespace artd { // Returns all existing files that are managed by artd. android::base::Result<std::vector<std::string>> ListManagedFiles(); +android::base::Result<std::vector<std::string>> ListRuntimeArtifactsFiles( + const aidl::com::android::server::art::RuntimeArtifactsPath& runtime_artifacts_path); + +android::base::Result<void> ValidateRuntimeArtifactsPath( + const aidl::com::android::server::art::RuntimeArtifactsPath& runtime_artifacts_path); + android::base::Result<void> ValidateDexPath(const std::string& dex_path); android::base::Result<std::string> BuildArtBinPath(const std::string& binary_name); |