diff options
author | 2023-05-02 10:53:14 -0700 | |
---|---|---|
committer | 2023-05-23 21:27:38 +0000 | |
commit | 75663392c67aa78850f047dabf4648e53c22f48a (patch) | |
tree | b147c44969021761bc7fc117ecd202523d9300bc | |
parent | 06560ed48f936e3b228f7b67895f6d9085d1f3c9 (diff) |
[res] Overlayable only mode of loading ApkAssets
OverlayManagerService only needs to know the overlayable
declarations of the apk, and as of now the only way to get those
is to completely load and parse the whole resources file.
This CL adds a flag to only parse the overlayable declarations,
speeding up loading by ~2x
Test: build + boot + UTs + user switching
Bug: 271904589
Change-Id: I1ec4b9b57dd1aee1769cc2d4dd9641e5e68639f8
-rw-r--r-- | core/java/android/content/res/ApkAssets.java | 5 | ||||
-rw-r--r-- | libs/androidfw/LoadedArsc.cpp | 21 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/LoadedArsc.h | 3 | ||||
-rw-r--r-- | services/core/java/com/android/server/om/OverlayManagerService.java | 3 |
4 files changed, 30 insertions, 2 deletions
diff --git a/core/java/android/content/res/ApkAssets.java b/core/java/android/content/res/ApkAssets.java index 143c00dd4d81..653e243f5e06 100644 --- a/core/java/android/content/res/ApkAssets.java +++ b/core/java/android/content/res/ApkAssets.java @@ -78,6 +78,11 @@ public final class ApkAssets { */ public static final int PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1 << 4; + /** + * The apk assets only contain the overlayable declarations information. + */ + public static final int PROPERTY_ONLY_OVERLAYABLES = 1 << 5; + /** Flags that change the behavior of loaded apk assets. */ @IntDef(prefix = { "PROPERTY_" }, value = { PROPERTY_SYSTEM, diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index fbfae5e2bcbe..c9d5e074271b 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -494,6 +494,8 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, util::ReadUtf16StringFromDevice(header->name, arraysize(header->name), &loaded_package->package_name_); + const bool only_overlayable = (property_flags & PROPERTY_ONLY_OVERLAYABLES) != 0; + // A map of TypeSpec builders, each associated with an type index. // We use these to accumulate the set of Types available for a TypeSpec, and later build a single, // contiguous block of memory that holds all the Types together with the TypeSpec. @@ -502,6 +504,9 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); while (iter.HasNext()) { const Chunk child_chunk = iter.Next(); + if (only_overlayable && child_chunk.type() != RES_TABLE_OVERLAYABLE_TYPE) { + continue; + } switch (child_chunk.type()) { case RES_STRING_POOL_TYPE: { const auto pool_address = child_chunk.header<ResChunk_header>(); @@ -655,6 +660,9 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, << name_to_actor_it->first << "'."; return {}; } + if (only_overlayable) { + break; + } // Iterate over the overlayable policy chunks contained within the overlayable chunk data ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size()); @@ -800,14 +808,21 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, global_string_pool_ = util::make_unique<OverlayStringPool>(loaded_idmap); } + const bool only_overlayable = (property_flags & PROPERTY_ONLY_OVERLAYABLES) != 0; + const size_t package_count = dtohl(header->packageCount); size_t packages_seen = 0; - packages_.reserve(package_count); + if (!only_overlayable) { + packages_.reserve(package_count); + } ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); while (iter.HasNext()) { const Chunk child_chunk = iter.Next(); + if (only_overlayable && child_chunk.type() != RES_TABLE_PACKAGE_TYPE) { + continue; + } switch (child_chunk.type()) { case RES_STRING_POOL_TYPE: // Only use the first string pool. Ignore others. @@ -837,6 +852,10 @@ bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, return false; } packages_.push_back(std::move(loaded_package)); + if (only_overlayable) { + // Overlayable is always in the first package, no need to process anything else. + return true; + } } break; default: diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h index 4d12885ad291..3a7287187781 100644 --- a/libs/androidfw/include/androidfw/LoadedArsc.h +++ b/libs/androidfw/include/androidfw/LoadedArsc.h @@ -96,6 +96,9 @@ enum : package_property_t { // The apk assets is owned by the application running in this process and incremental crash // protections for this APK must be disabled. PROPERTY_DISABLE_INCREMENTAL_HARDENING = 1U << 4U, + + // The apk assets only contain the overlayable declarations information. + PROPERTY_ONLY_OVERLAYABLES = 1U << 5U, }; struct OverlayableInfo { diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index d471c8abb1b2..e54f12c37559 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -1301,7 +1301,8 @@ public final class OverlayManagerService extends SystemService { ApkAssets apkAssets = null; try { - apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath()); + apkAssets = ApkAssets.loadFromPath(pkg.getSplits().get(0).getPath(), + ApkAssets.PROPERTY_ONLY_OVERLAYABLES); return apkAssets.getOverlayableInfo(targetOverlayableName); } finally { if (apkAssets != null) { |