Loading cmds/idmap2/include/idmap2/Idmap.h +58 −38 Original line number Diff line number Diff line Loading @@ -21,12 +21,16 @@ * 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 * Loading @@ -51,6 +55,11 @@ * 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 Loading @@ -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" Loading Loading @@ -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; } Loading @@ -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; Loading @@ -202,7 +222,7 @@ class IdmapData { struct TargetInlineEntry { ResourceId target_id; TargetValue value; std::map<ConfigDescription, TargetValue> values; }; struct OverlayEntry { Loading @@ -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_; } Loading cmds/idmap2/include/idmap2/ResourceMapping.h +2 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading cmds/idmap2/include/idmap2/ResourceUtils.h +4 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp +27 −2 Original line number Diff line number Diff line Loading @@ -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()) { Loading @@ -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()); } Loading cmds/idmap2/libidmap2/Idmap.cpp +61 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } 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; } data->target_inline_entries_.push_back(target_entry); 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. Loading Loading @@ -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}); } } Loading @@ -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); Loading Loading
cmds/idmap2/include/idmap2/Idmap.h +58 −38 Original line number Diff line number Diff line Loading @@ -21,12 +21,16 @@ * 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 * Loading @@ -51,6 +55,11 @@ * 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 Loading @@ -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" Loading Loading @@ -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; } Loading @@ -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; Loading @@ -202,7 +222,7 @@ class IdmapData { struct TargetInlineEntry { ResourceId target_id; TargetValue value; std::map<ConfigDescription, TargetValue> values; }; struct OverlayEntry { Loading @@ -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_; } Loading
cmds/idmap2/include/idmap2/ResourceMapping.h +2 −1 Original line number Diff line number Diff line Loading @@ -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 { Loading
cmds/idmap2/include/idmap2/ResourceUtils.h +4 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading
cmds/idmap2/libidmap2/BinaryStreamVisitor.cpp +27 −2 Original line number Diff line number Diff line Loading @@ -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()) { Loading @@ -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()); } Loading
cmds/idmap2/libidmap2/Idmap.cpp +61 −9 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; } 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; } data->target_inline_entries_.push_back(target_entry); 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. Loading Loading @@ -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}); } } Loading @@ -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); Loading