Add actor and name parsing for overlayable
Add parsing of two overlayable attributes:
name : The unnique identifying name of the overlayable set of resources
actor: The component responsible for enabling and disabling overlays
targeting the specified set of resources
Bug: 110869880
Bug: 119390855
Test: m -j aapt2_tests
Change-Id: Id42463e2b92b69034fb39cd29bc8606affb61ba7
diff --git a/libs/androidfw/LoadedArsc.cpp b/libs/androidfw/LoadedArsc.cpp
index c20c720..5a26780 100644
--- a/libs/androidfw/LoadedArsc.cpp
+++ b/libs/androidfw/LoadedArsc.cpp
@@ -623,7 +623,7 @@
}
// 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 9587704..96c03a6 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -99,7 +99,7 @@
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 @@
}
}
- 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::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 @@
}
}
} 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 03e6197..debca9c 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -892,11 +892,8 @@
}
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 @@
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, 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" />)"));
+}
+
+TEST_F(ResourceParserTest, ParseOverlayableBadActorFail) {
+ EXPECT_FALSE(TestParse(R"(<overlayable name="Name" actor="overley://theme" />)"));
}
TEST_F(ResourceParserTest, ParseOverlayablePolicy) {
- std::string input = R"(<overlayable />)";
- EXPECT_TRUE(TestParse(input));
-
- input = R"(
- <overlayable>
+ std::string input = R"(
+ <overlayable name="Name">
<item type="string" name="foo" />
<policy type="product">
<item type="string" name="bar" />
@@ -945,49 +953,55 @@
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 @@
EXPECT_FALSE(TestParse(input));
input = R"(
- <overlayable>
+ <overlayable name="Name">
<policy type="product">
<item name="foo" />
</policy>
@@ -1003,7 +1017,7 @@
EXPECT_FALSE(TestParse(input));
input = R"(
- <overlayable>
+ <overlayable name="Name">
<policy type="vendor">
<item type="string" />
</policy>
@@ -1013,7 +1027,7 @@
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 @@
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>
+ <overlayable name="Name">
<item type="string" name="foo" />
</overlayable>
- <overlayable>
+ <overlayable name="Name">
<item type="string" name="foo" />
</overlayable>)";
EXPECT_FALSE(TestParse(input));
input = R"(
- <overlayable>
+ <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 name="Name" actor="overlay://my.actor.one">
+ <item type="string" name="foo" />
+ </overlayable>
+ <overlayable name="Other" actor="overlay://my.actor.two">
+ <item type="string" name="foo" />
+ </overlayable>)";
+ EXPECT_FALSE(TestParse(input));
+
+ input = R"(
+ <overlayable name="Name">
<policy type="product">
<item type="string" name="foo" />
<item type="string" name="foo" />
@@ -1067,7 +1101,7 @@
EXPECT_FALSE(TestParse(input));
input = R"(
- <overlayable>
+ <overlayable name="Name">
<policy type="product">
<item type="string" name="foo" />
</policy>
@@ -1076,7 +1110,7 @@
EXPECT_FALSE(TestParse(input));
input = R"(
- <overlayable>
+ <overlayable name="Name">
<policy type="product">
<item type="string" name="foo" />
</policy>
@@ -1087,13 +1121,13 @@
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, 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 54633ad..dbd0a0c 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -40,6 +40,8 @@
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 @@
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 @@
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 @@
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 e646f5b..eaf6a47 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -57,10 +57,27 @@
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 @@
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 @@
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 @@
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 @@
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 31095c4..a733134 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -244,48 +244,90 @@
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);
- 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));
+ 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, AddDuplicateOverlayableSamePolicyFail) {
+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()));
+
+ 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, 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 81a2c2e..da541be 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -49,6 +49,9 @@
// 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 @@
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 @@
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 @@
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 61ebd4e..c496ff0 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -434,6 +434,8 @@
return false;
}
+ auto overlayable = std::make_shared<Overlayable>();
+
ResChunkPullParser parser(GetChunkData(chunk),
GetChunkDataLen(chunk));
while (ResChunkPullParser::IsGoodEvent(parser.Next())) {
@@ -441,25 +443,25 @@
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 @@
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 200e2d4..931d57b 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -429,29 +429,29 @@
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 e99ab1f..a5fb6fd 100644
--- a/tools/aapt2/format/binary/TableFlattener_test.cpp
+++ b/tools/aapt2/format/binary/TableFlattener_test.cpp
@@ -628,17 +628,17 @@
}
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 @@
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;
+ 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";
- Overlayable overlayable_one{};
- overlayable_one.policies |= Overlayable::Policy::kPublic;
- overlayable_one.policies |= Overlayable::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";
- Overlayable overlayable_two{};
- overlayable_two.policies |= Overlayable::Policy::kProduct;
- overlayable_two.policies |= Overlayable::Policy::kSystem;
- overlayable_two.policies |= Overlayable::Policy::kVendor;
+ 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";
- Overlayable overlayable_three{};
+ 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 @@
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 cf2ab0f..6b5746d 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -373,9 +373,44 @@
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 @@
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 @@
}
}
+ // 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 70bf868..76fbb46 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -272,9 +272,57 @@
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 @@
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 fb913f40..4a3c1b8 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -93,8 +93,11 @@
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 @@
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, 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 @@
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 8cbc037..c2340ba 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -374,8 +374,8 @@
}
// 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 22e1723..cc9fed5 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -134,18 +134,18 @@
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 17b2a83..921d634 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -437,14 +437,16 @@
}
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 @@
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 @@
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 @@
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 9c5b5d3..24cd5ba 100644
--- a/tools/aapt2/split/TableSplitter.cpp
+++ b/tools/aapt2/split/TableSplitter.cpp
@@ -248,7 +248,7 @@
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 884ec38..9a93f2a 100644
--- a/tools/aapt2/test/Builders.cpp
+++ b/tools/aapt2/test/Builders.cpp
@@ -136,7 +136,7 @@
}
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 a120484..c971a1b 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -74,7 +74,7 @@
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();