summaryrefslogtreecommitdiff
path: root/artd
diff options
context:
space:
mode:
author Jiakai Zhang <jiakaiz@google.com> 2023-09-07 19:05:10 +0100
committer Jiakai Zhang <jiakaiz@google.com> 2023-10-10 19:01:06 +0000
commit356505949dc46612f64b13424d2496f4e9ef9ace (patch)
tree5bdc185e46dd1397ca09199965f41ac8c82c03c4 /artd
parent6ab6ca740ec15717d8ebbbfcdea72f9f7a1c0731 (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.cc11
-rw-r--r--artd/artd.h4
-rw-r--r--artd/artd_test.cc103
-rw-r--r--artd/binder/com/android/server/art/IArtd.aidl13
-rw-r--r--artd/binder/com/android/server/art/RuntimeArtifactsPath.aidl32
-rw-r--r--artd/path_utils.cc31
-rw-r--r--artd/path_utils.h6
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);