Do not look for R.class of overlays
Now that RROs are loaded as shared libraries,
LoadedApk#makeApplication is attempting to find the onResourcesLoaded
method of the overlays. This is a performance hit and causes more
memory than necessary to be allocated during application start up.
Bug: 143314947
Test: com.android.performance.tests.HermeticMemoryTest
Change-Id: I3b8cd22dae83e0164d6678c80279f9fffceb34e6
diff --git a/libs/androidfw/ApkAssets.cpp b/libs/androidfw/ApkAssets.cpp
index 16dbbf6..18934fd 100644
--- a/libs/androidfw/ApkAssets.cpp
+++ b/libs/androidfw/ApkAssets.cpp
@@ -43,20 +43,22 @@
ApkAssets::ApkAssets(ZipArchiveHandle unmanaged_handle,
const std::string& path,
time_t last_mod_time,
- bool for_loader)
+ package_property_t property_flags)
: zip_handle_(unmanaged_handle, ::CloseArchive), path_(path), last_mod_time_(last_mod_time),
- for_loader_(for_loader) {
+ property_flags_(property_flags) {
}
std::unique_ptr<const ApkAssets> ApkAssets::Load(const std::string& path, bool system,
bool for_loader) {
- return LoadImpl({} /*fd*/, path, nullptr, nullptr, system, false /*load_as_shared_library*/,
- for_loader);
+ package_property_t flags = (system ? PROPERTY_SYSTEM : 0U) |
+ (for_loader ? PROPERTY_LOADER : 0U);
+ return LoadImpl({} /*fd*/, path, nullptr, nullptr, flags);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadAsSharedLibrary(const std::string& path,
bool system) {
- return LoadImpl({} /*fd*/, path, nullptr, nullptr, system, true /*load_as_shared_library*/);
+ package_property_t flags = PROPERTY_DYNAMIC | (system ? PROPERTY_SYSTEM : 0U);
+ return LoadImpl({} /*fd*/, path, nullptr, nullptr, flags);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadOverlay(const std::string& idmap_path,
@@ -74,27 +76,33 @@
LOG(ERROR) << "failed to load IDMAP " << idmap_path;
return {};
}
- return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(), std::move(idmap_asset),
- std::move(loaded_idmap), system, true /*load_as_shared_library*/);
+
+ return LoadImpl({} /*fd*/, loaded_idmap->OverlayApkPath(),
+ std::move(idmap_asset),
+ std::move(loaded_idmap),
+ PROPERTY_OVERLAY | (system ? PROPERTY_SYSTEM : 0U));
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadFromFd(unique_fd fd,
const std::string& friendly_name,
bool system, bool force_shared_lib,
bool for_loader) {
+ package_property_t flags = (system ? PROPERTY_SYSTEM : 0U) |
+ (force_shared_lib ? PROPERTY_DYNAMIC : 0U) |
+ (for_loader ? PROPERTY_LOADER : 0U);
return LoadImpl(std::move(fd), friendly_name, nullptr /*idmap_asset*/, nullptr /*loaded_idmap*/,
- system, force_shared_lib, for_loader);
+ flags);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadArsc(const std::string& path,
bool for_loader) {
- return LoadArscImpl({} /*fd*/, path, for_loader);
+ return LoadArscImpl({} /*fd*/, path, for_loader ? PROPERTY_LOADER : 0U);
}
std::unique_ptr<const ApkAssets> ApkAssets::LoadArsc(unique_fd fd,
const std::string& friendly_name,
bool for_loader) {
- return LoadArscImpl(std::move(fd), friendly_name, for_loader);
+ return LoadArscImpl(std::move(fd), friendly_name, for_loader ? PROPERTY_LOADER : 0U);
}
std::unique_ptr<Asset> ApkAssets::CreateAssetFromFile(const std::string& path) {
@@ -120,8 +128,7 @@
std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(
unique_fd fd, const std::string& path, std::unique_ptr<Asset> idmap_asset,
- std::unique_ptr<const LoadedIdmap> loaded_idmap, bool system, bool load_as_shared_library,
- bool for_loader) {
+ std::unique_ptr<const LoadedIdmap> loaded_idmap, package_property_t property_flags) {
::ZipArchiveHandle unmanaged_handle;
int32_t result;
if (fd >= 0) {
@@ -141,7 +148,7 @@
// Wrap the handle in a unique_ptr so it gets automatically closed.
std::unique_ptr<ApkAssets>
- loaded_apk(new ApkAssets(unmanaged_handle, path, last_mod_time, for_loader));
+ loaded_apk(new ApkAssets(unmanaged_handle, path, last_mod_time, property_flags));
// Find the resource table.
::ZipEntry entry;
@@ -170,9 +177,8 @@
const StringPiece data(
reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
loaded_apk->resources_asset_->getLength());
- loaded_apk->loaded_arsc_ =
- LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(), system, load_as_shared_library,
- for_loader);
+ loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, loaded_apk->loaded_idmap_.get(),
+ property_flags);
if (loaded_apk->loaded_arsc_ == nullptr) {
LOG(ERROR) << "Failed to load '" << kResourcesArsc << "' in APK '" << path << "'.";
return {};
@@ -184,7 +190,7 @@
std::unique_ptr<const ApkAssets> ApkAssets::LoadArscImpl(unique_fd fd,
const std::string& path,
- bool for_loader) {
+ package_property_t property_flags) {
std::unique_ptr<Asset> resources_asset;
if (fd >= 0) {
@@ -201,13 +207,14 @@
time_t last_mod_time = getFileModDate(path.c_str());
- std::unique_ptr<ApkAssets> loaded_apk(new ApkAssets(nullptr, path, last_mod_time, for_loader));
+ std::unique_ptr<ApkAssets> loaded_apk(
+ new ApkAssets(nullptr, path, last_mod_time, property_flags));
loaded_apk->resources_asset_ = std::move(resources_asset);
const StringPiece data(
reinterpret_cast<const char*>(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/)),
loaded_apk->resources_asset_->getLength());
- loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, nullptr, false, false, for_loader);
+ loaded_apk->loaded_arsc_ = LoadedArsc::Load(data, nullptr, property_flags);
if (loaded_apk->loaded_arsc_ == nullptr) {
LOG(ERROR) << "Failed to load '" << kResourcesArsc << path;
return {};
@@ -320,8 +327,8 @@
}
bool ApkAssets::IsUpToDate() const {
- // Loaders are invalidated by the app, not the system, so assume up to date
- if (for_loader_) {
+ if (IsLoader()) {
+ // Loaders are invalidated by the app, not the system, so assume up to date.
return true;
}
diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp
index 2b69c92..773353d 100644
--- a/libs/androidfw/Idmap.cpp
+++ b/libs/androidfw/Idmap.cpp
@@ -44,8 +44,8 @@
}
OverlayStringPool::OverlayStringPool(const LoadedIdmap* loaded_idmap)
- : data_header_(loaded_idmap->data_header_),
- idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
+ : data_header_(loaded_idmap->data_header_),
+ idmap_string_pool_(loaded_idmap->string_pool_.get()) { };
OverlayStringPool::~OverlayStringPool() {
uninit();
@@ -188,11 +188,12 @@
const Idmap_data_header* data_header,
const Idmap_target_entry* target_entries,
const Idmap_overlay_entry* overlay_entries,
- ResStringPool* string_pool) : header_(header),
- data_header_(data_header),
- target_entries_(target_entries),
- overlay_entries_(overlay_entries),
- string_pool_(string_pool) {
+ ResStringPool* string_pool)
+ : header_(header),
+ data_header_(data_header),
+ target_entries_(target_entries),
+ overlay_entries_(overlay_entries),
+ string_pool_(string_pool) {
size_t length = strnlen(reinterpret_cast<const char*>(header_->overlay_path),
arraysize(header_->overlay_path));
@@ -264,7 +265,7 @@
}
}
- // Can't use make_unique because LoadedImpl constructor is private.
+ // Can't use make_unique because LoadedIdmap constructor is private.
std::unique_ptr<LoadedIdmap> loaded_idmap = std::unique_ptr<LoadedIdmap>(
new LoadedIdmap(header, data_header, target_entries, overlay_entries,
idmap_string_pool.release()));
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index c896241..e35c024 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -397,9 +397,7 @@
}
std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
- bool system,
- bool load_as_shared_library,
- bool for_loader) {
+ package_property_t property_flags) {
ATRACE_NAME("LoadedPackage::Load");
std::unique_ptr<LoadedPackage> loaded_package(new LoadedPackage());
@@ -413,17 +411,24 @@
return {};
}
- loaded_package->system_ = system;
+ if ((property_flags & PROPERTY_SYSTEM) != 0) {
+ loaded_package->property_flags_ |= PROPERTY_SYSTEM;
+ }
+
+ if ((property_flags & PROPERTY_LOADER) != 0) {
+ loaded_package->property_flags_ |= PROPERTY_LOADER;
+ }
+
+ if ((property_flags & PROPERTY_OVERLAY) != 0) {
+ // Overlay resources must have an exclusive resource id space for referencing internal
+ // resources.
+ loaded_package->property_flags_ |= PROPERTY_OVERLAY | PROPERTY_DYNAMIC;
+ }
loaded_package->package_id_ = dtohl(header->id);
if (loaded_package->package_id_ == 0 ||
- (loaded_package->package_id_ == kAppPackageId && load_as_shared_library)) {
- // Package ID of 0 means this is a shared library.
- loaded_package->dynamic_ = true;
- }
-
- if (for_loader) {
- loaded_package->custom_loader_ = true;
+ (loaded_package->package_id_ == kAppPackageId && (property_flags & PROPERTY_DYNAMIC) != 0)) {
+ loaded_package->property_flags_ |= PROPERTY_DYNAMIC;
}
if (header->header.headerSize >= sizeof(ResTable_package)) {
@@ -677,7 +682,7 @@
}
bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
- bool load_as_shared_library, bool for_loader) {
+ package_property_t property_flags) {
const ResTable_header* header = chunk.header<ResTable_header>();
if (header == nullptr) {
LOG(ERROR) << "RES_TABLE_TYPE too small.";
@@ -720,7 +725,7 @@
packages_seen++;
std::unique_ptr<const LoadedPackage> loaded_package =
- LoadedPackage::Load(child_chunk, system_, load_as_shared_library, for_loader);
+ LoadedPackage::Load(child_chunk, property_flags);
if (!loaded_package) {
return false;
}
@@ -744,24 +749,18 @@
std::unique_ptr<const LoadedArsc> LoadedArsc::Load(const StringPiece& data,
const LoadedIdmap* loaded_idmap,
- bool system,
- bool load_as_shared_library,
- bool for_loader) {
+ package_property_t property_flags) {
ATRACE_NAME("LoadedArsc::Load");
// Not using make_unique because the constructor is private.
std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc());
- loaded_arsc->system_ = system;
ChunkIterator iter(data.data(), data.size());
while (iter.HasNext()) {
const Chunk chunk = iter.Next();
switch (chunk.type()) {
case RES_TABLE_TYPE:
- if (!loaded_arsc->LoadTable(chunk,
- loaded_idmap,
- load_as_shared_library,
- for_loader)) {
+ if (!loaded_arsc->LoadTable(chunk, loaded_idmap, property_flags)) {
return {};
}
break;
diff --git a/libs/androidfw/include/androidfw/ApkAssets.h b/libs/androidfw/include/androidfw/ApkAssets.h
index 2047287..af802b0 100644
--- a/libs/androidfw/include/androidfw/ApkAssets.h
+++ b/libs/androidfw/include/androidfw/ApkAssets.h
@@ -76,10 +76,10 @@
// Takes ownership of the file descriptor.
static std::unique_ptr<const ApkAssets> LoadArsc(base::unique_fd fd,
const std::string& friendly_name,
- bool resource_loader = false);
+ bool for_loader = false);
// Creates a totally empty ApkAssets with no resources table and no file entries.
- static std::unique_ptr<const ApkAssets> LoadEmpty(bool resource_loader = false);
+ static std::unique_ptr<const ApkAssets> LoadEmpty(bool for_loader = false);
std::unique_ptr<Asset> Open(const std::string& path,
Asset::AccessMode mode = Asset::AccessMode::ACCESS_RANDOM) const;
@@ -100,12 +100,12 @@
return loaded_idmap_.get();
}
- inline bool IsOverlay() const {
- return idmap_asset_.get() != nullptr;
+ inline bool IsLoader() const {
+ return (property_flags_ & PROPERTY_LOADER) != 0;
}
- inline bool IsLoader() const {
- return for_loader_;
+ inline bool IsOverlay() const {
+ return (property_flags_ & PROPERTY_OVERLAY) != 0;
}
bool IsUpToDate() const;
@@ -119,24 +119,23 @@
static std::unique_ptr<const ApkAssets> LoadImpl(base::unique_fd fd, const std::string& path,
std::unique_ptr<Asset> idmap_asset,
std::unique_ptr<const LoadedIdmap> loaded_idmap,
- bool system, bool load_as_shared_library,
- bool resource_loader = false);
+ package_property_t property_flags);
static std::unique_ptr<const ApkAssets> LoadArscImpl(base::unique_fd fd,
const std::string& path,
- bool resource_loader = false);
+ package_property_t property_flags);
ApkAssets(ZipArchiveHandle unmanaged_handle,
const std::string& path,
time_t last_mod_time,
- bool for_loader = false);
+ package_property_t property_flags);
using ZipArchivePtr = std::unique_ptr<ZipArchive, void (*)(ZipArchiveHandle)>;
ZipArchivePtr zip_handle_;
const std::string path_;
time_t last_mod_time_;
- bool for_loader_;
+ package_property_t property_flags_ = 0U;
std::unique_ptr<Asset> resources_asset_;
std::unique_ptr<Asset> idmap_asset_;
std::unique_ptr<const LoadedArsc> loaded_arsc_;
diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h
index 20e4023..00cbbca 100644
--- a/libs/androidfw/include/androidfw/AssetManager2.h
+++ b/libs/androidfw/include/androidfw/AssetManager2.h
@@ -263,10 +263,13 @@
// Creates a new Theme from this AssetManager.
std::unique_ptr<Theme> NewTheme();
- void ForEachPackage(const std::function<bool(const std::string&, uint8_t)> func) const {
+ void ForEachPackage(const std::function<bool(const std::string&, uint8_t)> func,
+ package_property_t excluded_property_flags = 0U) const {
for (const PackageGroup& package_group : package_groups_) {
- if (!func(package_group.packages_.front().loaded_package_->GetPackageName(),
- package_group.dynamic_ref_table->mAssignedPackageId)) {
+ const auto loaded_package = package_group.packages_.front().loaded_package_;
+ if ((loaded_package->GetPropertyFlags() & excluded_property_flags) == 0U
+ && !func(loaded_package->GetPackageName(),
+ package_group.dynamic_ref_table->mAssignedPackageId)) {
return;
}
}
diff --git a/libs/androidfw/include/androidfw/LoadedArsc.h b/libs/androidfw/include/androidfw/LoadedArsc.h
index ba1beaa..6cbda07 100644
--- a/libs/androidfw/include/androidfw/LoadedArsc.h
+++ b/libs/androidfw/include/androidfw/LoadedArsc.h
@@ -69,6 +69,14 @@
}
};
+using package_property_t = uint32_t;
+enum : package_property_t {
+ PROPERTY_DYNAMIC = 1,
+ PROPERTY_LOADER = 2,
+ PROPERTY_OVERLAY = 4,
+ PROPERTY_SYSTEM = 8,
+};
+
// TypeSpecPtr points to a block of memory that holds a TypeSpec struct, followed by an array of
// ResTable_type pointers.
// TypeSpecPtr is a managed pointer that knows how to delete itself.
@@ -131,9 +139,8 @@
return iterator(this, resource_ids_.size() + 1, 0);
}
- static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk, bool system,
- bool load_as_shared_library,
- bool load_as_custom_loader);
+ static std::unique_ptr<const LoadedPackage> Load(const Chunk& chunk,
+ package_property_t property_flags);
~LoadedPackage();
@@ -170,17 +177,26 @@
// Returns true if this package is dynamic (shared library) and needs to have an ID assigned.
inline bool IsDynamic() const {
- return dynamic_;
+ return (property_flags_ & PROPERTY_DYNAMIC) != 0;
+ }
+
+ // Returns true if this package is a Runtime Resource Overlay.
+ inline bool IsOverlay() const {
+ return (property_flags_ & PROPERTY_OVERLAY) != 0;
}
// Returns true if this package originates from a system provided resource.
inline bool IsSystem() const {
- return system_;
+ return (property_flags_ & PROPERTY_SYSTEM) != 0;
}
- // Returns true if this package is a custom loader and should behave like an overlay
+ // Returns true if this package is a custom loader and should behave like an overlay.
inline bool IsCustomLoader() const {
- return custom_loader_;
+ return (property_flags_ & PROPERTY_LOADER) != 0;
+ }
+
+ inline package_property_t GetPropertyFlags() const {
+ return property_flags_;
}
// Returns the map of package name to package ID used in this LoadedPackage. At runtime, a
@@ -248,12 +264,10 @@
ResStringPool type_string_pool_;
ResStringPool key_string_pool_;
std::string package_name_;
+ bool defines_overlayable_ = false;
int package_id_ = -1;
int type_id_offset_ = 0;
- bool dynamic_ = false;
- bool system_ = false;
- bool custom_loader_ = false;
- bool defines_overlayable_ = false;
+ package_property_t property_flags_ = 0U;
ByteBucketArray<TypeSpecPtr> type_specs_;
ByteBucketArray<uint32_t> resource_ids_;
@@ -274,9 +288,7 @@
// ID.
static std::unique_ptr<const LoadedArsc> Load(const StringPiece& data,
const LoadedIdmap* loaded_idmap = nullptr,
- bool system = false,
- bool load_as_shared_library = false,
- bool for_loader = false);
+ package_property_t property_flags = 0U);
// Create an empty LoadedArsc. This is used when an APK has no resources.arsc.
static std::unique_ptr<const LoadedArsc> CreateEmpty();
@@ -296,28 +308,15 @@
return packages_;
}
- // Returns true if this is a system provided resource.
- inline bool IsSystem() const {
- return system_;
- }
-
private:
DISALLOW_COPY_AND_ASSIGN(LoadedArsc);
LoadedArsc() = default;
- bool LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap, bool load_as_shared_library,
- bool for_loader);
-
- static std::unique_ptr<const LoadedArsc> LoadData(std::unique_ptr<LoadedArsc>& loaded_arsc,
- const char* data,
- size_t length,
- const LoadedIdmap* loaded_idmap = nullptr,
- bool load_as_shared_library = false,
- bool for_loader = false);
+ bool LoadTable(
+ const Chunk& chunk, const LoadedIdmap* loaded_idmap, package_property_t property_flags);
std::unique_ptr<ResStringPool> global_string_pool_ = util::make_unique<ResStringPool>();
std::vector<std::unique_ptr<const LoadedPackage>> packages_;
- bool system_ = false;
};
} // namespace android
diff --git a/libs/androidfw/tests/LoadedArsc_test.cpp b/libs/androidfw/tests/LoadedArsc_test.cpp
index 82dd335..8615069 100644
--- a/libs/androidfw/tests/LoadedArsc_test.cpp
+++ b/libs/androidfw/tests/LoadedArsc_test.cpp
@@ -144,8 +144,7 @@
"resources.arsc", &contents));
std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
- true /*load_as_shared_library*/);
+ LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, PROPERTY_DYNAMIC);
ASSERT_THAT(loaded_arsc, NotNull());
const auto& packages = loaded_arsc->GetPackages();
@@ -227,9 +226,7 @@
ASSERT_TRUE(ReadFileFromZipToString(GetTestDataPath() + "/overlayable/overlayable.apk",
"resources.arsc", &contents));
- std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(StringPiece(contents), nullptr /* loaded_idmap */, false /*system*/,
- false /*load_as_shared_library*/);
+ std::unique_ptr<const LoadedArsc> loaded_arsc = LoadedArsc::Load(StringPiece(contents));
ASSERT_THAT(loaded_arsc, NotNull());
const LoadedPackage* package = loaded_arsc->GetPackageById(
@@ -346,7 +343,7 @@
asset->getLength());
std::unique_ptr<const LoadedArsc> loaded_arsc =
- LoadedArsc::Load(data, nullptr, false, false, true);
+ LoadedArsc::Load(data, nullptr, PROPERTY_LOADER);
ASSERT_THAT(loaded_arsc, NotNull());
const LoadedPackage* package =