[aapt2] Add "link" option to override styles instead of overlaying.

For normal app development, the desired linking semantics are:
* styleables - take union of all definitions
* all other resources - take last non-weak definition

This differs from the semantics needed in other scenarios, where
merging/overlaying styles is desired.

Bug: 134525082
Change-Id: Iac0c43ca2ecf1f3fddc9c3367f8914c12c9258e1
Tested: aapt2_tests
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index c0802e6..c25e450 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -172,19 +172,22 @@
 //
 // Styleables and Styles don't simply overlay each other, their definitions merge and accumulate.
 // If both values are Styleables/Styles, we just merge them into the existing value.
-static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Value* incoming,
-                                                            StringPool* pool) {
+static ResourceTable::CollisionResult ResolveMergeCollision(
+    bool override_styles_instead_of_overlaying, Value* existing, Value* incoming,
+    StringPool* pool) {
   if (Styleable* existing_styleable = ValueCast<Styleable>(existing)) {
     if (Styleable* incoming_styleable = ValueCast<Styleable>(incoming)) {
       // Styleables get merged.
       existing_styleable->MergeWith(incoming_styleable);
       return ResourceTable::CollisionResult::kKeepOriginal;
     }
-  } else if (Style* existing_style = ValueCast<Style>(existing)) {
-    if (Style* incoming_style = ValueCast<Style>(incoming)) {
-      // Styles get merged.
-      existing_style->MergeWith(incoming_style, pool);
-      return ResourceTable::CollisionResult::kKeepOriginal;
+  } else if (!override_styles_instead_of_overlaying) {
+    if (Style* existing_style = ValueCast<Style>(existing)) {
+      if (Style* incoming_style = ValueCast<Style>(incoming)) {
+        // Styles get merged.
+        existing_style->MergeWith(incoming_style, pool);
+        return ResourceTable::CollisionResult::kKeepOriginal;
+      }
     }
   }
   // Delegate to the default handler.
@@ -194,6 +197,7 @@
 static ResourceTable::CollisionResult MergeConfigValue(IAaptContext* context,
                                                        const ResourceNameRef& res_name,
                                                        bool overlay,
+                                                       bool override_styles_instead_of_overlaying,
                                                        ResourceConfigValue* dst_config_value,
                                                        ResourceConfigValue* src_config_value,
                                                        StringPool* pool) {
@@ -204,7 +208,8 @@
 
   CollisionResult collision_result;
   if (overlay) {
-    collision_result = ResolveMergeCollision(dst_value, src_value, pool);
+    collision_result =
+        ResolveMergeCollision(override_styles_instead_of_overlaying, dst_value, src_value, pool);
   } else {
     collision_result = ResourceTable::ResolveValueCollision(dst_value, src_value);
   }
@@ -272,9 +277,9 @@
         ResourceConfigValue* dst_config_value = dst_entry->FindValue(
             src_config_value->config, src_config_value->product);
         if (dst_config_value) {
-          CollisionResult collision_result =
-              MergeConfigValue(context_, res_name, overlay, dst_config_value,
-                               src_config_value.get(), &master_table_->string_pool);
+          CollisionResult collision_result = MergeConfigValue(
+              context_, res_name, overlay, options_.override_styles_instead_of_overlaying,
+              dst_config_value, src_config_value.get(), &master_table_->string_pool);
           if (collision_result == CollisionResult::kConflict) {
             error = true;
             continue;