Loading tools/aapt2/cmd/Link.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading tools/aapt2/cmd/Link.h +5 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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", Loading tools/aapt2/cmd/Link_test.cpp +83 −1 Original line number Diff line number Diff line Loading @@ -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 tools/aapt2/link/TableMerger.cpp +16 −11 Original line number Diff line number Diff line Loading @@ -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)) { Loading @@ -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); } Loading @@ -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) { Loading @@ -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); } Loading Loading @@ -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; Loading tools/aapt2/link/TableMerger.h +2 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
tools/aapt2/cmd/Link.cpp +2 −0 Original line number Diff line number Diff line Loading @@ -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); Loading
tools/aapt2/cmd/Link.h +5 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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", Loading
tools/aapt2/cmd/Link_test.cpp +83 −1 Original line number Diff line number Diff line Loading @@ -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
tools/aapt2/link/TableMerger.cpp +16 −11 Original line number Diff line number Diff line Loading @@ -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)) { Loading @@ -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); } Loading @@ -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) { Loading @@ -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); } Loading Loading @@ -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; Loading
tools/aapt2/link/TableMerger.h +2 −0 Original line number Diff line number Diff line Loading @@ -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