diff options
author | 2022-08-23 17:42:50 +0000 | |
---|---|---|
committer | 2022-09-15 21:45:27 +0000 | |
commit | be2b7797466789f6c4fcf7ff81bc891dd933b990 (patch) | |
tree | a6c41325aef7d5713fbf6c58aecfaaf158b4880f | |
parent | 4e0d271b002ad6c47ecbf03218ffbf44c1af76f4 (diff) |
Store frro configs in idmap file
This also includes the change to use the configs to decide which (if
any) frros to use at runtime
Bug: 243066074
Test: Manual, updated and created automated tests
Change-Id: I3f1d23e2958ad170799880b9f5eb5bd8ceb1fa67
20 files changed, 400 insertions, 144 deletions
diff --git a/cmds/idmap2/include/idmap2/Idmap.h b/cmds/idmap2/include/idmap2/Idmap.h index 58aff42b1e98..03e714a3847e 100644 --- a/cmds/idmap2/include/idmap2/Idmap.h +++ b/cmds/idmap2/include/idmap2/Idmap.h @@ -21,42 +21,51 @@ * header := magic version target_crc overlay_crc fulfilled_policies * enforce_overlayable target_path overlay_path overlay_name * debug_info - * data := data_header target_entry* target_inline_entry* overlay_entry* - * string_pool - * data_header := target_entry_count target_inline_entry_count overlay_entry_count + * data := data_header target_entry* target_inline_entry* + target_inline_entry_value* config* overlay_entry* string_pool + * data_header := target_entry_count target_inline_entry_count + target_inline_entry_value_count config_count overlay_entry_count * string_pool_index * target_entry := target_id overlay_id - * target_inline_entry := target_id Res_value::size padding(1) Res_value::type + * target_inline_entry := target_id start_value_index value_count + * target_inline_entry_value := config_index Res_value::size padding(1) Res_value::type + * Res_value::value + * config := target_id Res_value::size padding(1) Res_value::type * Res_value::value * overlay_entry := overlay_id target_id * - * debug_info := string - * enforce_overlayable := <uint32_t> - * fulfilled_policies := <uint32_t> - * magic := <uint32_t> - * overlay_crc := <uint32_t> - * overlay_entry_count := <uint32_t> - * overlay_id := <uint32_t> - * overlay_package_id := <uint8_t> - * overlay_name := string - * overlay_path := string - * padding(n) := <uint8_t>[n] - * Res_value::size := <uint16_t> - * Res_value::type := <uint8_t> - * Res_value::value := <uint32_t> - * string := <uint32_t> <uint8_t>+ padding(n) - * string_pool := string - * string_pool_index := <uint32_t> - * string_pool_length := <uint32_t> - * target_crc := <uint32_t> - * target_entry_count := <uint32_t> - * target_inline_entry_count := <uint32_t> - * target_id := <uint32_t> - * target_package_id := <uint8_t> - * target_path := string - * value_type := <uint8_t> - * value_data := <uint32_t> - * version := <uint32_t> + * debug_info := string + * enforce_overlayable := <uint32_t> + * fulfilled_policies := <uint32_t> + * magic := <uint32_t> + * overlay_crc := <uint32_t> + * overlay_entry_count := <uint32_t> + * overlay_id := <uint32_t> + * overlay_package_id := <uint8_t> + * overlay_name := string + * overlay_path := string + * padding(n) := <uint8_t>[n] + * Res_value::size := <uint16_t> + * Res_value::type := <uint8_t> + * Res_value::value := <uint32_t> + * string := <uint32_t> <uint8_t>+ padding(n) + * string_pool := string + * string_pool_index := <uint32_t> + * string_pool_length := <uint32_t> + * target_crc := <uint32_t> + * target_entry_count := <uint32_t> + * target_inline_entry_count := <uint32_t> + * target_inline_entry_value_count := <uint32_t> + * config_count := <uint32_t> + * config_index := <uint32_t> + * start_value_index := <uint32_t> + * value_count := <uint32_t> + * target_id := <uint32_t> + * target_package_id := <uint8_t> + * target_path := string + * value_type := <uint8_t> + * value_data := <uint32_t> + * version := <uint32_t> */ #ifndef IDMAP2_INCLUDE_IDMAP2_IDMAP_H_ @@ -70,6 +79,7 @@ #include "android-base/macros.h" #include "androidfw/ResourceTypes.h" #include "androidfw/StringPiece.h" +#include "androidfw/ConfigDescription.h" #include "idmap2/ResourceContainer.h" #include "idmap2/ResourceMapping.h" @@ -165,19 +175,27 @@ class IdmapData { public: static std::unique_ptr<const Header> FromBinaryStream(std::istream& stream); - inline uint32_t GetTargetEntryCount() const { + [[nodiscard]] inline uint32_t GetTargetEntryCount() const { return target_entry_count; } - inline uint32_t GetTargetInlineEntryCount() const { + [[nodiscard]] inline uint32_t GetTargetInlineEntryCount() const { return target_entry_inline_count; } - inline uint32_t GetOverlayEntryCount() const { + [[nodiscard]] inline uint32_t GetTargetInlineEntryValueCount() const { + return target_entry_inline_value_count; + } + + [[nodiscard]] inline uint32_t GetConfigCount() const { + return config_count; + } + + [[nodiscard]] inline uint32_t GetOverlayEntryCount() const { return overlay_entry_count; } - inline uint32_t GetStringPoolIndexOffset() const { + [[nodiscard]] inline uint32_t GetStringPoolIndexOffset() const { return string_pool_index_offset; } @@ -186,6 +204,8 @@ class IdmapData { private: uint32_t target_entry_count; uint32_t target_entry_inline_count; + uint32_t target_entry_inline_value_count; + uint32_t config_count; uint32_t overlay_entry_count; uint32_t string_pool_index_offset; Header() = default; @@ -202,7 +222,7 @@ class IdmapData { struct TargetInlineEntry { ResourceId target_id; - TargetValue value; + std::map<ConfigDescription, TargetValue> values; }; struct OverlayEntry { @@ -227,11 +247,11 @@ class IdmapData { return target_inline_entries_; } - const std::vector<OverlayEntry>& GetOverlayEntries() const { + [[nodiscard]] const std::vector<OverlayEntry>& GetOverlayEntries() const { return overlay_entries_; } - const std::string& GetStringPoolData() const { + [[nodiscard]] const std::string& GetStringPoolData() const { return string_pool_data_; } diff --git a/cmds/idmap2/include/idmap2/ResourceMapping.h b/cmds/idmap2/include/idmap2/ResourceMapping.h index 21862a3635d5..4bad2fa392a2 100644 --- a/cmds/idmap2/include/idmap2/ResourceMapping.h +++ b/cmds/idmap2/include/idmap2/ResourceMapping.h @@ -33,7 +33,8 @@ using PolicyBitmask = android::ResTable_overlayable_policy_header::PolicyBitmask; namespace android::idmap2 { -using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, TargetValue>>; +using ConfigMap = std::unordered_map<std::string, TargetValue>; +using TargetResourceMap = std::map<ResourceId, std::variant<ResourceId, ConfigMap>>; using OverlayResourceMap = std::map<ResourceId, ResourceId>; class ResourceMapping { diff --git a/cmds/idmap2/include/idmap2/ResourceUtils.h b/cmds/idmap2/include/idmap2/ResourceUtils.h index 8ec749602c4a..af4dd8960cc3 100644 --- a/cmds/idmap2/include/idmap2/ResourceUtils.h +++ b/cmds/idmap2/include/idmap2/ResourceUtils.h @@ -46,6 +46,10 @@ struct TargetValue { struct TargetValueWithConfig { TargetValue value; std::string config; + + [[nodiscard]] std::pair<std::string, TargetValue> to_pair() const { + return std::make_pair(config, value); + } }; namespace utils { diff --git a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp index 3bbe9d91deb6..4b271a1ff96f 100644 --- a/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp +++ b/cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp @@ -70,12 +70,35 @@ void BinaryStreamVisitor::visit(const IdmapData& data) { } static constexpr uint16_t kValueSize = 8U; + std::vector<std::pair<ConfigDescription, TargetValue>> target_values; + target_values.reserve(data.GetHeader()->GetTargetInlineEntryValueCount()); for (const auto& target_entry : data.GetTargetInlineEntries()) { Write32(target_entry.target_id); + Write32(target_values.size()); + Write32(target_entry.values.size()); + target_values.insert( + target_values.end(), target_entry.values.begin(), target_entry.values.end()); + } + + std::vector<ConfigDescription> configs; + configs.reserve(data.GetHeader()->GetConfigCount()); + for (const auto& target_entry_value : target_values) { + auto config_it = find(configs.begin(), configs.end(), target_entry_value.first); + if (config_it != configs.end()) { + Write32(config_it - configs.begin()); + } else { + Write32(configs.size()); + configs.push_back(target_entry_value.first); + } Write16(kValueSize); Write8(0U); // padding - Write8(target_entry.value.data_type); - Write32(target_entry.value.data_value); + Write8(target_entry_value.second.data_type); + Write32(target_entry_value.second.data_value); + } + + for( auto& cd : configs) { + cd.swapHtoD(); + stream_.write(reinterpret_cast<char*>(&cd), sizeof(cd)); } for (const auto& overlay_entry : data.GetOverlayEntries()) { @@ -89,6 +112,8 @@ void BinaryStreamVisitor::visit(const IdmapData& data) { void BinaryStreamVisitor::visit(const IdmapData::Header& header) { Write32(header.GetTargetEntryCount()); Write32(header.GetTargetInlineEntryCount()); + Write32(header.GetTargetInlineEntryValueCount()); + Write32(header.GetConfigCount()); Write32(header.GetOverlayEntryCount()); Write32(header.GetStringPoolIndexOffset()); } diff --git a/cmds/idmap2/libidmap2/Idmap.cpp b/cmds/idmap2/libidmap2/Idmap.cpp index 06650f681b24..4efaeea74274 100644 --- a/cmds/idmap2/libidmap2/Idmap.cpp +++ b/cmds/idmap2/libidmap2/Idmap.cpp @@ -186,6 +186,8 @@ std::unique_ptr<const IdmapData::Header> IdmapData::Header::FromBinaryStream(std std::unique_ptr<IdmapData::Header> idmap_data_header(new IdmapData::Header()); if (!Read32(stream, &idmap_data_header->target_entry_count) || !Read32(stream, &idmap_data_header->target_entry_inline_count) || + !Read32(stream, &idmap_data_header->target_entry_inline_value_count) || + !Read32(stream, &idmap_data_header->config_count) || !Read32(stream, &idmap_data_header->overlay_entry_count) || !Read32(stream, &idmap_data_header->string_pool_index_offset)) { return nullptr; @@ -207,20 +209,59 @@ std::unique_ptr<const IdmapData> IdmapData::FromBinaryStream(std::istream& strea if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &target_entry.overlay_id)) { return nullptr; } - data->target_entries_.push_back(target_entry); + data->target_entries_.emplace_back(target_entry); } // Read the mapping of target resource id to inline overlay values. - uint8_t unused1; - uint16_t unused2; + std::vector<std::tuple<TargetInlineEntry, uint32_t, uint32_t>> target_inline_entries; for (size_t i = 0; i < data->header_->GetTargetInlineEntryCount(); i++) { TargetInlineEntry target_entry{}; - if (!Read32(stream, &target_entry.target_id) || !Read16(stream, &unused2) || - !Read8(stream, &unused1) || !Read8(stream, &target_entry.value.data_type) || - !Read32(stream, &target_entry.value.data_value)) { + uint32_t entry_offset; + uint32_t entry_count; + if (!Read32(stream, &target_entry.target_id) || !Read32(stream, &entry_offset) + || !Read32(stream, &entry_count)) { return nullptr; } - data->target_inline_entries_.push_back(target_entry); + target_inline_entries.emplace_back(std::make_tuple(target_entry, entry_offset, entry_count)); + } + + // Read the inline overlay resource values + std::vector<std::pair<uint32_t, TargetValue>> target_values; + uint8_t unused1; + uint16_t unused2; + for (size_t i = 0; i < data->header_->GetTargetInlineEntryValueCount(); i++) { + uint32_t config_index; + if (!Read32(stream, &config_index)) { + return nullptr; + } + TargetValue value; + if (!Read16(stream, &unused2) + || !Read8(stream, &unused1) + || !Read8(stream, &value.data_type) + || !Read32(stream, &value.data_value)) { + return nullptr; + } + target_values.emplace_back(std::make_pair(config_index, value)); + } + + // Read the configurations + std::vector<ConfigDescription> configurations; + for (size_t i = 0; i < data->header_->GetConfigCount(); i++) { + ConfigDescription cd; + if (!stream.read(reinterpret_cast<char*>(&cd), sizeof(ConfigDescription))) { + return nullptr; + } + configurations.emplace_back(cd); + } + + // Construct complete target inline entries + for (auto [target_entry, entry_offset, entry_count] : target_inline_entries) { + for(size_t i = 0; i < entry_count; i++) { + const auto& target_value = target_values[entry_offset + i]; + const auto& config = configurations[target_value.first]; + target_entry.values[config] = target_value.second; + } + data->target_inline_entries_.emplace_back(target_entry); } // Read the mapping of overlay resource id to target resource id. @@ -278,12 +319,21 @@ Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping( std::unique_ptr<IdmapData> data(new IdmapData()); data->string_pool_data_ = resource_mapping.GetStringPoolData().to_string(); + uint32_t inline_value_count = 0; + std::set<std::string> config_set; for (const auto& mapping : resource_mapping.GetTargetToOverlayMap()) { if (auto overlay_resource = std::get_if<ResourceId>(&mapping.second)) { data->target_entries_.push_back({mapping.first, *overlay_resource}); } else { - data->target_inline_entries_.push_back( - {mapping.first, std::get<TargetValue>(mapping.second)}); + std::map<ConfigDescription, TargetValue> values; + for (const auto& [config, value] : std::get<ConfigMap>(mapping.second)) { + config_set.insert(config); + ConfigDescription cd; + ConfigDescription::Parse(config, &cd); + values[cd] = value; + inline_value_count++; + } + data->target_inline_entries_.push_back({mapping.first, values}); } } @@ -295,6 +345,8 @@ Result<std::unique_ptr<const IdmapData>> IdmapData::FromResourceMapping( data_header->target_entry_count = static_cast<uint32_t>(data->target_entries_.size()); data_header->target_entry_inline_count = static_cast<uint32_t>(data->target_inline_entries_.size()); + data_header->target_entry_inline_value_count = inline_value_count; + data_header->config_count = config_set.size(); data_header->overlay_entry_count = static_cast<uint32_t>(data->overlay_entries_.size()); data_header->string_pool_index_offset = resource_mapping.GetStringPoolOffset(); data->header_ = std::move(data_header); diff --git a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp index d10a2785aaba..a44fa756aa1c 100644 --- a/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/PrettyPrintVisitor.cpp @@ -94,14 +94,17 @@ void PrettyPrintVisitor::visit(const IdmapData& data) { } for (auto& target_entry : data.GetTargetInlineEntries()) { - stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id) - << utils::DataTypeToString(target_entry.value.data_type); - - if (target_entry.value.data_type == Res_value::TYPE_STRING) { - auto str = string_pool.stringAt(target_entry.value.data_value - string_pool_offset); - stream_ << " \"" << str.value_or(StringPiece16(u"")) << "\""; - } else { - stream_ << " " << base::StringPrintf("0x%08x", target_entry.value.data_value); + for(auto iter = target_entry.values.begin(); iter != target_entry.values.end(); ++iter) { + auto value = iter->second; + stream_ << TAB << base::StringPrintf("0x%08x -> ", target_entry.target_id) + << utils::DataTypeToString(value.data_type); + + if (value.data_type == Res_value::TYPE_STRING) { + auto str = string_pool.stringAt(value.data_value - string_pool_offset); + stream_ << " \"" << str.value_or(StringPiece16(u"")) << "\""; + } else { + stream_ << " " << base::StringPrintf("0x%08x", value.data_value); + } } std::string target_name = kUnknownResourceName; diff --git a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp index 779538c617f4..3531cd7c2f36 100644 --- a/cmds/idmap2/libidmap2/RawPrintVisitor.cpp +++ b/cmds/idmap2/libidmap2/RawPrintVisitor.cpp @@ -89,22 +89,30 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { print(target_entry.target_id, "target id"); } + pad(sizeof(Res_value::size) + sizeof(Res_value::res0)); - print(target_entry.value.data_type, "type: %s", - utils::DataTypeToString(target_entry.value.data_type).data()); + for (auto& target_entry_value : target_entry.values) { + auto value = target_entry_value.second; - Result<std::string> overlay_name(Error("")); - if (overlay_ != nullptr && - (target_entry.value.data_value == Res_value::TYPE_REFERENCE || - target_entry.value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) { - overlay_name = overlay_->GetResourceName(target_entry.value.data_value); - } + print(target_entry_value.first.to_string(), false, "config: %s", + target_entry_value.first.toString().string()); - if (overlay_name) { - print(target_entry.value.data_value, "data: %s", overlay_name->c_str()); - } else { - print(target_entry.value.data_value, "data"); + print(value.data_type, "type: %s", + utils::DataTypeToString(value.data_type).data()); + + Result<std::string> overlay_name(Error("")); + if (overlay_ != nullptr && + (value.data_value == Res_value::TYPE_REFERENCE || + value.data_value == Res_value::TYPE_DYNAMIC_REFERENCE)) { + overlay_name = overlay_->GetResourceName(value.data_value); + } + + if (overlay_name) { + print(value.data_value, "data: %s", overlay_name->c_str()); + } else { + print(value.data_value, "data"); + } } } @@ -138,6 +146,8 @@ void RawPrintVisitor::visit(const IdmapData& data ATTRIBUTE_UNUSED) { void RawPrintVisitor::visit(const IdmapData::Header& header) { print(header.GetTargetEntryCount(), "target entry count"); print(header.GetTargetInlineEntryCount(), "target inline entry count"); + print(header.GetTargetInlineEntryValueCount(), "target inline entry value count"); + print(header.GetConfigCount(), "config count"); print(header.GetOverlayEntryCount(), "overlay entry count"); print(header.GetStringPoolIndexOffset(), "string pool index offset"); } diff --git a/cmds/idmap2/libidmap2/ResourceMapping.cpp b/cmds/idmap2/libidmap2/ResourceMapping.cpp index 8ebe5aa46e73..bb31c11d629c 100644 --- a/cmds/idmap2/libidmap2/ResourceMapping.cpp +++ b/cmds/idmap2/libidmap2/ResourceMapping.cpp @@ -161,14 +161,13 @@ Result<ResourceMapping> ResourceMapping::FromContainers(const TargetResourceCont Result<Unit> ResourceMapping::AddMapping( ResourceId target_resource, const std::variant<OverlayData::ResourceIdValue, TargetValueWithConfig>& value) { - if (target_map_.find(target_resource) != target_map_.end()) { - return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); - } - // TODO(141485591): Ensure that the overlay type is compatible with the target type. If the // runtime types are not compatible, it could cause runtime crashes when the resource is resolved. if (auto overlay_resource = std::get_if<OverlayData::ResourceIdValue>(&value)) { + if (target_map_.find(target_resource) != target_map_.end()) { + return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); + } target_map_.insert(std::make_pair(target_resource, overlay_resource->overlay_id)); if (overlay_resource->rewrite_id) { // An overlay resource can override multiple target resources at once. Rewrite the overlay @@ -176,8 +175,18 @@ Result<Unit> ResourceMapping::AddMapping( overlay_map_.insert(std::make_pair(overlay_resource->overlay_id, target_resource)); } } else { - auto overlay_value = std::get<TargetValueWithConfig>(value); - target_map_.insert(std::make_pair(target_resource, overlay_value.value)); + auto[iter, inserted] = target_map_.try_emplace(target_resource, ConfigMap()); + auto& resource_value = iter->second; + if (!inserted && std::holds_alternative<ResourceId>(resource_value)) { + return Error(R"(target resource id "0x%08x" mapped to multiple values)", target_resource); + } + auto& config_map = std::get<ConfigMap>(resource_value); + const auto& config_value = std::get<TargetValueWithConfig>(value); + if (config_map.find(config_value.config) != config_map.end()) { + return Error(R"(target resource id "0x%08x" mapped to multiple values with the same config)", + target_resource); + } + config_map.insert(config_value.to_pair()); } return Unit{}; diff --git a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp index bf6332742787..f1eeab9c803b 100644 --- a/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp +++ b/cmds/idmap2/tests/BinaryStreamVisitorTests.cpp @@ -84,8 +84,10 @@ TEST(BinaryStreamVisitorTests, CreateBinaryStreamViaBinaryStreamVisitor) { const auto& target_inline_entries2 = data2->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries1.size(), target_inline_entries2.size()); ASSERT_EQ(target_inline_entries1[0].target_id, target_inline_entries2[0].target_id); - ASSERT_EQ(target_inline_entries1[0].value.data_type, target_inline_entries2[0].value.data_type); - ASSERT_EQ(target_inline_entries1[0].value.data_value, target_inline_entries2[0].value.data_value); + ASSERT_EQ(target_inline_entries1[0].values.begin()->second.data_type, + target_inline_entries2[0].values.begin()->second.data_type); + ASSERT_EQ(target_inline_entries1[0].values.begin()->second.data_value, + target_inline_entries2[0].values.begin()->second.data_value); const auto& overlay_entries1 = data1->GetOverlayEntries(); const auto& overlay_entries2 = data2->GetOverlayEntries(); diff --git a/cmds/idmap2/tests/IdmapTests.cpp b/cmds/idmap2/tests/IdmapTests.cpp index ee9a424b3050..7b7dc17deea4 100644 --- a/cmds/idmap2/tests/IdmapTests.cpp +++ b/cmds/idmap2/tests/IdmapTests.cpp @@ -47,10 +47,11 @@ namespace android::idmap2 { ASSERT_EQ((entry).target_id, (target_resid)); \ ASSERT_EQ((entry).overlay_id, (overlay_resid)) -#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, expected_type, expected_value) \ - ASSERT_EQ((entry).target_id, target_resid); \ - ASSERT_EQ((entry).value.data_type, (expected_type)); \ - ASSERT_EQ((entry).value.data_value, (expected_value)) +#define ASSERT_TARGET_INLINE_ENTRY(entry, target_resid, ex_config, expected_type, expected_value) \ + ASSERT_EQ((entry).target_id, target_resid); \ + ASSERT_EQ((entry).values.begin()->first.to_string(), (ex_config)); \ + ASSERT_EQ((entry).values.begin()->second.data_type, (expected_type)); \ + ASSERT_EQ((entry).values.begin()->second.data_value, (expected_value)) #define ASSERT_OVERLAY_ENTRY(entry, overlay_resid, target_resid) \ ASSERT_EQ((entry).overlay_id, (overlay_resid)); \ @@ -67,7 +68,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromBinaryStream) { std::unique_ptr<const IdmapHeader> header = IdmapHeader::FromBinaryStream(stream); ASSERT_THAT(header, NotNull()); ASSERT_EQ(header->GetMagic(), 0x504d4449U); - ASSERT_EQ(header->GetVersion(), 0x08U); + ASSERT_EQ(header->GetVersion(), 0x09U); ASSERT_EQ(header->GetTargetCrc(), 0x1234U); ASSERT_EQ(header->GetOverlayCrc(), 0x5678U); ASSERT_EQ(header->GetFulfilledPolicies(), 0x11); @@ -122,8 +123,8 @@ TEST(IdmapTests, CreateIdmapDataFromBinaryStream) { const auto& target_inline_entries = data->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries.size(), 1U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX, - 0x12345678); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, "land-xxhdpi-v7", + Res_value::TYPE_INT_HEX, 0x12345678); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 3U); @@ -142,7 +143,7 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x09U); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), 0x1234U); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), 0x5678U); ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), kIdmapRawDataPolicies); @@ -165,8 +166,8 @@ TEST(IdmapTests, CreateIdmapFromBinaryStream) { const auto& target_inline_entries = data->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries.size(), 1U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, Res_value::TYPE_INT_HEX, - 0x12345678); + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], 0x7f040000, "land-xxhdpi-v7", + Res_value::TYPE_INT_HEX, 0x12345678); const auto& overlay_entries = data->GetOverlayEntries(); ASSERT_EQ(target_entries.size(), 3U); @@ -203,7 +204,7 @@ TEST(IdmapTests, CreateIdmapHeaderFromApkAssets) { ASSERT_THAT(idmap->GetHeader(), NotNull()); ASSERT_EQ(idmap->GetHeader()->GetMagic(), 0x504d4449U); - ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x08U); + ASSERT_EQ(idmap->GetHeader()->GetVersion(), 0x09U); ASSERT_EQ(idmap->GetHeader()->GetTargetCrc(), android::idmap2::TestConstants::TARGET_CRC); ASSERT_EQ(idmap->GetHeader()->GetOverlayCrc(), android::idmap2::TestConstants::OVERLAY_CRC); ASSERT_EQ(idmap->GetHeader()->GetFulfilledPolicies(), PolicyFlags::PUBLIC); @@ -261,9 +262,9 @@ TEST(IdmapTests, FabricatedOverlay) { auto frro = FabricatedOverlay::Builder("com.example.overlay", "SandTheme", "test.target") .SetOverlayable("TestResources") - .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "") - .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "") - .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "") + .SetResourceValue("integer/int1", Res_value::TYPE_INT_DEC, 2U, "land-xxhdpi-v7") + .SetResourceValue("string/str1", Res_value::TYPE_REFERENCE, 0x7f010000, "land") + .SetResourceValue("string/str2", Res_value::TYPE_STRING, "foobar", "xxhdpi-v7") .Build(); ASSERT_TRUE(frro); @@ -295,11 +296,11 @@ TEST(IdmapTests, FabricatedOverlay) { const auto& target_inline_entries = data->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries.size(), 3U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, "land-xxhdpi-v7", Res_value::TYPE_INT_DEC, 2U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, "land", Res_value::TYPE_REFERENCE, 0x7f010000); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[2], R::target::string::str2, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[2], R::target::string::str2, "xxhdpi-v7", Res_value::TYPE_STRING, (uint32_t) (string_pool.indexOfString(u"foobar", 6)).value_or(-1)); } @@ -442,9 +443,9 @@ TEST(IdmapTests, CreateIdmapDataInlineResources) { constexpr size_t overlay_string_pool_size = 10U; const auto& target_inline_entries = data->GetTargetInlineEntries(); ASSERT_EQ(target_inline_entries.size(), 2U); - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[0], R::target::integer::int1, std::string(), Res_value::TYPE_INT_DEC, 73U); // -> 73 - ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, + ASSERT_TARGET_INLINE_ENTRY(target_inline_entries[1], R::target::string::str1, std::string(), Res_value::TYPE_STRING, overlay_string_pool_size + 0U); // -> "Hello World" diff --git a/cmds/idmap2/tests/RawPrintVisitorTests.cpp b/cmds/idmap2/tests/RawPrintVisitorTests.cpp index a6371cb74f2e..7112eeb9ea0c 100644 --- a/cmds/idmap2/tests/RawPrintVisitorTests.cpp +++ b/cmds/idmap2/tests/RawPrintVisitorTests.cpp @@ -64,7 +64,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000009 version\n", stream.str()); ASSERT_CONTAINS_REGEX( StringPrintf(ADDRESS "%s target crc\n", android::idmap2::TestConstants::TARGET_CRC_STRING), stream.str()); @@ -75,6 +75,8 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitor) { ASSERT_CONTAINS_REGEX(ADDRESS "00000001 enforce overlayable\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 target entry count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000000 target inline entry count", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000000 target inline entry value count", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000000 config count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 overlay entry count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "0000000a string pool index offset", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f010000 target id: integer/int1", stream.str()); @@ -111,7 +113,7 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { (*idmap)->accept(&visitor); ASSERT_CONTAINS_REGEX(ADDRESS "504d4449 magic\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "00000008 version\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000009 version\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00001234 target crc\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00005678 overlay crc\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000011 fulfilled policies: public|signature\n", stream.str()); @@ -124,17 +126,25 @@ TEST(RawPrintVisitorTests, CreateRawPrintVisitorWithoutAccessToApks) { ASSERT_CONTAINS_REGEX(ADDRESS "........ overlay name: OverlayName\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000003 target entry count\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry count\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000001 target inline entry value count", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "00000001 config count", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000003 overlay entry count\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000000 string pool index offset\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str()); - ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030000 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030000 overlay id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f030001 overlay id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "7f040000 target id\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "0000000e config: land-xxhdpi-v7 size\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "........ config: land-xxhdpi-v7\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS " 11 type: integer\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "12345678 data\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f020000 overlay id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "7f030002 target id\n", stream.str()); ASSERT_CONTAINS_REGEX(ADDRESS "00000004 string pool size\n", stream.str()); - ASSERT_CONTAINS_REGEX("000000a4: ........ string pool\n", stream.str()); + ASSERT_CONTAINS_REGEX(ADDRESS "........ string pool\n", stream.str()); } } // namespace android::idmap2 diff --git a/cmds/idmap2/tests/ResourceMappingTests.cpp b/cmds/idmap2/tests/ResourceMappingTests.cpp index ca9a444bcb05..016d427e7452 100644 --- a/cmds/idmap2/tests/ResourceMappingTests.cpp +++ b/cmds/idmap2/tests/ResourceMappingTests.cpp @@ -111,19 +111,20 @@ Result<Unit> MappingExists(const ResourceMapping& mapping, const ResourceId& tar return Error("Failed to find mapping for target resource"); } - auto actual_overlay_value = std::get_if<TargetValue>(&entry_map->second); - if (actual_overlay_value == nullptr) { + auto config_map = std::get_if<ConfigMap>(&entry_map->second); + if (config_map == nullptr || config_map->empty()) { return Error("Target resource is not mapped to an inline value"); } + auto actual_overlay_value = config_map->begin()->second; - if (actual_overlay_value->data_type != type) { + if (actual_overlay_value.data_type != type) { return Error(R"(Expected type: "0x%02x" Actual type: "0x%02x")", type, - actual_overlay_value->data_type); + actual_overlay_value.data_type); } - if (actual_overlay_value->data_value != value) { + if (actual_overlay_value.data_value != value) { return Error(R"(Expected value: "0x%08x" Actual value: "0x%08x")", type, - actual_overlay_value->data_value); + actual_overlay_value.data_value); } return Result<Unit>({}); diff --git a/cmds/idmap2/tests/TestHelpers.h b/cmds/idmap2/tests/TestHelpers.h index 6b5f3a8a98eb..45740e2d5a9e 100644 --- a/cmds/idmap2/tests/TestHelpers.h +++ b/cmds/idmap2/tests/TestHelpers.h @@ -30,7 +30,7 @@ const unsigned char kIdmapRawData[] = { 0x49, 0x44, 0x4d, 0x50, // 0x4: version - 0x08, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, // 0x8: target crc 0x34, 0x12, 0x00, 0x00, @@ -76,66 +76,123 @@ const unsigned char kIdmapRawData[] = { // 0x58: target_inline_entry_count 0x01, 0x00, 0x00, 0x00, - // 0x5c: overlay_entry_count + // 0x5c: target_inline_entry_value_count + 0x01, 0x00, 0x00, 0x00, + + // 0x60: config_count + 0x01, 0x00, 0x00, 0x00, + + // 0x64: overlay_entry_count 0x03, 0x00, 0x00, 0x00, - // 0x60: string_pool_offset + // 0x68: string_pool_offset 0x00, 0x00, 0x00, 0x00, // TARGET ENTRIES - // 0x64: target id (0x7f020000) + // 0x6c: target id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x68: overlay_id (0x7f020000) + // 0x70: overlay_id (0x7f020000) 0x00, 0x00, 0x02, 0x7f, - // 0x6c: target id (0x7f030000) + // 0x74: target id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x70: overlay_id (0x7f030000) + // 0x78: overlay_id (0x7f030000) 0x00, 0x00, 0x03, 0x7f, - // 0x74: target id (0x7f030002) + // 0x7c: target id (0x7f030002) 0x02, 0x00, 0x03, 0x7f, - // 0x78: overlay_id (0x7f030001) + // 0x80: overlay_id (0x7f030001) 0x01, 0x00, 0x03, 0x7f, // INLINE TARGET ENTRIES - // 0x7c: target_id + // 0x84: target_id 0x00, 0x00, 0x04, 0x7f, - // 0x80: Res_value::size (value ignored by idmap) + // 0x88: start value index + 0x00, 0x00, 0x00, 0x00, + + // 0x8c: value count + 0x01, 0x00, 0x00, 0x00, + + // INLINE TARGET ENTRY VALUES + + // 0x90: config index + 0x00, 0x00, 0x00, 0x00, + + // 0x94: Res_value::size (value ignored by idmap) 0x08, 0x00, - // 0x82: Res_value::res0 (value ignored by idmap) + // 0x98: Res_value::res0 (value ignored by idmap) 0x00, - // 0x83: Res_value::dataType (TYPE_INT_HEX) + // 0x9c: Res_value::dataType (TYPE_INT_HEX) 0x11, - // 0x84: Res_value::data + // 0xa0: Res_value::data 0x78, 0x56, 0x34, 0x12, + // CONFIGURATIONS + + // 0xa4: ConfigDescription + // size + 0x40, 0x00, 0x00, 0x00, + // 0xa8: imsi + 0x00, 0x00, 0x00, 0x00, + // 0xac: locale + 0x00, 0x00, 0x00, 0x00, + // 0xb0: screenType + 0x02, 0x00, 0xe0, 0x01, + // 0xb4: input + 0x00, 0x00, 0x00, 0x00, + // 0xb8: screenSize + 0x00, 0x00, 0x00, 0x00, + // 0xbc: version + 0x07, 0x00, 0x00, 0x00, + // 0xc0: screenConfig + 0x00, 0x00, 0x00, 0x00, + // 0xc4: screenSizeDp + 0x00, 0x00, 0x00, 0x00, + // 0xc8: localeScript + 0x00, 0x00, 0x00, 0x00, + // 0xcc: localVariant(1) + 0x00, 0x00, 0x00, 0x00, + // 0xd0: localVariant(2) + 0x00, 0x00, 0x00, 0x00, + // 0xd4: screenConfig2 + 0x00, 0x00, 0x00, 0x00, + // 0xd8: localeScriptWasComputed + 0x00, + // 0xd9: localeNumberingSystem(1) + 0x00, 0x00, 0x00, 0x00, + // 0xdd: localeNumberingSystem(2) + 0x00, 0x00, 0x00, 0x00, + + // 0xe1: padding + 0x00, 0x00, 0x00, + + // OVERLAY ENTRIES - // 0x88: 0x7f020000 -> 0x7f020000 + // 0xe4: 0x7f020000 -> 0x7f020000 0x00, 0x00, 0x02, 0x7f, 0x00, 0x00, 0x02, 0x7f, - // 0x90: 0x7f030000 -> 0x7f030000 + // 0xec: 0x7f030000 -> 0x7f030000 0x00, 0x00, 0x03, 0x7f, 0x00, 0x00, 0x03, 0x7f, - // 0x98: 0x7f030001 -> 0x7f030002 + // 0xf4: 0x7f030001 -> 0x7f030002 0x01, 0x00, 0x03, 0x7f, 0x02, 0x00, 0x03, 0x7f, - // 0xa0: string pool + // 0xfc: string pool // string length, 0x04, 0x00, 0x00, 0x00, - // 0xa4 string contents "test" + // 0x100 string contents "test" 0x74, 0x65, 0x73, 0x74}; -const unsigned int kIdmapRawDataLen = 0xa8; +const unsigned int kIdmapRawDataLen = 0x104; const unsigned int kIdmapRawDataOffset = 0x54; const unsigned int kIdmapRawDataTargetCrc = 0x1234; const unsigned int kIdmapRawOverlayCrc = 0x5678; diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 39c7d198fe5b..235700b27c25 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -601,10 +601,6 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( return base::unexpected(result.error()); } - if (type_idx == 0x1c) { - LOG(ERROR) << base::StringPrintf("foobar first result %s", result->package_name->c_str()); - } - bool overlaid = false; if (!stop_at_first_match && !ignore_configuration && !apk_assets_[result->cookie]->IsLoader()) { for (const auto& id_map : package_group.overlays_) { @@ -615,7 +611,21 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( } if (overlay_entry.IsInlineValue()) { // The target resource is overlaid by an inline value not represented by a resource. - result->entry = overlay_entry.GetInlineValue(); + ConfigDescription best_frro_config; + Res_value best_frro_value; + bool frro_found = false; + for( const auto& [config, value] : overlay_entry.GetInlineValue()) { + if ((!frro_found || config.isBetterThan(best_frro_config, desired_config)) + && config.match(*desired_config)) { + frro_found = true; + best_frro_config = config; + best_frro_value = value; + } + } + if (!frro_found) { + continue; + } + result->entry = best_frro_value; result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable(); result->cookie = id_map.cookie; diff --git a/libs/androidfw/Idmap.cpp b/libs/androidfw/Idmap.cpp index efd1f6a25786..e122d4844ee9 100644 --- a/libs/androidfw/Idmap.cpp +++ b/libs/androidfw/Idmap.cpp @@ -56,6 +56,8 @@ struct Idmap_header { struct Idmap_data_header { uint32_t target_entry_count; uint32_t target_inline_entry_count; + uint32_t target_inline_entry_value_count; + uint32_t configuration_count; uint32_t overlay_entry_count; uint32_t string_pool_index_offset; @@ -68,6 +70,12 @@ struct Idmap_target_entry { struct Idmap_target_entry_inline { uint32_t target_id; + uint32_t start_value_index; + uint32_t value_count; +}; + +struct Idmap_target_entry_inline_value { + uint32_t config_index; Res_value value; }; @@ -138,11 +146,15 @@ status_t OverlayDynamicRefTable::lookupResourceIdNoRewrite(uint32_t* resId) cons IdmapResMap::IdmapResMap(const Idmap_data_header* data_header, const Idmap_target_entry* entries, const Idmap_target_entry_inline* inline_entries, + const Idmap_target_entry_inline_value* inline_entry_values, + const ConfigDescription* configs, uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) : data_header_(data_header), entries_(entries), inline_entries_(inline_entries), + inline_entry_values_(inline_entry_values), + configurations_(configs), target_assigned_package_id_(target_assigned_package_id), overlay_ref_table_(overlay_ref_table) { } @@ -183,7 +195,13 @@ IdmapResMap::Result IdmapResMap::Lookup(uint32_t target_res_id) const { if (inline_entry != end_inline_entry && (0x00FFFFFFU & dtohl(inline_entry->target_id)) == target_res_id) { - return Result(inline_entry->value); + std::map<ConfigDescription, Res_value> values_map; + for (int i = 0; i < inline_entry->value_count; i++) { + const auto& value = inline_entry_values_[inline_entry->start_value_index + i]; + const auto& config = configurations_[value.config_index]; + values_map[config] = value.value; + } + return Result(values_map); } return {}; } @@ -237,6 +255,8 @@ LoadedIdmap::LoadedIdmap(std::string&& idmap_path, const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, const Idmap_target_entry_inline* target_inline_entries, + const Idmap_target_entry_inline_value* inline_entry_values, + const ConfigDescription* configs, const Idmap_overlay_entry* overlay_entries, std::unique_ptr<ResStringPool>&& string_pool, std::string_view overlay_apk_path, @@ -245,6 +265,8 @@ LoadedIdmap::LoadedIdmap(std::string&& idmap_path, data_header_(data_header), target_entries_(target_entries), target_inline_entries_(target_inline_entries), + inline_entry_values_(inline_entry_values), + configurations_(configs), overlay_entries_(overlay_entries), string_pool_(std::move(string_pool)), idmap_path_(std::move(idmap_path)), @@ -303,6 +325,21 @@ std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path, if (target_inline_entries == nullptr) { return {}; } + + auto target_inline_entry_values = ReadType<Idmap_target_entry_inline_value>( + &data_ptr, &data_size, "target inline values", + dtohl(data_header->target_inline_entry_value_count)); + if (target_inline_entry_values == nullptr) { + return {}; + } + + auto configurations = ReadType<ConfigDescription>( + &data_ptr, &data_size, "configurations", + dtohl(data_header->configuration_count)); + if (configurations == nullptr) { + return {}; + } + auto overlay_entries = ReadType<Idmap_overlay_entry>(&data_ptr, &data_size, "target inline", dtohl(data_header->overlay_entry_count)); if (overlay_entries == nullptr) { @@ -329,8 +366,8 @@ std::unique_ptr<LoadedIdmap> LoadedIdmap::Load(const StringPiece& idmap_path, // Can't use make_unique because LoadedIdmap constructor is private. return std::unique_ptr<LoadedIdmap>( new LoadedIdmap(idmap_path.to_string(), header, data_header, target_entries, - target_inline_entries, overlay_entries, std::move(idmap_string_pool), - *target_path, *overlay_path)); + target_inline_entries, target_inline_entry_values, configurations, + overlay_entries, std::move(idmap_string_pool), *target_path, *overlay_path)); } bool LoadedIdmap::IsUpToDate() const { diff --git a/libs/androidfw/include/androidfw/Idmap.h b/libs/androidfw/include/androidfw/Idmap.h index 6804472b3d17..a1cbbbf2271b 100644 --- a/libs/androidfw/include/androidfw/Idmap.h +++ b/libs/androidfw/include/androidfw/Idmap.h @@ -23,6 +23,7 @@ #include <variant> #include "android-base/macros.h" +#include "androidfw/ConfigDescription.h" #include "androidfw/StringPiece.h" #include "androidfw/ResourceTypes.h" #include "utils/ByteOrder.h" @@ -35,6 +36,7 @@ struct Idmap_header; struct Idmap_data_header; struct Idmap_target_entry; struct Idmap_target_entry_inline; +struct Idmap_target_entry_inline_value; struct Idmap_overlay_entry; // A string pool for overlay apk assets. The string pool holds the strings of the overlay resources @@ -91,7 +93,8 @@ class IdmapResMap { public: Result() = default; explicit Result(uint32_t value) : data_(value) {}; - explicit Result(const Res_value& value) : data_(value) { }; + explicit Result(const std::map<ConfigDescription, Res_value> &value) + : data_(value) { }; // Returns `true` if the resource is overlaid. explicit operator bool() const { @@ -107,15 +110,16 @@ class IdmapResMap { } bool IsInlineValue() const { - return std::get_if<Res_value>(&data_) != nullptr; + return std::get_if<2>(&data_) != nullptr; } - const Res_value& GetInlineValue() const { - return std::get<Res_value>(data_); + const std::map<ConfigDescription, Res_value>& GetInlineValue() const { + return std::get<2>(data_); } private: - std::variant<std::monostate, uint32_t, Res_value> data_; + std::variant<std::monostate, uint32_t, + std::map<ConfigDescription, Res_value> > data_; }; // Looks up the value that overlays the target resource id. @@ -129,12 +133,16 @@ class IdmapResMap { explicit IdmapResMap(const Idmap_data_header* data_header, const Idmap_target_entry* entries, const Idmap_target_entry_inline* inline_entries, + const Idmap_target_entry_inline_value* inline_entry_values, + const ConfigDescription* configs, uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table); const Idmap_data_header* data_header_; const Idmap_target_entry* entries_; const Idmap_target_entry_inline* inline_entries_; + const Idmap_target_entry_inline_value* inline_entry_values_; + const ConfigDescription* configurations_; const uint8_t target_assigned_package_id_; const OverlayDynamicRefTable* overlay_ref_table_; @@ -170,8 +178,8 @@ class LoadedIdmap { // Returns a mapping from target resource ids to overlay values. const IdmapResMap GetTargetResourcesMap(uint8_t target_assigned_package_id, const OverlayDynamicRefTable* overlay_ref_table) const { - return IdmapResMap(data_header_, target_entries_, target_inline_entries_, - target_assigned_package_id, overlay_ref_table); + return IdmapResMap(data_header_, target_entries_, target_inline_entries_, inline_entry_values_, + configurations_, target_assigned_package_id, overlay_ref_table); } // Returns a dynamic reference table for a loaded overlay package. @@ -191,6 +199,8 @@ class LoadedIdmap { const Idmap_data_header* data_header_; const Idmap_target_entry* target_entries_; const Idmap_target_entry_inline* target_inline_entries_; + const Idmap_target_entry_inline_value* inline_entry_values_; + const ConfigDescription* configurations_; const Idmap_overlay_entry* overlay_entries_; const std::unique_ptr<ResStringPool> string_pool_; @@ -207,6 +217,8 @@ class LoadedIdmap { const Idmap_data_header* data_header, const Idmap_target_entry* target_entries, const Idmap_target_entry_inline* target_inline_entries, + const Idmap_target_entry_inline_value* inline_entry_values_, + const ConfigDescription* configs, const Idmap_overlay_entry* overlay_entries, std::unique_ptr<ResStringPool>&& string_pool, std::string_view overlay_apk_path, diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 8c614bcf7145..9309091f4124 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -45,7 +45,7 @@ namespace android { constexpr const uint32_t kIdmapMagic = 0x504D4449u; -constexpr const uint32_t kIdmapCurrentVersion = 0x00000008u; +constexpr const uint32_t kIdmapCurrentVersion = 0x00000009u; // This must never change. constexpr const uint32_t kFabricatedOverlayMagic = 0x4f525246; // FRRO (big endian) @@ -1098,7 +1098,7 @@ struct ResTable_config SDKVERSION_ANY = 0 }; - enum { + enum { MINORVERSION_ANY = 0 }; diff --git a/libs/androidfw/tests/data/overlay/overlay.idmap b/libs/androidfw/tests/data/overlay/overlay.idmap Binary files differindex 88eadccb38cf..8e847e81aa31 100644 --- a/libs/androidfw/tests/data/overlay/overlay.idmap +++ b/libs/androidfw/tests/data/overlay/overlay.idmap diff --git a/services/core/java/com/android/server/om/OverlayManagerService.java b/services/core/java/com/android/server/om/OverlayManagerService.java index 715967369ffb..be8647e42539 100644 --- a/services/core/java/com/android/server/om/OverlayManagerService.java +++ b/services/core/java/com/android/server/om/OverlayManagerService.java @@ -1098,6 +1098,7 @@ public final class OverlayManagerService extends SystemService { private void enforceActor(@NonNull OverlayIdentifier overlay, @NonNull String methodName, int realUserId) throws SecurityException { OverlayInfo overlayInfo = mImpl.getOverlayInfo(overlay, realUserId); + if (overlayInfo == null) { throw new IllegalArgumentException("Unable to retrieve overlay information for " + overlay); diff --git a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java index dade7aa09283..6e95cd60ba74 100644 --- a/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java +++ b/services/core/java/com/android/server/om/OverlayManagerServiceImpl.java @@ -519,6 +519,7 @@ final class OverlayManagerServiceImpl { throws OperationFailedException { final OverlayIdentifier overlayIdentifier = new OverlayIdentifier( info.packageName, info.overlayName); + final Set<PackageAndUser> updatedTargets = new ArraySet<>(); OverlayInfo oi = mSettings.getNullableOverlayInfo(overlayIdentifier, userId); if (oi != null) { |