diff options
author | Ryan Mitchell <rtmitchell@google.com> | 2018-11-06 16:39:36 -0800 |
---|---|---|
committer | Ryan Mitchell <rtmitchell@google.com> | 2018-12-04 16:45:26 -0800 |
commit | 75e20dda2b1ef3d2593b02f6a366a02656c1c89d (patch) | |
tree | 8fbbab15ed762cd27097f38e4db0279d679f14eb /libs/androidfw/LoadedArsc.cpp | |
parent | 7208efc83baa70999d2ab264c289b0a38d716ed5 (diff) |
Encoding of <overlayable> and <policy>
This change defines two new chunks for encoding overlayable information.
RES_TABLE_OVERLAYABLE_POLICY_TYPE contains flags that represent
restrictions enforced on overlays that try to overlay a specific set of
resource ids. The chunk header is followed by ResTable_ref for each id
that belongs to the policy type. A policy chunk will be created for
every unique combination of policies that are defined in overlayable
declarations.
RES_TABLE_OVERLAYABLE_TYPE holds policy blocks. Since <overlayable>
does not currently have any attributes, only one overlayable block is
encoded in an APK.
This change also removes the SPEC_OVERLAYABLE flag because the runtime
does not use the flag, and the overlayable chunk encoding renders it
obsolete.
Bug: 110869880
Bug: 117545186
Test: libandroidfw_tests and aapt2_tests
Change-Id: I45ae9bf4176699f14c85e2b7a2e8560185d8a0b8
Diffstat (limited to 'libs/androidfw/LoadedArsc.cpp')
-rw-r--r-- | libs/androidfw/LoadedArsc.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index 68d216d286cf..c20c720eadbb 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -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: |