Allow merging of resources with the same overlayable
If a resource is redefined with the same overlayable name, actor, and
policies, do not error.
Bug: 128843658
Test: m -j Launcher3 && aapt2_tests
Change-Id: I2c79f7d9fa7ff16b38ec41cec7e9804d39b372d5
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index a24e0d2f..c0802e6 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -138,17 +138,29 @@
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_item.value().source)
- << "duplicate overlayable declaration for resource '"
- << src_entry->name << "'");
- context->GetDiagnostics()->Error(DiagMessage(dst_entry->overlayable_item.value().source)
- << "previous declaration here");
- return false;
- } else {
- dst_entry->overlayable_item = std::move(src_entry->overlayable_item);
+ CHECK(src_entry->overlayable_item.value().overlayable != nullptr);
+ Overlayable* src_overlayable = src_entry->overlayable_item.value().overlayable.get();
+
+ CHECK(dst_entry->overlayable_item.value().overlayable != nullptr);
+ Overlayable* dst_overlayable = dst_entry->overlayable_item.value().overlayable.get();
+
+ if (src_overlayable->name != dst_overlayable->name
+ || src_overlayable->actor != dst_overlayable->actor
+ || src_entry->overlayable_item.value().policies !=
+ dst_entry->overlayable_item.value().policies) {
+
+ // Do not allow a resource with an overlayable declaration to have that overlayable
+ // declaration redefined.
+ 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_item.value().source)
+ << "previous declaration here");
+ return false;
+ }
}
+
+ dst_entry->overlayable_item = std::move(src_entry->overlayable_item);
}
return true;
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index ad3674e..9dd31e6 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -521,6 +521,35 @@
.Build();
auto overlayable_second = std::make_shared<Overlayable>("ThemeResources",
+ "overlay://customization");
+ 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_item_second)
+ .Build();
+
+ ResourceTable final_table;
+ TableMergerOptions options;
+ options.auto_add_overlay = true;
+ TableMerger merger(context_.get(), &final_table, options);
+ ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+ ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
+}
+
+TEST_F(TableMergerTest, SameResourceDifferentActorFail) {
+ 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_item_first)
+ .Build();
+
+ auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
"overlay://theme");
OverlayableItem overlayable_item_second(overlayable_second);
overlayable_item_second.policies |= OverlayableItem::Policy::kProduct;
@@ -538,11 +567,10 @@
ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
}
-TEST_F(TableMergerTest, SameResourceSameNameFail) {
- auto overlayable = std::make_shared<Overlayable>("CustomizableResources",
- "overlay://customization");
-
- OverlayableItem overlayable_item_first(overlayable);
+TEST_F(TableMergerTest, SameResourceDifferentPoliciesFail) {
+ 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()
@@ -550,8 +578,10 @@
.SetOverlayable("bool/foo", overlayable_item_first)
.Build();
- OverlayableItem overlayable_item_second(overlayable);
- overlayable_item_second.policies |= OverlayableItem::Policy::kSystem;
+ auto overlayable_second = std::make_shared<Overlayable>("CustomizableResources",
+ "overlay://customization");
+ OverlayableItem overlayable_item_second(overlayable_second);
+ overlayable_item_second.policies |= OverlayableItem::Policy::kSignature;
std::unique_ptr<ResourceTable> table_b =
test::ResourceTableBuilder()
.SetPackageId("com.app.a", 0x7f)
@@ -566,4 +596,32 @@
ASSERT_FALSE(merger.Merge({}, table_b.get(), false /*overlay*/));
}
+TEST_F(TableMergerTest, SameResourceSameOverlayable) {
+ 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_item_first)
+ .Build();
+
+ OverlayableItem overlayable_item_second(overlayable);
+ overlayable_item_second.policies |= OverlayableItem::Policy::kProduct;
+ std::unique_ptr<ResourceTable> table_b =
+ test::ResourceTableBuilder()
+ .SetPackageId("com.app.a", 0x7f)
+ .SetOverlayable("bool/foo", overlayable_item_second)
+ .Build();
+
+ ResourceTable final_table;
+ TableMergerOptions options;
+ options.auto_add_overlay = true;
+ TableMerger merger(context_.get(), &final_table, options);
+ ASSERT_TRUE(merger.Merge({}, table_a.get(), false /*overlay*/));
+ ASSERT_TRUE(merger.Merge({}, table_b.get(), false /*overlay*/));
+}
+
} // namespace aapt