summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Yurii Zubrytskyi <zyy@google.com> 2023-05-01 21:58:51 -0700
committer Yurii Zubrytskyi <zyy@google.com> 2023-05-17 18:17:35 +0000
commit70ded19435a5546cc0441e79af985edd210be304 (patch)
treee665538d2425fd5d93fa08dc6f88932805aaca0f
parentf834821e4175bcac67d8627cfc5c4a92179540da (diff)
[idmap] Cache target apks as they are often reused
idmap2d is being often called for the same targets, e.g. system apps. Caching those apks makes idmap verification and creation much faster e.g. for user switching Test: build + boot + UTs Bug: 271904589 Change-Id: Ib6f7af385c2389b50d5c74aa08b4bab290580809
-rw-r--r--cmds/idmap2/Android.bp4
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.cpp44
-rw-r--r--cmds/idmap2/idmap2d/Idmap2Service.h15
3 files changed, 52 insertions, 11 deletions
diff --git a/cmds/idmap2/Android.bp b/cmds/idmap2/Android.bp
index 5f06c971ba98..9988a7dbc3fd 100644
--- a/cmds/idmap2/Android.bp
+++ b/cmds/idmap2/Android.bp
@@ -28,11 +28,14 @@ cc_defaults {
tidy_checks: [
"modernize-*",
"-modernize-avoid-c-arrays",
+ "-modernize-use-nodiscard",
"-modernize-use-trailing-return-type",
"android-*",
"misc-*",
+ "-misc-const-correctness",
"readability-*",
"-readability-identifier-length",
+ "-readability-implicit-bool-conversion",
],
tidy_checks_as_errors: [
"modernize-*",
@@ -56,6 +59,7 @@ cc_defaults {
"-readability-const-return-type",
"-readability-convert-member-functions-to-static",
"-readability-duplicate-include",
+ "-readability-implicit-bool-conversion",
"-readability-else-after-return",
"-readability-named-parameter",
"-readability-redundant-access-specifiers",
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.cpp b/cmds/idmap2/idmap2d/Idmap2Service.cpp
index 10947dc90a76..409ab84112d9 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.cpp
+++ b/cmds/idmap2/idmap2d/Idmap2Service.cpp
@@ -59,7 +59,7 @@ using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask
namespace {
-constexpr const char* kFrameworkPath = "/system/framework/framework-res.apk";
+constexpr std::string_view kFrameworkPath = "/system/framework/framework-res.apk";
Status ok() {
return Status::ok();
@@ -207,23 +207,47 @@ Status Idmap2Service::createIdmap(const std::string& target_path, const std::str
idmap2::Result<Idmap2Service::TargetResourceContainerPtr> Idmap2Service::GetTargetContainer(
const std::string& target_path) {
- if (target_path == kFrameworkPath) {
- if (framework_apk_cache_ == nullptr) {
- // Initialize the framework APK cache.
- auto target = TargetResourceContainer::FromPath(target_path);
- if (!target) {
- return target.GetError();
+ const bool is_framework = target_path == kFrameworkPath;
+ bool use_cache;
+ struct stat st = {};
+ if (is_framework || !::stat(target_path.c_str(), &st)) {
+ use_cache = true;
+ } else {
+ LOG(WARNING) << "failed to stat target path '" << target_path << "' for the cache";
+ use_cache = false;
+ }
+
+ if (use_cache) {
+ std::lock_guard lock(container_cache_mutex_);
+ if (auto cache_it = container_cache_.find(target_path); cache_it != container_cache_.end()) {
+ const auto& item = cache_it->second;
+ if (is_framework ||
+ (item.dev == st.st_dev && item.inode == st.st_ino && item.size == st.st_size
+ && item.mtime.tv_sec == st.st_mtim.tv_sec && item.mtime.tv_nsec == st.st_mtim.tv_nsec)) {
+ return {item.apk.get()};
}
- framework_apk_cache_ = std::move(*target);
+ container_cache_.erase(cache_it);
}
- return {framework_apk_cache_.get()};
}
auto target = TargetResourceContainer::FromPath(target_path);
if (!target) {
return target.GetError();
}
- return {std::move(*target)};
+ if (!use_cache) {
+ return {std::move(*target)};
+ }
+
+ const auto res = target->get();
+ std::lock_guard lock(container_cache_mutex_);
+ container_cache_.emplace(target_path, CachedContainer {
+ .dev = dev_t(st.st_dev),
+ .inode = ino_t(st.st_ino),
+ .size = st.st_size,
+ .mtime = st.st_mtim,
+ .apk = std::move(*target)
+ });
+ return {res};
}
Status Idmap2Service::createFabricatedOverlay(
diff --git a/cmds/idmap2/idmap2d/Idmap2Service.h b/cmds/idmap2/idmap2d/Idmap2Service.h
index cc8cc5f218d2..a69fa6119974 100644
--- a/cmds/idmap2/idmap2d/Idmap2Service.h
+++ b/cmds/idmap2/idmap2d/Idmap2Service.h
@@ -75,7 +75,20 @@ class Idmap2Service : public BinderService<Idmap2Service>, public BnIdmap2 {
private:
// idmap2d is killed after a period of inactivity, so any information stored on this class should
// be able to be recalculated if idmap2 dies and restarts.
- std::unique_ptr<idmap2::TargetResourceContainer> framework_apk_cache_;
+
+ // A cache item for the resource containers (apks or frros), with all information needed to
+ // detect if it has changed since it was parsed:
+ // - (dev, inode) pair uniquely identifies a file on a particular device partition (see stat(2)).
+ // - (mtime, size) ensure the file data hasn't changed inside that file.
+ struct CachedContainer {
+ dev_t dev;
+ ino_t inode;
+ int64_t size;
+ struct timespec mtime;
+ std::unique_ptr<idmap2::TargetResourceContainer> apk;
+ };
+ std::unordered_map<std::string, CachedContainer> container_cache_;
+ std::mutex container_cache_mutex_;
int32_t frro_iter_id_ = 0;
std::optional<std::filesystem::directory_iterator> frro_iter_;