From 75e20dda2b1ef3d2593b02f6a366a02656c1c89d Mon Sep 17 00:00:00 2001 From: Ryan Mitchell Date: Tue, 6 Nov 2018 16:39:36 -0800 Subject: Encoding of and 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 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 --- tools/aapt2/format/binary/BinaryResourceParser.cpp | 96 ++++++++++++++++++---- 1 file changed, 78 insertions(+), 18 deletions(-) (limited to 'tools/aapt2/format/binary/BinaryResourceParser.cpp') diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index ed70fb3c57d6..df0daebe8453 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -240,6 +240,12 @@ bool BinaryResourceParser::ParsePackage(const ResChunk_header* chunk) { } break; + case android::RES_TABLE_OVERLAYABLE_TYPE: + if (!ParseOverlayable(parser.chunk())) { + return false; + } + break; + default: diag_->Warn(DiagMessage(source_) << "unexpected chunk type " @@ -383,24 +389,12 @@ bool BinaryResourceParser::ParseType(const ResourceTablePackage* package, return false; } - const uint32_t type_spec_flags = entry_type_spec_flags_[res_id]; - if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0 || - (type_spec_flags & ResTable_typeSpec::SPEC_OVERLAYABLE) != 0) { - if (entry->flags & ResTable_entry::FLAG_PUBLIC) { - Visibility visibility; - visibility.level = Visibility::Level::kPublic; - visibility.source = source_.WithLine(0); - if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) { - return false; - } - } - - if (type_spec_flags & ResTable_typeSpec::SPEC_OVERLAYABLE) { - Overlayable overlayable; - overlayable.source = source_.WithLine(0); - if (!table_->AddOverlayableMangled(name, overlayable, diag_)) { - return false; - } + if (entry->flags & ResTable_entry::FLAG_PUBLIC) { + Visibility visibility; + visibility.level = Visibility::Level::kPublic; + visibility.source = source_.WithLine(0); + if (!table_->SetVisibilityWithIdMangled(name, visibility, res_id, diag_)) { + return false; } // Erase the ID from the map once processed, so that we don't mark the same symbol more than @@ -433,6 +427,72 @@ bool BinaryResourceParser::ParseLibrary(const ResChunk_header* chunk) { return true; } +bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { + const ResTable_overlayable_header* header = ConvertTo(chunk); + if (!header) { + diag_->Error(DiagMessage(source_) << "corrupt ResTable_category_header chunk"); + return false; + } + + ResChunkPullParser parser(GetChunkData(chunk), + GetChunkDataLen(chunk)); + while (ResChunkPullParser::IsGoodEvent(parser.Next())) { + if (util::DeviceToHost16(parser.chunk()->type) == android::RES_TABLE_OVERLAYABLE_POLICY_TYPE) { + const ResTable_overlayable_policy_header* policy_header = + ConvertTo(parser.chunk()); + + std::vector policies; + if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_PUBLIC) { + policies.push_back(Overlayable::Policy::kPublic); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION) { + policies.push_back(Overlayable::Policy::kSystem); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION) { + policies.push_back(Overlayable::Policy::kVendor); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) { + policies.push_back(Overlayable::Policy::kProduct); + } + if (policy_header->policy_flags + & ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION) { + policies.push_back(Overlayable::Policy::kProductServices); + } + + const ResTable_ref* const ref_begin = reinterpret_cast( + ((uint8_t *)policy_header) + util::DeviceToHost32(policy_header->header.headerSize)); + const ResTable_ref* const ref_end = ref_begin + + util::DeviceToHost32(policy_header->entry_count); + for (auto ref_iter = ref_begin; ref_iter != ref_end; ++ref_iter) { + ResourceId res_id(util::DeviceToHost32(ref_iter->ident)); + const auto iter = id_index_.find(res_id); + + // If the overlayable chunk comes before the type chunks, the resource ids and resource name + // pairing will not exist at this point. + if (iter == id_index_.cend()) { + diag_->Error(DiagMessage(source_) << "failed to find resource name for overlayable" + << " resource " << res_id); + return false; + } + + for (Overlayable::Policy policy : policies) { + Overlayable overlayable; + overlayable.source = source_.WithLine(0); + overlayable.policy = policy; + if (!table_->AddOverlayable(iter->second, overlayable, diag_)) { + return false; + } + } + } + } + } + + return true; +} + std::unique_ptr BinaryResourceParser::ParseValue(const ResourceNameRef& name, const ConfigDescription& config, const android::Res_value& value) { -- cgit v1.2.3