Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7a031ae8 authored by Donald Chai's avatar Donald Chai Committed by Android (Google) Code Review
Browse files

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

parents 06eb3c41 121c6e8a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1691,6 +1691,8 @@ class Linker {

    TableMergerOptions table_merger_options;
    table_merger_options.auto_add_overlay = options_.auto_add_overlay;
    table_merger_options.override_styles_instead_of_overlaying =
        options_.override_styles_instead_of_overlaying;
    table_merger_options.strict_visibility = options_.strict_visibility;
    table_merger_ = util::make_unique<TableMerger>(context_, &final_table_, table_merger_options);

+5 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ struct LinkOptions {
  std::vector<std::string> assets_dirs;
  bool output_to_directory = false;
  bool auto_add_overlay = false;
  bool override_styles_instead_of_overlaying = false;
  OutputFormat output_format = OutputFormat::kApk;

  // Java/Proguard options.
@@ -242,6 +243,10 @@ class LinkCommand : public Command {
        "Allows the addition of new resources in overlays without\n"
            "<add-resource> tags.",
        &options_.auto_add_overlay);
    AddOptionalSwitch("--override-styles-instead-of-overlaying",
                      "Causes styles defined in -R resources to replace previous definitions\n"
                      "instead of merging into them\n",
                      &options_.override_styles_instead_of_overlaying);
    AddOptionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml.",
        &options_.manifest_fixer_options.rename_manifest_package);
    AddOptionalFlag("--rename-instrumentation-target-package",
+83 −1
Original line number Diff line number Diff line
@@ -171,4 +171,86 @@ TEST_F(LinkTest, NoCompressResources) {
  EXPECT_FALSE(file->WasCompressed());
}

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
+16 −11
Original line number Diff line number Diff line
@@ -172,7 +172,8 @@ static bool MergeEntry(IAaptContext* context, const Source& src,
//
// 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,
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)) {
@@ -180,13 +181,15 @@ static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Val
      existing_styleable->MergeWith(incoming_styleable);
      return ResourceTable::CollisionResult::kKeepOriginal;
    }
  } else if (Style* existing_style = ValueCast<Style>(existing)) {
  } 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.
  return ResourceTable::ResolveValueCollision(existing, incoming);
}
@@ -194,6 +197,7 @@ static ResourceTable::CollisionResult ResolveMergeCollision(Value* existing, Val
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 @@ static ResourceTable::CollisionResult MergeConfigValue(IAaptContext* context,

  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 @@ bool TableMerger::DoMerge(const Source& src, ResourceTablePackage* src_package,
        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;
+2 −0
Original line number Diff line number Diff line
@@ -37,6 +37,8 @@ struct TableMergerOptions {
  bool auto_add_overlay = false;
  // If true, resource overlays with conflicting visibility are not allowed.
  bool strict_visibility = false;
  // If true, styles specified via "aapt2 link -R" completely replace any previously-seen resources.
  bool override_styles_instead_of_overlaying = false;
};

// TableMerger takes resource tables and merges all packages within the tables that have the same
Loading