diff options
-rw-r--r-- | libs/androidfw/LoadedArsc.cpp | 2 | ||||
-rw-r--r-- | tools/aapt2/ResourceParser.cpp | 101 | ||||
-rw-r--r-- | tools/aapt2/ResourceParser_test.cpp | 144 | ||||
-rw-r--r-- | tools/aapt2/ResourceTable.cpp | 20 | ||||
-rw-r--r-- | tools/aapt2/ResourceTable.h | 32 | ||||
-rw-r--r-- | tools/aapt2/ResourceTable_test.cpp | 90 | ||||
-rw-r--r-- | tools/aapt2/Resources.proto | 27 | ||||
-rw-r--r-- | tools/aapt2/format/binary/BinaryResourceParser.cpp | 22 | ||||
-rw-r--r-- | tools/aapt2/format/binary/TableFlattener.cpp | 18 | ||||
-rw-r--r-- | tools/aapt2/format/binary/TableFlattener_test.cpp | 101 | ||||
-rw-r--r-- | tools/aapt2/format/proto/ProtoDeserialize.cpp | 93 | ||||
-rw-r--r-- | tools/aapt2/format/proto/ProtoSerialize.cpp | 74 | ||||
-rw-r--r-- | tools/aapt2/format/proto/ProtoSerialize_test.cpp | 86 | ||||
-rw-r--r-- | tools/aapt2/link/ReferenceLinker.cpp | 4 | ||||
-rw-r--r-- | tools/aapt2/link/TableMerger.cpp | 10 | ||||
-rw-r--r-- | tools/aapt2/link/TableMerger_test.cpp | 75 | ||||
-rw-r--r-- | tools/aapt2/split/TableSplitter.cpp | 2 | ||||
-rw-r--r-- | tools/aapt2/test/Builders.cpp | 2 | ||||
-rw-r--r-- | tools/aapt2/test/Builders.h | 2 |
19 files changed, 573 insertions, 332 deletions
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp index c20c720eadbb..5a267804ddf1 100644 --- a/libs/androidfw/LoadedArsc.cpp +++ b/libs/androidfw/LoadedArsc.cpp @@ -623,7 +623,7 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, } // Add the pairing of overlayable properties to resource ids to the package - OverlayableInfo overlayable_info; + OverlayableInfo overlayable_info{}; overlayable_info.policy_flags = policy_header->policy_flags; loaded_package->overlayable_infos_.push_back(std::make_pair(overlayable_info, ids)); break; diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp index 95877045072b..96c03a6184cf 100644 --- a/tools/aapt2/ResourceParser.cpp +++ b/tools/aapt2/ResourceParser.cpp @@ -99,7 +99,7 @@ struct ParsedResource { ResourceId id; Visibility::Level visibility_level = Visibility::Level::kUndefined; bool allow_new = false; - Maybe<Overlayable> overlayable; + Maybe<OverlayableItem> overlayable_item; std::string comment; std::unique_ptr<Value> value; @@ -133,8 +133,8 @@ static bool AddResourcesToTable(ResourceTable* table, IDiagnostics* diag, Parsed } } - if (res->overlayable) { - if (!table->SetOverlayable(res->name, res->overlayable.value(), diag)) { + if (res->overlayable_item) { + if (!table->SetOverlayable(res->name, res->overlayable_item.value(), diag)) { return false; } } @@ -1059,92 +1059,119 @@ bool ResourceParser::ParseSymbol(xml::XmlPullParser* parser, ParsedResource* out bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource* out_resource) { if (out_resource->config != ConfigDescription::DefaultConfig()) { diag_->Warn(DiagMessage(out_resource->source) - << "ignoring configuration '" << out_resource->config - << "' for <overlayable> tag"); + << "ignoring configuration '" << out_resource->config + << "' for <overlayable> tag"); + } + + Maybe<StringPiece> overlayable_name = xml::FindNonEmptyAttribute(parser, "name"); + if (!overlayable_name) { + diag_->Error(DiagMessage(out_resource->source) + << "<overlayable> tag must have a 'name' attribute"); + return false; } + const std::string kActorUriScheme = + android::base::StringPrintf("%s://", Overlayable::kActorScheme); + Maybe<StringPiece> overlayable_actor = xml::FindNonEmptyAttribute(parser, "actor"); + if (overlayable_actor && !util::StartsWith(overlayable_actor.value(), kActorUriScheme)) { + diag_->Error(DiagMessage(out_resource->source) + << "specified <overlayable> tag 'actor' attribute must use the scheme '" + << Overlayable::kActorScheme << "'"); + return false; + } + + // Create a overlayable entry grouping that represents this <overlayable> + auto overlayable = std::make_shared<Overlayable>( + overlayable_name.value(), (overlayable_actor) ? overlayable_actor.value() : "", + out_resource->source); + bool error = false; std::string comment; - Overlayable::PolicyFlags current_policies = Overlayable::Policy::kNone; + OverlayableItem::PolicyFlags current_policies = OverlayableItem::Policy::kNone; const size_t start_depth = parser->depth(); while (xml::XmlPullParser::IsGoodEvent(parser->Next())) { xml::XmlPullParser::Event event = parser->event(); if (event == xml::XmlPullParser::Event::kEndElement && parser->depth() == start_depth) { - // Break the loop when exiting the overlayable element + // Break the loop when exiting the <overlayable> break; } else if (event == xml::XmlPullParser::Event::kEndElement && parser->depth() == start_depth + 1) { - // Clear the current policies when exiting the policy element - current_policies = Overlayable::Policy::kNone; + // Clear the current policies when exiting the <policy> tags + current_policies = OverlayableItem::Policy::kNone; continue; } else if (event == xml::XmlPullParser::Event::kComment) { - // Get the comment of individual item elements + // Retrieve the comment of individual <item> tags comment = parser->comment(); continue; } else if (event != xml::XmlPullParser::Event::kStartElement) { - // Skip to the next element + // Skip to the start of the next element continue; } - const Source item_source = source_.WithLine(parser->line_number()); + const Source element_source = source_.WithLine(parser->line_number()); const std::string& element_name = parser->element_name(); const std::string& element_namespace = parser->element_namespace(); if (element_namespace.empty() && element_name == "item") { // Items specify the name and type of resource that should be overlayable - Maybe<StringPiece> maybe_name = xml::FindNonEmptyAttribute(parser, "name"); - if (!maybe_name) { - diag_->Error(DiagMessage(item_source) - << "<item> within an <overlayable> tag must have a 'name' attribute"); + Maybe<StringPiece> item_name = xml::FindNonEmptyAttribute(parser, "name"); + if (!item_name) { + diag_->Error(DiagMessage(element_source) + << "<item> within an <overlayable> must have a 'name' attribute"); error = true; continue; } - Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type"); - if (!maybe_type) { - diag_->Error(DiagMessage(item_source) - << "<item> within an <overlayable> tag must have a 'type' attribute"); + Maybe<StringPiece> item_type = xml::FindNonEmptyAttribute(parser, "type"); + if (!item_type) { + diag_->Error(DiagMessage(element_source) + << "<item> within an <overlayable> must have a 'type' attribute"); error = true; continue; } - const ResourceType* type = ParseResourceType(maybe_type.value()); + const ResourceType* type = ParseResourceType(item_type.value()); if (type == nullptr) { - diag_->Error(DiagMessage(item_source) - << "invalid resource type '" << maybe_type.value() + diag_->Error(DiagMessage(element_source) + << "invalid resource type '" << item_type.value() << "' in <item> within an <overlayable>"); error = true; continue; } - ParsedResource child_resource; + OverlayableItem overlayable_item(overlayable); + overlayable_item.policies = current_policies; + overlayable_item.comment = comment; + overlayable_item.source = element_source; + + ParsedResource child_resource{}; child_resource.name.type = *type; - child_resource.name.entry = maybe_name.value().to_string(); - child_resource.overlayable = Overlayable{current_policies, item_source, comment}; + child_resource.name.entry = item_name.value().to_string(); + child_resource.overlayable_item = overlayable_item; out_resource->child_resources.push_back(std::move(child_resource)); } else if (element_namespace.empty() && element_name == "policy") { - if (current_policies != Overlayable::Policy::kNone) { + if (current_policies != OverlayableItem::Policy::kNone) { // If the policy list is not empty, then we are currently inside a policy element - diag_->Error(DiagMessage(item_source) << "<policy> blocks cannot be recursively nested"); + diag_->Error(DiagMessage(element_source) << "<policy> blocks cannot be recursively nested"); error = true; break; } else if (Maybe<StringPiece> maybe_type = xml::FindNonEmptyAttribute(parser, "type")) { // Parse the polices separated by vertical bar characters to allow for specifying multiple - // policies + // policies. Items within the policy tag will have the specified policy. for (StringPiece part : util::Tokenize(maybe_type.value(), '|')) { StringPiece trimmed_part = util::TrimWhitespace(part); if (trimmed_part == "public") { - current_policies |= Overlayable::Policy::kPublic; + current_policies |= OverlayableItem::Policy::kPublic; } else if (trimmed_part == "product") { - current_policies |= Overlayable::Policy::kProduct; + current_policies |= OverlayableItem::Policy::kProduct; } else if (trimmed_part == "product_services") { - current_policies |= Overlayable::Policy::kProductServices; + current_policies |= OverlayableItem::Policy::kProductServices; } else if (trimmed_part == "system") { - current_policies |= Overlayable::Policy::kSystem; + current_policies |= OverlayableItem::Policy::kSystem; } else if (trimmed_part == "vendor") { - current_policies |= Overlayable::Policy::kVendor; + current_policies |= OverlayableItem::Policy::kVendor; } else { - diag_->Error(DiagMessage(item_source) + diag_->Error(DiagMessage(element_source) << "<policy> has unsupported type '" << trimmed_part << "'"); error = true; continue; @@ -1152,11 +1179,13 @@ bool ResourceParser::ParseOverlayable(xml::XmlPullParser* parser, ParsedResource } } } else if (!ShouldIgnoreElement(element_namespace, element_name)) { - diag_->Error(DiagMessage(item_source) << "invalid element <" << element_name << "> " + diag_->Error(DiagMessage(element_source) << "invalid element <" << element_name << "> " << " in <overlayable>"); error = true; break; } + + comment.clear(); } return !error; diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp index 03e6197027cb..debca9c1e1ba 100644 --- a/tools/aapt2/ResourceParser_test.cpp +++ b/tools/aapt2/ResourceParser_test.cpp @@ -892,11 +892,8 @@ TEST_F(ResourceParserTest, ParsePlatformIndependentNewline) { } TEST_F(ResourceParserTest, ParseOverlayable) { - std::string input = R"(<overlayable />)"; - EXPECT_TRUE(TestParse(input)); - - input = R"( - <overlayable> + std::string input = R"( + <overlayable name="Name" actor="overlay://theme"> <item type="string" name="foo" /> <item type="drawable" name="bar" /> </overlayable>)"; @@ -905,24 +902,35 @@ TEST_F(ResourceParserTest, ParseOverlayable) { auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - EXPECT_THAT(search_result.value().entry->overlayable.value().policies, - Eq(Overlayable::Policy::kNone)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); search_result = table_.FindResource(test::ParseNameOrDie("drawable/bar")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - EXPECT_THAT(search_result.value().entry->overlayable.value().policies, - Eq(Overlayable::Policy::kNone)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); } -TEST_F(ResourceParserTest, ParseOverlayablePolicy) { - std::string input = R"(<overlayable />)"; - EXPECT_TRUE(TestParse(input)); +TEST_F(ResourceParserTest, ParseOverlayableRequiresName) { + EXPECT_FALSE(TestParse(R"(<overlayable actor="overlay://theme" />)")); + EXPECT_TRUE(TestParse(R"(<overlayable name="Name" />)")); + EXPECT_TRUE(TestParse(R"(<overlayable name="Name" actor="overlay://theme" />)")); +} - input = R"( - <overlayable> +TEST_F(ResourceParserTest, ParseOverlayableBadActorFail) { + EXPECT_FALSE(TestParse(R"(<overlayable name="Name" actor="overley://theme" />)")); +} + +TEST_F(ResourceParserTest, ParseOverlayablePolicy) { + std::string input = R"( + <overlayable name="Name"> <item type="string" name="foo" /> <policy type="product"> <item type="string" name="bar" /> @@ -945,49 +953,55 @@ TEST_F(ResourceParserTest, ParseOverlayablePolicy) { auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - Overlayable& overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kNone)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kProduct)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct)); search_result = table_.FindResource(test::ParseNameOrDie("string/baz")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kProductServices)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices)); search_result = table_.FindResource(test::ParseNameOrDie("string/fiz")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kSystem)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kSystem)); search_result = table_.FindResource(test::ParseNameOrDie("string/fuz")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kVendor)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor)); search_result = table_.FindResource(test::ParseNameOrDie("string/faz")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kPublic)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic)); } TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) { std::string input = R"( - <overlayable> + <overlayable name="Name"> <policy type="illegal_policy"> <item type="string" name="foo" /> </policy> @@ -995,7 +1009,7 @@ TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) { EXPECT_FALSE(TestParse(input)); input = R"( - <overlayable> + <overlayable name="Name"> <policy type="product"> <item name="foo" /> </policy> @@ -1003,7 +1017,7 @@ TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) { EXPECT_FALSE(TestParse(input)); input = R"( - <overlayable> + <overlayable name="Name"> <policy type="vendor"> <item type="string" /> </policy> @@ -1013,7 +1027,7 @@ TEST_F(ResourceParserTest, ParseOverlayableBadPolicyError) { TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) { std::string input = R"( - <overlayable> + <overlayable name="Name"> <policy type="vendor|product_services"> <item type="string" name="foo" /> </policy> @@ -1026,39 +1040,59 @@ TEST_F(ResourceParserTest, ParseOverlayableMultiplePolicy) { auto search_result = table_.FindResource(test::ParseNameOrDie("string/foo")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - Overlayable& overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kVendor - | Overlayable::Policy::kProductServices)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kVendor + | OverlayableItem::Policy::kProductServices)); search_result = table_.FindResource(test::ParseNameOrDie("string/bar")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(overlayable.policies, Eq(Overlayable::Policy::kProduct - | Overlayable::Policy::kSystem)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct + | OverlayableItem::Policy::kSystem)); } TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { std::string input = R"( - <overlayable> + <overlayable name="Name"> + <item type="string" name="foo" /> + <item type="string" name="foo" /> + </overlayable>)"; + EXPECT_FALSE(TestParse(input)); + + input = R"( + <overlayable name="Name"> + <item type="string" name="foo" /> + </overlayable> + <overlayable name="Name"> <item type="string" name="foo" /> + </overlayable>)"; + EXPECT_FALSE(TestParse(input)); + + input = R"( + <overlayable name="Name"> + <item type="string" name="foo" /> + </overlayable> + <overlayable name="Other"> <item type="string" name="foo" /> </overlayable>)"; EXPECT_FALSE(TestParse(input)); input = R"( - <overlayable> + <overlayable name="Name" actor="overlay://my.actor.one"> <item type="string" name="foo" /> </overlayable> - <overlayable> + <overlayable name="Other" actor="overlay://my.actor.two"> <item type="string" name="foo" /> </overlayable>)"; EXPECT_FALSE(TestParse(input)); input = R"( - <overlayable> + <overlayable name="Name"> <policy type="product"> <item type="string" name="foo" /> <item type="string" name="foo" /> @@ -1067,7 +1101,7 @@ TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { EXPECT_FALSE(TestParse(input)); input = R"( - <overlayable> + <overlayable name="Name"> <policy type="product"> <item type="string" name="foo" /> </policy> @@ -1076,7 +1110,7 @@ TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { EXPECT_FALSE(TestParse(input)); input = R"( - <overlayable> + <overlayable name="Name"> <policy type="product"> <item type="string" name="foo" /> </policy> @@ -1087,13 +1121,13 @@ TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { EXPECT_FALSE(TestParse(input)); input = R"( - <overlayable> + <overlayable name="Name"> <policy type="product"> <item type="string" name="foo" /> </policy> </overlayable> - <overlayable> + <overlayable name="Name"> <policy type="product"> <item type="string" name="foo" /> </policy> @@ -1103,7 +1137,7 @@ TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { TEST_F(ResourceParserTest, NestPolicyInOverlayableError) { std::string input = R"( - <overlayable> + <overlayable name="Name"> <policy type="vendor|product"> <policy type="product_services"> <item type="string" name="foo" /> diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp index 54633ad5c5e3..dbd0a0ca1799 100644 --- a/tools/aapt2/ResourceTable.cpp +++ b/tools/aapt2/ResourceTable.cpp @@ -40,6 +40,8 @@ using ::android::base::StringPrintf; namespace aapt { +const char* Overlayable::kActorScheme = "overlay"; + static bool less_than_type_and_id(const std::unique_ptr<ResourceTableType>& lhs, const std::pair<ResourceType, Maybe<uint8_t>>& rhs) { return lhs->type < rhs.first || (lhs->type == rhs.first && rhs.second && lhs->id < rhs.second); @@ -625,17 +627,18 @@ bool ResourceTable::SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& return true; } -bool ResourceTable::SetOverlayable(const ResourceNameRef& name, const Overlayable& overlayable, +bool ResourceTable::SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable, IDiagnostics* diag) { return SetOverlayableImpl(name, overlayable, ResourceNameValidator, diag); } bool ResourceTable::SetOverlayableMangled(const ResourceNameRef& name, - const Overlayable& overlayable, IDiagnostics* diag) { + const OverlayableItem& overlayable, IDiagnostics* diag) { return SetOverlayableImpl(name, overlayable, SkipNameValidator, diag); } -bool ResourceTable::SetOverlayableImpl(const ResourceNameRef& name, const Overlayable& overlayable, +bool ResourceTable::SetOverlayableImpl(const ResourceNameRef& name, + const OverlayableItem& overlayable, NameValidator name_validator, IDiagnostics *diag) { CHECK(diag != nullptr); @@ -647,14 +650,15 @@ bool ResourceTable::SetOverlayableImpl(const ResourceNameRef& name, const Overla ResourceTableType* type = package->FindOrCreateType(name.type); ResourceEntry* entry = type->FindOrCreateEntry(name.entry); - if (entry->overlayable) { + if (entry->overlayable_item) { diag->Error(DiagMessage(overlayable.source) - << "duplicate overlayable declaration for resource '" << name << "'"); - diag->Error(DiagMessage(entry->overlayable.value().source) << "previous declaration here"); + << "duplicate overlayable declaration for resource '" << name << "'"); + diag->Error(DiagMessage(entry->overlayable_item.value().source) + << "previous declaration here"); return false; } - entry->overlayable = overlayable; + entry->overlayable_item = overlayable; return true; } @@ -690,7 +694,7 @@ std::unique_ptr<ResourceTable> ResourceTable::Clone() const { new_entry->id = entry->id; new_entry->visibility = entry->visibility; new_entry->allow_new = entry->allow_new; - new_entry->overlayable = entry->overlayable; + new_entry->overlayable_item = entry->overlayable_item; for (const auto& config_value : entry->values) { ResourceConfigValue* new_value = diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h index e646f5be43c7..eaf6a47a15fd 100644 --- a/tools/aapt2/ResourceTable.h +++ b/tools/aapt2/ResourceTable.h @@ -57,10 +57,27 @@ struct AllowNew { std::string comment; }; -// Represents a declaration that a resource is overlayable at runtime. struct Overlayable { + Overlayable() = default; + Overlayable(const android::StringPiece& name, const android::StringPiece& actor) + : name(name.to_string()), actor(actor.to_string()) {} + Overlayable(const android::StringPiece& name, const android::StringPiece& actor, + const Source& source) + : name(name.to_string()), actor(actor.to_string()), source(source ){} + + static const char* kActorScheme; + std::string name; + std::string actor; + Source source; +}; + +// Represents a declaration that a resource is overlayable at runtime. +struct OverlayableItem { + explicit OverlayableItem(const std::shared_ptr<Overlayable>& overlayable) + : overlayable(overlayable) {} // Represents the types overlays that are allowed to overlay the resource. + typedef uint32_t PolicyFlags; enum Policy : uint32_t { kNone = 0x00, @@ -80,11 +97,10 @@ struct Overlayable { kProductServices = 0x10 }; - typedef uint32_t PolicyFlags; + std::shared_ptr<Overlayable> overlayable; PolicyFlags policies = Policy::kNone; - - Source source; std::string comment; + Source source; }; class ResourceConfigValue { @@ -121,7 +137,7 @@ class ResourceEntry { Maybe<AllowNew> allow_new; // The declarations of this resource as overlayable for RROs - Maybe<Overlayable> overlayable; + Maybe<OverlayableItem> overlayable_item; // The resource's values for each configuration. std::vector<std::unique_ptr<ResourceConfigValue>> values; @@ -251,9 +267,9 @@ class ResourceTable { bool SetVisibilityWithIdMangled(const ResourceNameRef& name, const Visibility& visibility, const ResourceId& res_id, IDiagnostics* diag); - bool SetOverlayable(const ResourceNameRef& name, const Overlayable& overlayable, + bool SetOverlayable(const ResourceNameRef& name, const OverlayableItem& overlayable, IDiagnostics *diag); - bool SetOverlayableMangled(const ResourceNameRef& name, const Overlayable& overlayable, + bool SetOverlayableMangled(const ResourceNameRef& name, const OverlayableItem& overlayable, IDiagnostics* diag); bool SetAllowNew(const ResourceNameRef& name, const AllowNew& allow_new, IDiagnostics* diag); @@ -328,7 +344,7 @@ class ResourceTable { bool SetAllowNewImpl(const ResourceNameRef& name, const AllowNew& allow_new, NameValidator name_validator, IDiagnostics* diag); - bool SetOverlayableImpl(const ResourceNameRef &name, const Overlayable &overlayable, + bool SetOverlayableImpl(const ResourceNameRef &name, const OverlayableItem& overlayable, NameValidator name_validator, IDiagnostics *diag); bool SetSymbolStateImpl(const ResourceNameRef& name, const ResourceId& res_id, diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp index 31095c4d88c8..a733134f123c 100644 --- a/tools/aapt2/ResourceTable_test.cpp +++ b/tools/aapt2/ResourceTable_test.cpp @@ -244,48 +244,90 @@ TEST(ResourceTableTest, SetAllowNew) { TEST(ResourceTableTest, SetOverlayable) { ResourceTable table; - Overlayable overlayable{}; - overlayable.policies |= Overlayable::Policy::kProduct; - overlayable.policies |= Overlayable::Policy::kProductServices; - overlayable.comment = "comment"; + auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme", + Source("res/values/overlayable.xml", 40)); + OverlayableItem overlayable_item(overlayable); + overlayable_item.policies |= OverlayableItem::Policy::kProduct; + overlayable_item.policies |= OverlayableItem::Policy::kProductServices; + overlayable_item.comment = "comment"; + overlayable_item.source = Source("res/values/overlayable.xml", 42); const ResourceName name = test::ParseNameOrDie("android:string/foo"); - ASSERT_TRUE(table.SetOverlayable(name, overlayable, test::GetDiagnostics())); + ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics())); Maybe<ResourceTable::SearchResult> search_result = table.FindResource(name); ASSERT_TRUE(search_result); - ASSERT_TRUE(search_result.value().entry->overlayable); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + + OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("Name")); + EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml")); + EXPECT_THAT(result_overlayable_item.overlayable->source.line, 40); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct + | OverlayableItem::Policy::kProductServices)); + ASSERT_THAT(result_overlayable_item.comment, StrEq("comment")); + EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml")); + EXPECT_THAT(result_overlayable_item.source.line, 42); +} + +TEST(ResourceTableTest, SetMultipleOverlayableResources) { + ResourceTable table; + + const ResourceName foo = test::ParseNameOrDie("android:string/foo"); + auto group = std::make_shared<Overlayable>("Name", "overlay://theme"); + OverlayableItem overlayable(group); + overlayable.policies = OverlayableItem::Policy::kProduct; + ASSERT_TRUE(table.SetOverlayable(foo, overlayable, test::GetDiagnostics())); + + const ResourceName bar = test::ParseNameOrDie("android:string/bar"); + OverlayableItem overlayable2(group); + overlayable2.policies = OverlayableItem::Policy::kProduct; + ASSERT_TRUE(table.SetOverlayable(bar, overlayable2, test::GetDiagnostics())); + + const ResourceName baz = test::ParseNameOrDie("android:string/baz"); + OverlayableItem overlayable3(group); + overlayable3.policies = OverlayableItem::Policy::kVendor; + ASSERT_TRUE(table.SetOverlayable(baz, overlayable3, test::GetDiagnostics())); +} + +TEST(ResourceTableTest, SetOverlayableDifferentResourcesDifferentName) { + ResourceTable table; + + const ResourceName foo = test::ParseNameOrDie("android:string/foo"); + OverlayableItem overlayable_item(std::make_shared<Overlayable>("Name", "overlay://theme")); + overlayable_item.policies = OverlayableItem::Policy::kProduct; + ASSERT_TRUE(table.SetOverlayable(foo, overlayable_item, test::GetDiagnostics())); - Overlayable& result_overlayable = search_result.value().entry->overlayable.value(); - ASSERT_THAT(result_overlayable.comment, StrEq("comment")); - EXPECT_THAT(result_overlayable.policies, Eq(Overlayable::Policy::kProduct - | Overlayable::Policy::kProductServices)); + const ResourceName bar = test::ParseNameOrDie("android:string/bar"); + OverlayableItem overlayable_item2(std::make_shared<Overlayable>("Name2", "overlay://theme")); + overlayable_item2.policies = OverlayableItem::Policy::kProduct; + ASSERT_TRUE(table.SetOverlayable(bar, overlayable_item2, test::GetDiagnostics())); } -TEST(ResourceTableTest, AddDuplicateOverlayableSamePolicyFail) { +TEST(ResourceTableTest, SetOverlayableSameResourcesFail) { ResourceTable table; const ResourceName name = test::ParseNameOrDie("android:string/foo"); - Overlayable overlayable{}; - overlayable.policies = Overlayable::Policy::kProduct; - ASSERT_TRUE(table.SetOverlayable(name, overlayable, test::GetDiagnostics())); + auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme"); + OverlayableItem overlayable_item(overlayable); + ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics())); - Overlayable overlayable2{}; - overlayable2.policies = Overlayable::Policy::kProduct; - ASSERT_FALSE(table.SetOverlayable(name, overlayable2, test::GetDiagnostics())); + OverlayableItem overlayable_item2(overlayable); + ASSERT_FALSE(table.SetOverlayable(name, overlayable_item2, test::GetDiagnostics())); } -TEST(ResourceTableTest, AddDuplicateOverlayableDifferentPolicyFail) { +TEST(ResourceTableTest, SetOverlayableSameResourcesDifferentNameFail) { ResourceTable table; const ResourceName name = test::ParseNameOrDie("android:string/foo"); - Overlayable overlayable{}; - overlayable.policies = Overlayable::Policy::kProduct; - ASSERT_TRUE(table.SetOverlayable(name, overlayable, test::GetDiagnostics())); + auto overlayable = std::make_shared<Overlayable>("Name", "overlay://theme"); + OverlayableItem overlayable_item(overlayable); + ASSERT_TRUE(table.SetOverlayable(name, overlayable_item, test::GetDiagnostics())); - Overlayable overlayable2{}; - overlayable2.policies = Overlayable::Policy::kVendor; - ASSERT_FALSE(table.SetOverlayable(name, overlayable2, test::GetDiagnostics())); + auto overlayable2 = std::make_shared<Overlayable>("Other", "overlay://theme"); + OverlayableItem overlayable_item2(overlayable2); + ASSERT_FALSE(table.SetOverlayable(name, overlayable_item2, test::GetDiagnostics())); } TEST(ResourceTableTest, AllowDuplictaeResourcesNames) { diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto index 81a2c2e5cc02..da541be9502b 100644 --- a/tools/aapt2/Resources.proto +++ b/tools/aapt2/Resources.proto @@ -49,6 +49,9 @@ message ResourceTable { // Resource definitions corresponding to an Android package. repeated Package package = 2; + + // The <overlayable> declarations within the resource table. + repeated Overlayable overlayable = 3; } // A package ID in the range [0x00, 0xff]. @@ -133,8 +136,20 @@ message AllowNew { string comment = 2; } -// Represents a declaration that a resource is overayable at runtime. +// Represents a set of overlayable resources. message Overlayable { + // The name of the <overlyabale>. + string name = 1; + + // The location of the <overlyabale> declaration in the source. + Source source = 2; + + // The component responsible for enabling and disabling overlays targeting this <overlayable>. + string actor = 3; +} + +// Represents an overlayable <item> declaration within an <overlayable> tag. +message OverlayableItem { enum Policy { PUBLIC = 0; SYSTEM = 1; @@ -143,14 +158,18 @@ message Overlayable { PRODUCT_SERVICES = 4; } - // Where this declaration was defined in source. + // The location of the <item> declaration in source. Source source = 1; // Any comment associated with the declaration. string comment = 2; - // The policy defined in the overlayable declaration. + // The policy defined by the enclosing <policy> tag of this <item>. repeated Policy policy = 3; + + // The index into overlayable list that points to the <overlayable> tag that contains + // this <item>. + uint32 overlayable_idx = 4; } // An entry ID in the range [0x0000, 0xffff]. @@ -180,7 +199,7 @@ message Entry { AllowNew allow_new = 4; // Whether this resource can be overlaid by a runtime resource overlay (RRO). - Overlayable overlayable = 5; + OverlayableItem overlayable_item = 5; // The set of values defined for this entry, each corresponding to a different // configuration/variant. diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp index 61ebd4ee26ca..c496ff0e159b 100644 --- a/tools/aapt2/format/binary/BinaryResourceParser.cpp +++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp @@ -434,6 +434,8 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { return false; } + auto overlayable = std::make_shared<Overlayable>(); + ResChunkPullParser parser(GetChunkData(chunk), GetChunkDataLen(chunk)); while (ResChunkPullParser::IsGoodEvent(parser.Next())) { @@ -441,25 +443,25 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { const ResTable_overlayable_policy_header* policy_header = ConvertTo<ResTable_overlayable_policy_header>(parser.chunk()); - Overlayable::PolicyFlags policies = Overlayable::Policy::kNone; + OverlayableItem::PolicyFlags policies = OverlayableItem::Policy::kNone; if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_PUBLIC) { - policies |= Overlayable::Policy::kPublic; + policies |= OverlayableItem::Policy::kPublic; } if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION) { - policies |= Overlayable::Policy::kSystem; + policies |= OverlayableItem::Policy::kSystem; } if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION) { - policies |= Overlayable::Policy::kVendor; + policies |= OverlayableItem::Policy::kVendor; } if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION) { - policies |= Overlayable::Policy::kProduct; + policies |= OverlayableItem::Policy::kProduct; } if (policy_header->policy_flags & ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION) { - policies |= Overlayable::Policy::kProductServices; + policies |= OverlayableItem::Policy::kProductServices; } const ResTable_ref* const ref_begin = reinterpret_cast<const ResTable_ref*>( @@ -478,10 +480,10 @@ bool BinaryResourceParser::ParseOverlayable(const ResChunk_header* chunk) { return false; } - Overlayable overlayable{}; - overlayable.source = source_.WithLine(0); - overlayable.policies = policies; - if (!table_->SetOverlayable(iter->second, overlayable, diag_)) { + OverlayableItem overlayable_item(overlayable); + overlayable_item.source = source_.WithLine(0); + overlayable_item.policies = policies; + if (!table_->SetOverlayable(iter->second, overlayable_item, diag_)) { return false; } } diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index 200e2d468500..931d57b1c08a 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -429,29 +429,29 @@ class PackageFlattener { CHECK(bool(type->id)) << "type must have an ID set when flattening <overlayable>"; for (auto& entry : type->entries) { CHECK(bool(type->id)) << "entry must have an ID set when flattening <overlayable>"; - if (!entry->overlayable) { + if (!entry->overlayable_item) { continue; } - Overlayable overlayable = entry->overlayable.value(); - uint32_t policy_flags = Overlayable::Policy::kNone; - if (overlayable.policies & Overlayable::Policy::kPublic) { + OverlayableItem& overlayable = entry->overlayable_item.value(); + uint32_t policy_flags = OverlayableItem::Policy::kNone; + if (overlayable.policies & OverlayableItem::Policy::kPublic) { policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC; } - if (overlayable.policies & Overlayable::Policy::kSystem) { + if (overlayable.policies & OverlayableItem::Policy::kSystem) { policy_flags |= ResTable_overlayable_policy_header::POLICY_SYSTEM_PARTITION; } - if (overlayable.policies & Overlayable::Policy::kVendor) { + if (overlayable.policies & OverlayableItem::Policy::kVendor) { policy_flags |= ResTable_overlayable_policy_header::POLICY_VENDOR_PARTITION; } - if (overlayable.policies & Overlayable::Policy::kProduct) { + if (overlayable.policies & OverlayableItem::Policy::kProduct) { policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_PARTITION; } - if (overlayable.policies & Overlayable::Policy::kProductServices) { + if (overlayable.policies & OverlayableItem::Policy::kProductServices) { policy_flags |= ResTable_overlayable_policy_header::POLICY_PRODUCT_SERVICES_PARTITION; } - if (overlayable.policies == Overlayable::Policy::kNone) { + if (overlayable.policies == OverlayableItem::Policy::kNone) { // Encode overlayable entries defined without a policy as publicly overlayable policy_flags |= ResTable_overlayable_policy_header::POLICY_PUBLIC; } diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index e99ab1f37761..a5fb6fd6d7aa 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -628,17 +628,17 @@ TEST_F(TableFlattenerTest, ObfuscatingResourceNamesWithWhitelistSucceeds) { } TEST_F(TableFlattenerTest, FlattenOverlayable) { - Overlayable overlayable{}; - overlayable.policies |= Overlayable::Policy::kProduct; - overlayable.policies |= Overlayable::Policy::kSystem; - overlayable.policies |= Overlayable::Policy::kVendor; + OverlayableItem overlayable_item(std::make_shared<Overlayable>("TestName", "overlay://theme")); + overlayable_item.policies |= OverlayableItem::Policy::kProduct; + overlayable_item.policies |= OverlayableItem::Policy::kSystem; + overlayable_item.policies |= OverlayableItem::Policy::kVendor; std::string name = "com.app.test:integer/overlayable"; std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() .SetPackageId("com.app.test", 0x7f) .AddSimple(name, ResourceId(0x7f020000)) - .SetOverlayable(name, overlayable) + .SetOverlayable(name, overlayable_item) .Build(); ResourceTable output_table; @@ -647,45 +647,46 @@ TEST_F(TableFlattenerTest, FlattenOverlayable) { auto search_result = output_table.FindResource(test::ParseNameOrDie(name)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - Overlayable& result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_EQ(result_overlayable.policies, Overlayable::Policy::kSystem - | Overlayable::Policy::kVendor - | Overlayable::Policy::kProduct); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_EQ(result_overlayable_item.policies, OverlayableItem::Policy::kSystem + | OverlayableItem::Policy::kVendor + | OverlayableItem::Policy::kProduct); } TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { - std::string name_zero = "com.app.test:integer/overlayable_zero"; - Overlayable overlayable_zero{}; - overlayable_zero.policies |= Overlayable::Policy::kProduct; - overlayable_zero.policies |= Overlayable::Policy::kSystem; - overlayable_zero.policies |= Overlayable::Policy::kProductServices; - - std::string name_one = "com.app.test:integer/overlayable_one"; - Overlayable overlayable_one{}; - overlayable_one.policies |= Overlayable::Policy::kPublic; - overlayable_one.policies |= Overlayable::Policy::kProductServices; - - std::string name_two = "com.app.test:integer/overlayable_two"; - Overlayable overlayable_two{}; - overlayable_two.policies |= Overlayable::Policy::kProduct; - overlayable_two.policies |= Overlayable::Policy::kSystem; - overlayable_two.policies |= Overlayable::Policy::kVendor; - - std::string name_three = "com.app.test:integer/overlayable_three"; - Overlayable overlayable_three{}; + auto overlayable = std::make_shared<Overlayable>("TestName", "overlay://theme"); + std::string name_zero = "com.app.test:integer/overlayable_zero_item"; + OverlayableItem overlayable_zero_item(overlayable); + overlayable_zero_item.policies |= OverlayableItem::Policy::kProduct; + overlayable_zero_item.policies |= OverlayableItem::Policy::kSystem; + overlayable_zero_item.policies |= OverlayableItem::Policy::kProductServices; + + std::string name_one = "com.app.test:integer/overlayable_one_item"; + OverlayableItem overlayable_one_item(overlayable); + overlayable_one_item.policies |= OverlayableItem::Policy::kPublic; + overlayable_one_item.policies |= OverlayableItem::Policy::kProductServices; + + std::string name_two = "com.app.test:integer/overlayable_two_item"; + OverlayableItem overlayable_two_item(overlayable); + overlayable_two_item.policies |= OverlayableItem::Policy::kProduct; + overlayable_two_item.policies |= OverlayableItem::Policy::kSystem; + overlayable_two_item.policies |= OverlayableItem::Policy::kVendor; + + std::string name_three = "com.app.test:integer/overlayable_three_item"; + OverlayableItem overlayable_three_item(overlayable); std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() .SetPackageId("com.app.test", 0x7f) .AddSimple(name_zero, ResourceId(0x7f020000)) - .SetOverlayable(name_zero, overlayable_zero) + .SetOverlayable(name_zero, overlayable_zero_item) .AddSimple(name_one, ResourceId(0x7f020001)) - .SetOverlayable(name_one, overlayable_one) + .SetOverlayable(name_one, overlayable_one_item) .AddSimple(name_two, ResourceId(0x7f020002)) - .SetOverlayable(name_two, overlayable_two) + .SetOverlayable(name_two, overlayable_two_item) .AddSimple(name_three, ResourceId(0x7f020003)) - .SetOverlayable(name_three, overlayable_three) + .SetOverlayable(name_three, overlayable_three_item) .Build(); ResourceTable output_table; @@ -694,35 +695,35 @@ TEST_F(TableFlattenerTest, FlattenMultipleOverlayablePolicies) { auto search_result = output_table.FindResource(test::ParseNameOrDie(name_zero)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - Overlayable& result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_EQ(result_overlayable.policies, Overlayable::Policy::kSystem - | Overlayable::Policy::kProduct - | Overlayable::Policy::kProductServices); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem + | OverlayableItem::Policy::kProduct + | OverlayableItem::Policy::kProductServices); search_result = output_table.FindResource(test::ParseNameOrDie(name_one)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_EQ(result_overlayable.policies, Overlayable::Policy::kPublic - | Overlayable::Policy::kProductServices); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic + | OverlayableItem::Policy::kProductServices); search_result = output_table.FindResource(test::ParseNameOrDie(name_two)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_EQ(result_overlayable.policies, Overlayable::Policy::kSystem - | Overlayable::Policy::kProduct - | Overlayable::Policy::kVendor); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kSystem + | OverlayableItem::Policy::kProduct + | OverlayableItem::Policy::kVendor); search_result = output_table.FindResource(test::ParseNameOrDie(name_three)); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_EQ(result_overlayable.policies, Overlayable::Policy::kPublic); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_EQ(overlayable_item.policies, OverlayableItem::Policy::kPublic); } } // namespace aapt diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp index cf2ab0f45ad6..6b5746d63bf8 100644 --- a/tools/aapt2/format/proto/ProtoDeserialize.cpp +++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp @@ -373,9 +373,44 @@ static Visibility::Level DeserializeVisibilityFromPb(const pb::Visibility::Level return Visibility::Level::kUndefined; } +bool DeserializeOverlayableItemFromPb(const pb::OverlayableItem& pb_overlayable, + const android::ResStringPool& src_pool, + OverlayableItem* out_overlayable, std::string* out_error) { + for (const int policy : pb_overlayable.policy()) { + switch (policy) { + case pb::OverlayableItem::PUBLIC: + out_overlayable->policies |= OverlayableItem::Policy::kPublic; + break; + case pb::OverlayableItem::SYSTEM: + out_overlayable->policies |= OverlayableItem::Policy::kSystem; + break; + case pb::OverlayableItem::VENDOR: + out_overlayable->policies |= OverlayableItem::Policy::kVendor; + break; + case pb::OverlayableItem::PRODUCT: + out_overlayable->policies |= OverlayableItem::Policy::kProduct; + break; + case pb::OverlayableItem::PRODUCT_SERVICES: + out_overlayable->policies |= OverlayableItem::Policy::kProductServices; + break; + default: + *out_error = "unknown overlayable policy"; + return false; + } + } + + if (pb_overlayable.has_source()) { + DeserializeSourceFromPb(pb_overlayable.source(), src_pool, &out_overlayable->source); + } + + out_overlayable->comment = pb_overlayable.comment(); + return true; +} + static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStringPool& src_pool, - io::IFileCollection* files, ResourceTable* out_table, - std::string* out_error) { + io::IFileCollection* files, + const std::vector<std::shared_ptr<Overlayable>>& overlayables, + ResourceTable* out_table, std::string* out_error) { Maybe<uint8_t> id; if (pb_package.has_package_id()) { id = static_cast<uint8_t>(pb_package.package_id().id()); @@ -437,39 +472,22 @@ static bool DeserializePackageFromPb(const pb::Package& pb_package, const ResStr entry->allow_new = std::move(allow_new); } - if (pb_entry.has_overlayable()) { - Overlayable overlayable{}; - - const pb::Overlayable& pb_overlayable = pb_entry.overlayable(); - for (const int policy : pb_overlayable.policy()) { - switch (policy) { - case pb::Overlayable::PUBLIC: - overlayable.policies |= Overlayable::Policy::kPublic; - break; - case pb::Overlayable::SYSTEM: - overlayable.policies |= Overlayable::Policy::kSystem; - break; - case pb::Overlayable::VENDOR: - overlayable.policies |= Overlayable::Policy::kVendor; - break; - case pb::Overlayable::PRODUCT: - overlayable.policies |= Overlayable::Policy::kProduct; - break; - case pb::Overlayable::PRODUCT_SERVICES: - overlayable.policies |= Overlayable::Policy::kProductServices; - break; - default: - *out_error = "unknown overlayable policy"; - return false; - } + if (pb_entry.has_overlayable_item()) { + // Find the overlayable to which this item belongs + pb::OverlayableItem pb_overlayable_item = pb_entry.overlayable_item(); + if (pb_overlayable_item.overlayable_idx() >= overlayables.size()) { + *out_error = android::base::StringPrintf("invalid overlayable_idx value %d", + pb_overlayable_item.overlayable_idx()); + return false; } - if (pb_overlayable.has_source()) { - DeserializeSourceFromPb(pb_overlayable.source(), src_pool, &overlayable.source); + OverlayableItem overlayable_item(overlayables[pb_overlayable_item.overlayable_idx()]); + if (!DeserializeOverlayableItemFromPb(pb_overlayable_item, src_pool, &overlayable_item, + out_error)) { + return false; } - overlayable.comment = pb_overlayable.comment(); - entry->overlayable = overlayable; + entry->overlayable_item = std::move(overlayable_item); } ResourceId resid(pb_package.package_id().id(), pb_type.type_id().id(), @@ -522,8 +540,19 @@ bool DeserializeTableFromPb(const pb::ResourceTable& pb_table, io::IFileCollecti } } + // Deserialize the overlayable groups of the table + std::vector<std::shared_ptr<Overlayable>> overlayables; + for (const pb::Overlayable& pb_overlayable : pb_table.overlayable()) { + auto group = std::make_shared<Overlayable>(pb_overlayable.name(), pb_overlayable.actor()); + if (pb_overlayable.has_source()) { + DeserializeSourceFromPb(pb_overlayable.source(), source_pool, &group->source); + } + overlayables.push_back(group); + } + for (const pb::Package& pb_package : pb_table.package()) { - if (!DeserializePackageFromPb(pb_package, source_pool, files, out_table, out_error)) { + if (!DeserializePackageFromPb(pb_package, source_pool, files, overlayables, out_table, + out_error)) { return false; } } diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp index 70bf8684f8a8..76fbb464b62a 100644 --- a/tools/aapt2/format/proto/ProtoSerialize.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize.cpp @@ -272,9 +272,57 @@ void SerializeConfig(const ConfigDescription& config, pb::Configuration* out_pb_ out_pb_config->set_sdk_version(config.sdkVersion); } +static void SerializeOverlayableItemToPb(const OverlayableItem& overlayable_item, + std::vector<Overlayable*>& serialized_overlayables, + StringPool* source_pool, pb::Entry* pb_entry, + pb::ResourceTable* pb_table) { + // Retrieve the index of the overlayable in the list of groups that have already been serialized. + size_t i; + for (i = 0 ; i < serialized_overlayables.size(); i++) { + if (overlayable_item.overlayable.get() == serialized_overlayables[i]) { + break; + } + } + + // Serialize the overlayable if it has not been serialized already. + if (i == serialized_overlayables.size()) { + serialized_overlayables.push_back(overlayable_item.overlayable.get()); + pb::Overlayable* pb_overlayable = pb_table->add_overlayable(); + pb_overlayable->set_name(overlayable_item.overlayable->name); + pb_overlayable->set_actor(overlayable_item.overlayable->actor); + SerializeSourceToPb(overlayable_item.overlayable->source, source_pool, + pb_overlayable->mutable_source()); + } + + pb::OverlayableItem* pb_overlayable_item = pb_entry->mutable_overlayable_item(); + pb_overlayable_item->set_overlayable_idx(i); + + if (overlayable_item.policies & OverlayableItem::Policy::kPublic) { + pb_overlayable_item->add_policy(pb::OverlayableItem::PUBLIC); + } + if (overlayable_item.policies & OverlayableItem::Policy::kProduct) { + pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT); + } + if (overlayable_item.policies & OverlayableItem::Policy::kProductServices) { + pb_overlayable_item->add_policy(pb::OverlayableItem::PRODUCT_SERVICES); + } + if (overlayable_item.policies & OverlayableItem::Policy::kSystem) { + pb_overlayable_item->add_policy(pb::OverlayableItem::SYSTEM); + } + if (overlayable_item.policies & OverlayableItem::Policy::kVendor) { + pb_overlayable_item->add_policy(pb::OverlayableItem::VENDOR); + } + + SerializeSourceToPb(overlayable_item.source, source_pool, + pb_overlayable_item->mutable_source()); + pb_overlayable_item->set_comment(overlayable_item.comment); +} + void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table, IDiagnostics* diag) { StringPool source_pool; + + std::vector<Overlayable*> overlayables; for (const std::unique_ptr<ResourceTablePackage>& package : table.packages) { pb::Package* pb_package = out_table->add_package(); if (package->id) { @@ -310,29 +358,9 @@ void SerializeTableToPb(const ResourceTable& table, pb::ResourceTable* out_table pb_allow_new->set_comment(entry->allow_new.value().comment); } - if (entry->overlayable) { - pb::Overlayable* pb_overlayable = pb_entry->mutable_overlayable(); - - Overlayable overlayable = entry->overlayable.value(); - if (overlayable.policies & Overlayable::Policy::kPublic) { - pb_overlayable->add_policy(pb::Overlayable::PUBLIC); - } - if (overlayable.policies & Overlayable::Policy::kProduct) { - pb_overlayable->add_policy(pb::Overlayable::PRODUCT); - } - if (overlayable.policies & Overlayable::Policy::kProductServices) { - pb_overlayable->add_policy(pb::Overlayable::PRODUCT_SERVICES); - } - if (overlayable.policies & Overlayable::Policy::kSystem) { - pb_overlayable->add_policy(pb::Overlayable::SYSTEM); - } - if (overlayable.policies & Overlayable::Policy::kVendor) { - pb_overlayable->add_policy(pb::Overlayable::VENDOR); - } - - SerializeSourceToPb(overlayable.source, &source_pool, - pb_overlayable->mutable_source()); - pb_overlayable->set_comment(overlayable.comment); + if (entry->overlayable_item) { + SerializeOverlayableItemToPb(entry->overlayable_item.value(), overlayables, &source_pool, + pb_entry, out_table); } for (const std::unique_ptr<ResourceConfigValue>& config_value : entry->values) { diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp index fb913f409f52..4a3c1b86236e 100644 --- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp +++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp @@ -93,8 +93,11 @@ TEST(ProtoSerializeTest, SerializeSinglePackage) { util::make_unique<Reference>(expected_ref), context->GetDiagnostics())); // Make an overlayable resource. + OverlayableItem overlayable_item(std::make_shared<Overlayable>( + "OverlayableName", "overlay://theme", Source("res/values/overlayable.xml", 40))); + overlayable_item.source = Source("res/values/overlayable.xml", 42); ASSERT_TRUE(table->SetOverlayable(test::ParseNameOrDie("com.app.a:integer/overlayable"), - Overlayable{}, test::GetDiagnostics())); + overlayable_item, test::GetDiagnostics())); pb::ResourceTable pb_table; SerializeTableToPb(*table, &pb_table, context->GetDiagnostics()); @@ -160,9 +163,15 @@ TEST(ProtoSerializeTest, SerializeSinglePackage) { new_table.FindResource(test::ParseNameOrDie("com.app.a:integer/overlayable")); ASSERT_TRUE(search_result); ASSERT_THAT(search_result.value().entry, NotNull()); - ASSERT_TRUE(search_result.value().entry->overlayable); - EXPECT_THAT(search_result.value().entry->overlayable.value().policies, - Eq(Overlayable::Policy::kNone)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("OverlayableName")); + EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(result_overlayable_item.overlayable->source.path, Eq("res/values/overlayable.xml")); + EXPECT_THAT(result_overlayable_item.overlayable->source.line, Eq(40)); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); + EXPECT_THAT(result_overlayable_item.source.path, Eq("res/values/overlayable.xml")); + EXPECT_THAT(result_overlayable_item.source.line, Eq(42)); } TEST(ProtoSerializeTest, SerializeAndDeserializeXml) { @@ -503,26 +512,31 @@ TEST(ProtoSerializeTest, SerializeDeserializeConfiguration) { } TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { - Overlayable overlayable_foo{}; - overlayable_foo.policies |= Overlayable::Policy::kSystem; - overlayable_foo.policies |= Overlayable::Policy::kProduct; + OverlayableItem overlayable_item_foo(std::make_shared<Overlayable>( + "CustomizableResources", "overlay://customization")); + overlayable_item_foo.policies |= OverlayableItem::Policy::kSystem; + overlayable_item_foo.policies |= OverlayableItem::Policy::kProduct; - Overlayable overlayable_bar{}; - overlayable_bar.policies |= Overlayable::Policy::kProductServices; - overlayable_bar.policies |= Overlayable::Policy::kVendor; + OverlayableItem overlayable_item_bar(std::make_shared<Overlayable>( + "TaskBar", "overlay://theme")); + overlayable_item_bar.policies |= OverlayableItem::Policy::kProductServices; + overlayable_item_bar.policies |= OverlayableItem::Policy::kVendor; - Overlayable overlayable_baz{}; - overlayable_baz.policies |= Overlayable::Policy::kPublic; + OverlayableItem overlayable_item_baz(std::make_shared<Overlayable>( + "FontPack", "overlay://theme")); + overlayable_item_baz.policies |= OverlayableItem::Policy::kPublic; - Overlayable overlayable_biz{}; + OverlayableItem overlayable_item_biz(std::make_shared<Overlayable>( + "Other", "overlay://customization")); + overlayable_item_biz.comment ="comment"; std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build(); std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder() - .SetOverlayable("com.app.a:bool/foo", overlayable_foo) - .SetOverlayable("com.app.a:bool/bar", overlayable_bar) - .SetOverlayable("com.app.a:bool/baz", overlayable_baz) - .SetOverlayable("com.app.a:bool/biz", overlayable_biz) + .SetOverlayable("com.app.a:bool/foo", overlayable_item_foo) + .SetOverlayable("com.app.a:bool/bar", overlayable_item_bar) + .SetOverlayable("com.app.a:bool/baz", overlayable_item_baz) + .SetOverlayable("com.app.a:bool/biz", overlayable_item_biz) .AddValue("com.app.a:bool/fiz", ResourceUtils::TryParseBool("true")) .Build(); @@ -538,33 +552,41 @@ TEST(ProtoSerializeTest, SerializeAndDeserializeOverlayable) { Maybe<ResourceTable::SearchResult> search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/foo")); ASSERT_TRUE(search_result); - ASSERT_TRUE(search_result.value().entry->overlayable); - Overlayable result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(result_overlayable.policies, Eq(Overlayable::Policy::kSystem - | Overlayable::Policy::kProduct)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem& overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(overlayable_item.overlayable->name, Eq("CustomizableResources")); + EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://customization")); + EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kSystem + | OverlayableItem::Policy::kProduct)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/bar")); ASSERT_TRUE(search_result); - ASSERT_TRUE(search_result.value().entry->overlayable); - result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(result_overlayable.policies, Eq(Overlayable::Policy::kProductServices - | Overlayable::Policy::kVendor)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(overlayable_item.overlayable->name, Eq("TaskBar")); + EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kProductServices + | OverlayableItem::Policy::kVendor)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/baz")); ASSERT_TRUE(search_result); - ASSERT_TRUE(search_result.value().entry->overlayable); - result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(result_overlayable.policies, Overlayable::Policy::kPublic); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(overlayable_item.overlayable->name, Eq("FontPack")); + EXPECT_THAT(overlayable_item.overlayable->actor, Eq("overlay://theme")); + EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic)); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/biz")); ASSERT_TRUE(search_result); - ASSERT_TRUE(search_result.value().entry->overlayable); - result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(result_overlayable.policies, Overlayable::Policy::kNone); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(overlayable_item.overlayable->name, Eq("Other")); + EXPECT_THAT(overlayable_item.policies, Eq(OverlayableItem::Policy::kNone)); + EXPECT_THAT(overlayable_item.comment, Eq("comment")); search_result = new_table.FindResource(test::ParseNameOrDie("com.app.a:bool/fiz")); ASSERT_TRUE(search_result); - ASSERT_FALSE(search_result.value().entry->overlayable); + ASSERT_FALSE(search_result.value().entry->overlayable_item); } } // namespace aapt diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp index 8cbc03738677..c2340ba65e38 100644 --- a/tools/aapt2/link/ReferenceLinker.cpp +++ b/tools/aapt2/link/ReferenceLinker.cpp @@ -374,8 +374,8 @@ bool ReferenceLinker::Consume(IAaptContext* context, ResourceTable* table) { } // Ensure that definitions for values declared as overlayable exist - if (entry->overlayable && entry->values.empty()) { - context->GetDiagnostics()->Error(DiagMessage(entry->overlayable.value().source) + if (entry->overlayable_item && entry->values.empty()) { + context->GetDiagnostics()->Error(DiagMessage(entry->overlayable_item.value().source) << "no definition for overlayable symbol '" << name << "'"); error = true; diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp index 22e1723591a8..cc9fed554350 100644 --- a/tools/aapt2/link/TableMerger.cpp +++ b/tools/aapt2/link/TableMerger.cpp @@ -134,18 +134,18 @@ static bool MergeEntry(IAaptContext* context, const Source& src, dst_entry->allow_new = std::move(src_entry->allow_new); } - if (src_entry->overlayable) { - if (dst_entry->overlayable) { + if (src_entry->overlayable_item) { + if (dst_entry->overlayable_item) { // Do not allow a resource with an overlayable declaration to have that overlayable // declaration redefined - context->GetDiagnostics()->Error(DiagMessage(src_entry->overlayable.value().source) + context->GetDiagnostics()->Error(DiagMessage(src_entry->overlayable_item.value().source) << "duplicate overlayable declaration for resource '" << src_entry->name << "'"); - context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable.value().source) + context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable_item.value().source) << "previous declaration here"); return false; } else { - dst_entry->overlayable = std::move(src_entry->overlayable); + dst_entry->overlayable_item = std::move(src_entry->overlayable_item); } } diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp index 17b2a83bad04..921d634e583e 100644 --- a/tools/aapt2/link/TableMerger_test.cpp +++ b/tools/aapt2/link/TableMerger_test.cpp @@ -437,14 +437,16 @@ TEST_F(TableMergerTest, OverlaidStyleablesAndStylesShouldBeMerged) { } TEST_F(TableMergerTest, SetOverlayable) { - Overlayable overlayable{}; - overlayable.policies |= Overlayable::Policy::kProduct; - overlayable.policies |= Overlayable::Policy::kVendor; + auto overlayable = std::make_shared<Overlayable>("CustomizableResources", + "overlay://customization"); + OverlayableItem overlayable_item(overlayable); + overlayable_item.policies |= OverlayableItem::Policy::kProduct; + overlayable_item.policies |= OverlayableItem::Policy::kVendor; std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .SetOverlayable("bool/foo", overlayable) + .SetOverlayable("bool/foo", overlayable_item) .Build(); std::unique_ptr<ResourceTable> table_b = @@ -463,26 +465,30 @@ TEST_F(TableMergerTest, SetOverlayable) { const ResourceName name = test::ParseNameOrDie("com.app.a:bool/foo"); Maybe<ResourceTable::SearchResult> search_result = final_table.FindResource(name); ASSERT_TRUE(search_result); - ASSERT_TRUE(search_result.value().entry->overlayable); - Overlayable& result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(result_overlayable.policies, Eq(Overlayable::Policy::kProduct - | Overlayable::Policy::kVendor)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources")); + EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kProduct + | OverlayableItem::Policy::kVendor)); } TEST_F(TableMergerTest, SetOverlayableLater) { + auto overlayable = std::make_shared<Overlayable>("CustomizableResources", + "overlay://customization"); std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) .AddSimple("bool/foo") .Build(); - Overlayable overlayable{}; - overlayable.policies |= Overlayable::Policy::kPublic; - overlayable.policies |= Overlayable::Policy::kProductServices; + OverlayableItem overlayable_item(overlayable); + overlayable_item.policies |= OverlayableItem::Policy::kPublic; + overlayable_item.policies |= OverlayableItem::Policy::kProductServices; std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .SetOverlayable("bool/foo", overlayable) + .SetOverlayable("bool/foo", overlayable_item) .Build(); ResourceTable final_table; @@ -495,27 +501,33 @@ TEST_F(TableMergerTest, SetOverlayableLater) { const ResourceName name = test::ParseNameOrDie("com.app.a:bool/foo"); Maybe<ResourceTable::SearchResult> search_result = final_table.FindResource(name); ASSERT_TRUE(search_result); - ASSERT_TRUE(search_result.value().entry->overlayable); - Overlayable& result_overlayable = search_result.value().entry->overlayable.value(); - EXPECT_THAT(result_overlayable.policies, Eq(Overlayable::Policy::kPublic - | Overlayable::Policy::kProductServices)); + ASSERT_TRUE(search_result.value().entry->overlayable_item); + OverlayableItem& result_overlayable_item = search_result.value().entry->overlayable_item.value(); + EXPECT_THAT(result_overlayable_item.overlayable->name, Eq("CustomizableResources")); + EXPECT_THAT(result_overlayable_item.overlayable->actor, Eq("overlay://customization")); + EXPECT_THAT(result_overlayable_item.policies, Eq(OverlayableItem::Policy::kPublic + | OverlayableItem::Policy::kProductServices)); } -TEST_F(TableMergerTest, SetOverlayableSamePolicesFail) { - Overlayable overlayable_first{}; - overlayable_first.policies |= Overlayable::Policy::kProduct; +TEST_F(TableMergerTest, SameResourceDifferentNameFail) { + auto overlayable_first = std::make_shared<Overlayable>("CustomizableResources", + "overlay://customization"); + OverlayableItem overlayable_item_first(overlayable_first); + overlayable_item_first.policies |= OverlayableItem::Policy::kProduct; std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .SetOverlayable("bool/foo", overlayable_first) + .SetOverlayable("bool/foo", overlayable_item_first) .Build(); - Overlayable overlayable_second{}; - overlayable_second.policies |= Overlayable::Policy::kProduct; + auto overlayable_second = std::make_shared<Overlayable>("ThemeResources", + "overlay://theme"); + OverlayableItem overlayable_item_second(overlayable_second); + overlayable_item_second.policies |= OverlayableItem::Policy::kProduct; std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .SetOverlayable("bool/foo", overlayable_second) + .SetOverlayable("bool/foo", overlayable_item_second) .Build(); ResourceTable final_table; @@ -526,21 +538,24 @@ TEST_F(TableMergerTest, SetOverlayableSamePolicesFail) { ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/)); } -TEST_F(TableMergerTest, SetOverlayableDifferentPolicesFail) { - Overlayable overlayable_first{}; - overlayable_first.policies |= Overlayable::Policy::kVendor; +TEST_F(TableMergerTest, SameResourceSameNameFail) { + auto overlayable = std::make_shared<Overlayable>("CustomizableResources", + "overlay://customization"); + + OverlayableItem overlayable_item_first(overlayable); + overlayable_item_first.policies |= OverlayableItem::Policy::kProduct; std::unique_ptr<ResourceTable> table_a = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .SetOverlayable("bool/foo",overlayable_first) + .SetOverlayable("bool/foo", overlayable_item_first) .Build(); - Overlayable overlayable_second{}; - overlayable_second.policies |= Overlayable::Policy::kProduct; + OverlayableItem overlayable_item_second(overlayable); + overlayable_item_second.policies |= OverlayableItem::Policy::kSystem; std::unique_ptr<ResourceTable> table_b = test::ResourceTableBuilder() .SetPackageId("com.app.a", 0x7f) - .SetOverlayable("bool/foo", overlayable_second) + .SetOverlayable("bool/foo", overlayable_item_second) .Build(); ResourceTable final_table; diff --git a/tools/aapt2/split/TableSplitter.cpp b/tools/aapt2/split/TableSplitter.cpp index 9c5b5d36b798..24cd5ba302ea 100644 --- a/tools/aapt2/split/TableSplitter.cpp +++ b/tools/aapt2/split/TableSplitter.cpp @@ -248,7 +248,7 @@ void TableSplitter::SplitTable(ResourceTable* original_table) { if (!split_entry->id) { split_entry->id = entry->id; split_entry->visibility = entry->visibility; - split_entry->overlayable = entry->overlayable; + split_entry->overlayable_item = entry->overlayable_item; } // Copy the selected values into the new Split Entry. diff --git a/tools/aapt2/test/Builders.cpp b/tools/aapt2/test/Builders.cpp index 884ec38290f8..9a93f2a7476c 100644 --- a/tools/aapt2/test/Builders.cpp +++ b/tools/aapt2/test/Builders.cpp @@ -136,7 +136,7 @@ ResourceTableBuilder& ResourceTableBuilder::SetSymbolState(const StringPiece& na } ResourceTableBuilder& ResourceTableBuilder::SetOverlayable(const StringPiece& name, - const Overlayable& overlayable) { + const OverlayableItem& overlayable) { ResourceName res_name = ParseNameOrDie(name); CHECK(table_->SetOverlayable(res_name, overlayable, GetDiagnostics())); diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h index a12048436e38..c971a1b47fd5 100644 --- a/tools/aapt2/test/Builders.h +++ b/tools/aapt2/test/Builders.h @@ -74,7 +74,7 @@ class ResourceTableBuilder { ResourceTableBuilder& SetSymbolState(const android::StringPiece& name, const ResourceId& id, Visibility::Level level, bool allow_new = false); ResourceTableBuilder& SetOverlayable(const android::StringPiece& name, - const Overlayable& overlayable); + const OverlayableItem& overlayable); StringPool* string_pool(); std::unique_ptr<ResourceTable> Build(); |