Loading libs/androidfw/LoadedArsc.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -583,7 +583,65 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, loaded_package->dynamic_package_map_.emplace_back(std::move(package_name), dtohl(entry_iter->packageId)); } } break; case RES_TABLE_OVERLAYABLE_TYPE: { const ResTable_overlayable_header* header = child_chunk.header<ResTable_overlayable_header>(); if (header == nullptr) { LOG(ERROR) << "RES_TABLE_OVERLAYABLE_TYPE too small."; return {}; } // Iterate over the overlayable policy chunks ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size()); while (overlayable_iter.HasNext()) { const Chunk overlayable_child_chunk = overlayable_iter.Next(); switch (overlayable_child_chunk.type()) { case RES_TABLE_OVERLAYABLE_POLICY_TYPE: { const ResTable_overlayable_policy_header* policy_header = overlayable_child_chunk.header<ResTable_overlayable_policy_header>(); if (policy_header == nullptr) { LOG(ERROR) << "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small."; return {}; } if ((overlayable_child_chunk.data_size() / sizeof(ResTable_ref)) < dtohl(policy_header->entry_count)) { LOG(ERROR) << "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small to hold entries."; return {}; } // Retrieve all the ids belonging to this policy std::unordered_set<uint32_t> ids; const auto ids_begin = reinterpret_cast<const ResTable_ref*>(overlayable_child_chunk.data_ptr()); const auto ids_end = ids_begin + dtohl(policy_header->entry_count); for (auto id_iter = ids_begin; id_iter != ids_end; ++id_iter) { ids.insert(dtohl(id_iter->ident)); } // Add the pairing of overlayable properties to resource ids to the package OverlayableInfo overlayable_info; overlayable_info.policy_flags = policy_header->policy_flags; loaded_package->overlayable_infos_.push_back(std::make_pair(overlayable_info, ids)); break; } default: LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } if (overlayable_iter.HadError()) { LOG(ERROR) << StringPrintf("Error parsing RES_TABLE_OVERLAYABLE_POLICY_TYPE: %s", overlayable_iter.GetLastError().c_str()); if (overlayable_iter.HadFatalError()) { return {}; } } } break; default: Loading libs/androidfw/ResourceTypes.cpp +1 −13 Original line number Diff line number Diff line Loading @@ -7076,7 +7076,7 @@ public: } } const auto& getTypeMapping() const { const std::map<uint8_t, std::set<std::pair<uint32_t, uint32_t>>>& getTypeMapping() const { return mTypeMapping->mData; } Loading Loading @@ -7137,9 +7137,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, const PackageGroup* packageGroup = mPackageGroups[0]; // the number of resources overlaid that were not explicitly marked overlayable size_t forcedOverlayCount = 0u; // find the resources that exist in both packages auto typeMapping = std::make_unique<IdmapTypeMapping>(); for (size_t typeIndex = 0; typeIndex < packageGroup->types.size(); ++typeIndex) { Loading Loading @@ -7170,11 +7167,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, continue; } if ((dtohl(typeConfigs->typeSpecFlags[entryIndex]) & ResTable_typeSpec::SPEC_OVERLAYABLE) == 0) { ++forcedOverlayCount; } typeMapping->add(target_resid, overlay_resid); } } Loading Loading @@ -7243,10 +7235,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, typeData += entryCount * 2; } if (forcedOverlayCount > 0) { ALOGW("idmap: overlaid %zu resources not marked overlayable", forcedOverlayCount); } return NO_ERROR; } Loading libs/androidfw/include/androidfw/Chunk.h +3 −1 Original line number Diff line number Diff line Loading @@ -89,8 +89,10 @@ class ChunkIterator { len_(len), last_error_(nullptr) { CHECK(next_chunk_ != nullptr) << "data can't be nullptr"; if (len_ != 0) { VerifyNextChunk(); } } Chunk Next(); inline bool HasNext() const { return !HadError() && len_ != 0; }; Loading libs/androidfw/include/androidfw/LoadedArsc.h +18 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <memory> #include <set> #include <vector> #include <unordered_set> #include "android-base/macros.h" Loading Loading @@ -76,6 +77,10 @@ struct TypeSpec { // TypeSpecPtr is a managed pointer that knows how to delete itself. using TypeSpecPtr = util::unique_cptr<TypeSpec>; struct OverlayableInfo { uint32_t policy_flags; }; class LoadedPackage { public: class iterator { Loading Loading @@ -216,6 +221,18 @@ class LoadedPackage { } } // Retrieve the overlayable properties of the specified resource. If the resource is not // overlayable, this will return a null pointer. const OverlayableInfo* GetOverlayableInfo(uint32_t resid) const { for (const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>& overlayable_info_ids : overlayable_infos_) { if (overlayable_info_ids.second.find(resid) != overlayable_info_ids.second.end()) { return &overlayable_info_ids.first; } } return nullptr; } private: DISALLOW_COPY_AND_ASSIGN(LoadedPackage); Loading @@ -233,6 +250,7 @@ class LoadedPackage { ByteBucketArray<TypeSpecPtr> type_specs_; ByteBucketArray<uint32_t> resource_ids_; std::vector<DynamicPackageEntry> dynamic_package_map_; std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_; }; // Read-only view into a resource table. This class validates all data Loading libs/androidfw/include/androidfw/ResourceTypes.h +46 −5 Original line number Diff line number Diff line Loading @@ -234,7 +234,9 @@ enum { RES_TABLE_PACKAGE_TYPE = 0x0200, RES_TABLE_TYPE_TYPE = 0x0201, RES_TABLE_TYPE_SPEC_TYPE = 0x0202, RES_TABLE_LIBRARY_TYPE = 0x0203 RES_TABLE_LIBRARY_TYPE = 0x0203, RES_TABLE_OVERLAYABLE_TYPE = 0x0204, RES_TABLE_OVERLAYABLE_POLICY_TYPE = 0x0205, }; /** Loading Loading @@ -1354,10 +1356,6 @@ struct ResTable_typeSpec enum : uint32_t { // Additional flag indicating an entry is public. SPEC_PUBLIC = 0x40000000u, // Additional flag indicating an entry is overlayable at runtime. // Added in Android-P. SPEC_OVERLAYABLE = 0x80000000u, }; }; Loading Loading @@ -1607,6 +1605,49 @@ struct ResTable_lib_entry uint16_t packageName[128]; }; /** * Specifies the set of resources that are explicitly allowed to be overlaid by RROs. */ struct ResTable_overlayable_header { struct ResChunk_header header; }; /** * Holds a list of resource ids that are protected from being overlaid by a set of policies. If * the overlay fulfils at least one of the policies, then the overlay can overlay the list of * resources. */ struct ResTable_overlayable_policy_header { struct ResChunk_header header; enum PolicyFlags { // Any overlay can overlay these resources. POLICY_PUBLIC = 0x00000001, // The overlay must reside of the system partition or must have existed on the system partition // before an upgrade to overlay these resources. POLICY_SYSTEM_PARTITION = 0x00000002, // The overlay must reside of the vendor partition or must have existed on the vendor partition // before an upgrade to overlay these resources. POLICY_VENDOR_PARTITION = 0x00000004, // The overlay must reside of the product partition or must have existed on the product // partition before an upgrade to overlay these resources. POLICY_PRODUCT_PARTITION = 0x00000008, // The overlay must reside of the product services partition or must have existed on the product // services partition before an upgrade to overlay these resources. POLICY_PRODUCT_SERVICES_PARTITION = 0x00000010, }; uint32_t policy_flags; // The number of ResTable_ref that follow this header. uint32_t entry_count; }; struct alignas(uint32_t) Idmap_header { // Always 0x504D4449 ('IDMP') uint32_t magic; Loading Loading
libs/androidfw/LoadedArsc.cpp +58 −0 Original line number Diff line number Diff line Loading @@ -583,7 +583,65 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, loaded_package->dynamic_package_map_.emplace_back(std::move(package_name), dtohl(entry_iter->packageId)); } } break; case RES_TABLE_OVERLAYABLE_TYPE: { const ResTable_overlayable_header* header = child_chunk.header<ResTable_overlayable_header>(); if (header == nullptr) { LOG(ERROR) << "RES_TABLE_OVERLAYABLE_TYPE too small."; return {}; } // Iterate over the overlayable policy chunks ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size()); while (overlayable_iter.HasNext()) { const Chunk overlayable_child_chunk = overlayable_iter.Next(); switch (overlayable_child_chunk.type()) { case RES_TABLE_OVERLAYABLE_POLICY_TYPE: { const ResTable_overlayable_policy_header* policy_header = overlayable_child_chunk.header<ResTable_overlayable_policy_header>(); if (policy_header == nullptr) { LOG(ERROR) << "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small."; return {}; } if ((overlayable_child_chunk.data_size() / sizeof(ResTable_ref)) < dtohl(policy_header->entry_count)) { LOG(ERROR) << "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small to hold entries."; return {}; } // Retrieve all the ids belonging to this policy std::unordered_set<uint32_t> ids; const auto ids_begin = reinterpret_cast<const ResTable_ref*>(overlayable_child_chunk.data_ptr()); const auto ids_end = ids_begin + dtohl(policy_header->entry_count); for (auto id_iter = ids_begin; id_iter != ids_end; ++id_iter) { ids.insert(dtohl(id_iter->ident)); } // Add the pairing of overlayable properties to resource ids to the package OverlayableInfo overlayable_info; overlayable_info.policy_flags = policy_header->policy_flags; loaded_package->overlayable_infos_.push_back(std::make_pair(overlayable_info, ids)); break; } default: LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type()); break; } } if (overlayable_iter.HadError()) { LOG(ERROR) << StringPrintf("Error parsing RES_TABLE_OVERLAYABLE_POLICY_TYPE: %s", overlayable_iter.GetLastError().c_str()); if (overlayable_iter.HadFatalError()) { return {}; } } } break; default: Loading
libs/androidfw/ResourceTypes.cpp +1 −13 Original line number Diff line number Diff line Loading @@ -7076,7 +7076,7 @@ public: } } const auto& getTypeMapping() const { const std::map<uint8_t, std::set<std::pair<uint32_t, uint32_t>>>& getTypeMapping() const { return mTypeMapping->mData; } Loading Loading @@ -7137,9 +7137,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, const PackageGroup* packageGroup = mPackageGroups[0]; // the number of resources overlaid that were not explicitly marked overlayable size_t forcedOverlayCount = 0u; // find the resources that exist in both packages auto typeMapping = std::make_unique<IdmapTypeMapping>(); for (size_t typeIndex = 0; typeIndex < packageGroup->types.size(); ++typeIndex) { Loading Loading @@ -7170,11 +7167,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, continue; } if ((dtohl(typeConfigs->typeSpecFlags[entryIndex]) & ResTable_typeSpec::SPEC_OVERLAYABLE) == 0) { ++forcedOverlayCount; } typeMapping->add(target_resid, overlay_resid); } } Loading Loading @@ -7243,10 +7235,6 @@ status_t ResTable::createIdmap(const ResTable& targetResTable, typeData += entryCount * 2; } if (forcedOverlayCount > 0) { ALOGW("idmap: overlaid %zu resources not marked overlayable", forcedOverlayCount); } return NO_ERROR; } Loading
libs/androidfw/include/androidfw/Chunk.h +3 −1 Original line number Diff line number Diff line Loading @@ -89,8 +89,10 @@ class ChunkIterator { len_(len), last_error_(nullptr) { CHECK(next_chunk_ != nullptr) << "data can't be nullptr"; if (len_ != 0) { VerifyNextChunk(); } } Chunk Next(); inline bool HasNext() const { return !HadError() && len_ != 0; }; Loading
libs/androidfw/include/androidfw/LoadedArsc.h +18 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <memory> #include <set> #include <vector> #include <unordered_set> #include "android-base/macros.h" Loading Loading @@ -76,6 +77,10 @@ struct TypeSpec { // TypeSpecPtr is a managed pointer that knows how to delete itself. using TypeSpecPtr = util::unique_cptr<TypeSpec>; struct OverlayableInfo { uint32_t policy_flags; }; class LoadedPackage { public: class iterator { Loading Loading @@ -216,6 +221,18 @@ class LoadedPackage { } } // Retrieve the overlayable properties of the specified resource. If the resource is not // overlayable, this will return a null pointer. const OverlayableInfo* GetOverlayableInfo(uint32_t resid) const { for (const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>& overlayable_info_ids : overlayable_infos_) { if (overlayable_info_ids.second.find(resid) != overlayable_info_ids.second.end()) { return &overlayable_info_ids.first; } } return nullptr; } private: DISALLOW_COPY_AND_ASSIGN(LoadedPackage); Loading @@ -233,6 +250,7 @@ class LoadedPackage { ByteBucketArray<TypeSpecPtr> type_specs_; ByteBucketArray<uint32_t> resource_ids_; std::vector<DynamicPackageEntry> dynamic_package_map_; std::vector<const std::pair<OverlayableInfo, std::unordered_set<uint32_t>>> overlayable_infos_; }; // Read-only view into a resource table. This class validates all data Loading
libs/androidfw/include/androidfw/ResourceTypes.h +46 −5 Original line number Diff line number Diff line Loading @@ -234,7 +234,9 @@ enum { RES_TABLE_PACKAGE_TYPE = 0x0200, RES_TABLE_TYPE_TYPE = 0x0201, RES_TABLE_TYPE_SPEC_TYPE = 0x0202, RES_TABLE_LIBRARY_TYPE = 0x0203 RES_TABLE_LIBRARY_TYPE = 0x0203, RES_TABLE_OVERLAYABLE_TYPE = 0x0204, RES_TABLE_OVERLAYABLE_POLICY_TYPE = 0x0205, }; /** Loading Loading @@ -1354,10 +1356,6 @@ struct ResTable_typeSpec enum : uint32_t { // Additional flag indicating an entry is public. SPEC_PUBLIC = 0x40000000u, // Additional flag indicating an entry is overlayable at runtime. // Added in Android-P. SPEC_OVERLAYABLE = 0x80000000u, }; }; Loading Loading @@ -1607,6 +1605,49 @@ struct ResTable_lib_entry uint16_t packageName[128]; }; /** * Specifies the set of resources that are explicitly allowed to be overlaid by RROs. */ struct ResTable_overlayable_header { struct ResChunk_header header; }; /** * Holds a list of resource ids that are protected from being overlaid by a set of policies. If * the overlay fulfils at least one of the policies, then the overlay can overlay the list of * resources. */ struct ResTable_overlayable_policy_header { struct ResChunk_header header; enum PolicyFlags { // Any overlay can overlay these resources. POLICY_PUBLIC = 0x00000001, // The overlay must reside of the system partition or must have existed on the system partition // before an upgrade to overlay these resources. POLICY_SYSTEM_PARTITION = 0x00000002, // The overlay must reside of the vendor partition or must have existed on the vendor partition // before an upgrade to overlay these resources. POLICY_VENDOR_PARTITION = 0x00000004, // The overlay must reside of the product partition or must have existed on the product // partition before an upgrade to overlay these resources. POLICY_PRODUCT_PARTITION = 0x00000008, // The overlay must reside of the product services partition or must have existed on the product // services partition before an upgrade to overlay these resources. POLICY_PRODUCT_SERVICES_PARTITION = 0x00000010, }; uint32_t policy_flags; // The number of ResTable_ref that follow this header. uint32_t entry_count; }; struct alignas(uint32_t) Idmap_header { // Always 0x504D4449 ('IDMP') uint32_t magic; Loading