diff options
author | 2023-11-10 15:38:16 -0800 | |
---|---|---|
committer | 2024-01-17 23:52:44 -0800 | |
commit | 4f48ffd43b182f31a199e54a39406cbd3d84abb0 (patch) | |
tree | 5c61118e0ccd63e32b1ec35210d17e6ae87b7b23 | |
parent | 77e28bd5261e47775c8b65759320036a5fb52f15 (diff) |
[res] Store the number of types in typeSpec
Bug: 282215580
Test: build + boot + perf record
Change-Id: Ide34e48f8ba63a38a93f0a15618d601857498683
-rw-r--r-- | libs/androidfw/LoadedArsc.cpp | 22 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ResourceTypes.h | 4 | ||||
-rw-r--r-- | tools/aapt2/format/binary/TableFlattener.cpp | 17 |
3 files changed, 26 insertions, 17 deletions
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index c9d5e074271b..02707e0e0c73 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -21,6 +21,7 @@ #include <algorithm> #include <cstddef> #include <limits> +#include <optional> #include "android-base/logging.h" #include "android-base/stringprintf.h" @@ -50,7 +51,9 @@ namespace { // contiguous block of memory to store both the TypeSpec struct and // the Type structs. struct TypeSpecBuilder { - explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) {} + explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) { + type_entries.reserve(dtohs(header_->typesCount)); + } void AddType(incfs::verified_map_ptr<ResTable_type> type) { TypeSpec::TypeEntry& entry = type_entries.emplace_back(); @@ -59,6 +62,7 @@ struct TypeSpecBuilder { } TypeSpec Build() { + type_entries.shrink_to_fit(); return {header_, std::move(type_entries)}; } @@ -499,7 +503,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, // 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. - std::unordered_map<int, std::unique_ptr<TypeSpecBuilder>> type_builder_map; + std::unordered_map<int, std::optional<TypeSpecBuilder>> type_builder_map; ChunkIterator iter(chunk.data_ptr(), chunk.data_size()); while (iter.HasNext()) { @@ -567,14 +571,14 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, return {}; } - if (entry_count * sizeof(uint32_t) > chunk.data_size()) { + if (entry_count * sizeof(uint32_t) > child_chunk.data_size()) { LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small to hold entries."; return {}; } - std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type_spec->id]; - if (builder_ptr == nullptr) { - builder_ptr = util::make_unique<TypeSpecBuilder>(type_spec.verified()); + auto& maybe_type_builder = type_builder_map[type_spec->id]; + if (!maybe_type_builder) { + maybe_type_builder.emplace(type_spec.verified()); loaded_package->resource_ids_.set(type_spec->id, entry_count); } else { LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x", @@ -594,9 +598,9 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } // Type chunks must be preceded by their TypeSpec chunks. - std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type->id]; - if (builder_ptr != nullptr) { - builder_ptr->AddType(type.verified()); + auto& maybe_type_builder = type_builder_map[type->id]; + if (maybe_type_builder) { + maybe_type_builder->AddType(type.verified()); } else { LOG(ERROR) << StringPrintf( "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.", diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index c0514fdff469..44ab14a8a7ac 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -1401,8 +1401,8 @@ struct ResTable_typeSpec // Must be 0. uint8_t res0; - // Must be 0. - uint16_t res1; + // Used to be reserved, if >0 specifies the number of ResTable_type entries for this spec. + uint16_t typesCount; // Number of uint32_t entry configuration masks that follow. uint32_t entryCount; diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index f05611048caa..1a82021bce71 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -381,9 +381,9 @@ class PackageFlattener { return true; } - bool FlattenTypeSpec(const ResourceTableTypeView& type, - const std::vector<ResourceTableEntryView>& sorted_entries, - BigBuffer* buffer) { + ResTable_typeSpec* FlattenTypeSpec(const ResourceTableTypeView& type, + const std::vector<ResourceTableEntryView>& sorted_entries, + BigBuffer* buffer) { ChunkWriter type_spec_writer(buffer); ResTable_typeSpec* spec_header = type_spec_writer.StartChunk<ResTable_typeSpec>(RES_TABLE_TYPE_SPEC_TYPE); @@ -391,7 +391,7 @@ class PackageFlattener { if (sorted_entries.empty()) { type_spec_writer.Finish(); - return true; + return spec_header; } // We can't just take the size of the vector. There may be holes in the @@ -427,7 +427,7 @@ class PackageFlattener { } } type_spec_writer.Finish(); - return true; + return spec_header; } bool FlattenTypes(BigBuffer* buffer) { @@ -450,7 +450,8 @@ class PackageFlattener { expected_type_id++; type_pool_.MakeRef(type.named_type.to_string()); - if (!FlattenTypeSpec(type, type.entries, buffer)) { + const auto type_spec_header = FlattenTypeSpec(type, type.entries, buffer); + if (!type_spec_header) { return false; } @@ -511,6 +512,10 @@ class PackageFlattener { return false; } } + + // And now we can update the type entries count in the typeSpec header. + type_spec_header->typesCount = android::util::HostToDevice16(uint16_t(std::min<uint32_t>( + config_to_entry_list_map.size(), std::numeric_limits<uint16_t>::max()))); } return true; } |