[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/cmd/Link_test.cpp b/tools/aapt2/cmd/Link_test.cpp
index 32ed1dd..bf8f043 100644
--- a/tools/aapt2/cmd/Link_test.cpp
+++ b/tools/aapt2/cmd/Link_test.cpp
@@ -171,4 +171,86 @@
   EXPECT_FALSE(file->WasCompressed());
 }
 
-}  // namespace aapt
\ No newline at end of file
+TEST_F(LinkTest, OverlayStyles) {
+  StdErrDiagnostics diag;
+  const std::string compiled_files_dir = GetTestPath("compiled");
+  const std::string override_files_dir = GetTestPath("compiled-override");
+  ASSERT_TRUE(CompileFile(GetTestPath("res/values/values.xml"),
+                          R"(<resources>
+                               <style name="MyStyle">
+                                 <item name="android:textColor">#123</item>
+                               </style>
+                             </resources>)",
+                          compiled_files_dir, &diag));
+  ASSERT_TRUE(CompileFile(GetTestPath("res/values/values-override.xml"),
+                          R"(<resources>
+                               <style name="MyStyle">
+                                 <item name="android:background">#456</item>
+                               </style>
+                             </resources>)",
+                          override_files_dir, &diag));
+
+
+  const std::string out_apk = GetTestPath("out.apk");
+  std::vector<std::string> link_args = {
+      "--manifest", GetDefaultManifest(kDefaultPackageName),
+      "-o", out_apk,
+  };
+  const auto override_files = file::FindFiles(override_files_dir, &diag);
+  for (const auto &override_file : override_files.value()) {
+      link_args.push_back("-R");
+      link_args.push_back(file::BuildPath({override_files_dir, override_file}));
+  }
+  ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
+
+  std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+  const Style* actual_style = test::GetValue<Style>(
+      apk->GetResourceTable(), std::string(kDefaultPackageName) + ":style/MyStyle");
+  ASSERT_NE(actual_style, nullptr);
+  ASSERT_EQ(actual_style->entries.size(), 2);
+  EXPECT_EQ(actual_style->entries[0].key.id, 0x01010098);  // android:textColor
+  EXPECT_EQ(actual_style->entries[1].key.id, 0x010100d4);  // android:background
+}
+
+TEST_F(LinkTest, OverrideStylesInsteadOfOverlaying) {
+  StdErrDiagnostics diag;
+  const std::string compiled_files_dir = GetTestPath("compiled");
+  const std::string override_files_dir = GetTestPath("compiled-override");
+  ASSERT_TRUE(CompileFile(GetTestPath("res/values/values.xml"),
+                          R"(<resources>
+                               <style name="MyStyle">
+                                 <item name="android:textColor">#123</item>
+                               </style>
+                             </resources>)",
+                          compiled_files_dir, &diag));
+  ASSERT_TRUE(CompileFile(GetTestPath("res/values/values-override.xml"),
+                          R"(<resources>
+                               <style name="MyStyle">
+                                 <item name="android:background">#456</item>
+                               </style>
+                             </resources>)",
+                          override_files_dir, &diag));
+
+
+  const std::string out_apk = GetTestPath("out.apk");
+  std::vector<std::string> link_args = {
+      "--manifest", GetDefaultManifest(kDefaultPackageName),
+      "--override-styles-instead-of-overlaying",
+      "-o", out_apk,
+  };
+  const auto override_files = file::FindFiles(override_files_dir, &diag);
+  for (const auto &override_file : override_files.value()) {
+      link_args.push_back("-R");
+      link_args.push_back(file::BuildPath({override_files_dir, override_file}));
+  }
+  ASSERT_TRUE(Link(link_args, compiled_files_dir, &diag));
+
+  std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(out_apk, &diag);
+  const Style* actual_style = test::GetValue<Style>(
+      apk->GetResourceTable(), std::string(kDefaultPackageName) + ":style/MyStyle");
+  ASSERT_NE(actual_style, nullptr);
+  ASSERT_EQ(actual_style->entries.size(), 1);
+  EXPECT_EQ(actual_style->entries[0].key.id, 0x010100d4);  // android:background
+}
+
+}  // namespace aapt