Loading tools/aapt2/cmd/Optimize.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -161,6 +161,15 @@ class Optimizer { << "failed shortening resource paths"); return 1; } if (options_.obfuscation_map_path && !obfuscator.WriteObfuscationMap(options_.obfuscation_map_path.value())) { context_->GetDiagnostics()->Error(android::DiagMessage() << "failed to write the obfuscation map to file"); return 1; } // TODO(b/246489170): keep the old option and format until transform to the new one if (options_.shortened_paths_map_path && !WriteShortenedPathsMap(options_.table_flattener_options.shortened_path_map, options_.shortened_paths_map_path.value())) { Loading Loading @@ -292,6 +301,7 @@ class Optimizer { ArchiveEntry::kAlign, writer); } // TODO(b/246489170): keep the old option and format until transform to the new one bool WriteShortenedPathsMap(const std::map<std::string, std::string> &path_map, const std::string &file_path) { std::stringstream ss; Loading tools/aapt2/cmd/Optimize.h +10 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ struct OptimizeOptions { bool shorten_resource_paths = false; // Path to the output map of original resource paths to shortened paths. // TODO(b/246489170): keep the old option and format until transform to the new one std::optional<std::string> shortened_paths_map_path; // Whether sparse encoding should be used for O+ resources. Loading @@ -65,6 +66,9 @@ struct OptimizeOptions { // Whether sparse encoding should be used for all resources. bool force_sparse_encoding = false; // Path to the output map of original resource paths/names to obfuscated paths/names. std::optional<std::string> obfuscation_map_path; }; class OptimizeCommand : public Command { Loading Loading @@ -120,9 +124,13 @@ class OptimizeCommand : public Command { AddOptionalSwitch("--shorten-resource-paths", "Shortens the paths of resources inside the APK.", &options_.shorten_resource_paths); // TODO(b/246489170): keep the old option and format until transform to the new one AddOptionalFlag("--resource-path-shortening-map", "Path to output the map of old resource paths to shortened paths.", "[Deprecated]Path to output the map of old resource paths to shortened paths.", &options_.shortened_paths_map_path); AddOptionalFlag("--save-obfuscation-map", "Path to output the map of original paths/names to obfuscated paths/names.", &options_.obfuscation_map_path); AddOptionalSwitch( "--deduplicate-entry-values", "Whether to deduplicate pairs of resource entry and value for simple resources.\n" Loading tools/aapt2/optimize/Obfuscator.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "optimize/Obfuscator.h" #include <fstream> #include <map> #include <set> #include <string> Loading Loading @@ -192,6 +193,29 @@ bool Obfuscator::Consume(IAaptContext* context, ResourceTable* table) { return true; } bool Obfuscator::WriteObfuscationMap(const std::string& file_path) const { pb::ResourceMappings resourceMappings; for (const auto& [id, name] : options_.id_resource_map) { auto* collapsedNameMapping = resourceMappings.mutable_collapsed_names()->add_resource_names(); collapsedNameMapping->set_id(id); collapsedNameMapping->set_name(name); } for (const auto& [original_path, shortened_path] : options_.shortened_path_map) { auto* resource_path = resourceMappings.mutable_shortened_paths()->add_resource_paths(); resource_path->set_original_path(original_path); resource_path->set_shortened_path(shortened_path); } { // RAII style, output the pb content to file and close fout in destructor std::ofstream fout(file_path, std::ios::out | std::ios::trunc | std::ios::binary); if (!fout.is_open()) { return false; } return resourceMappings.SerializeToOstream(&fout); } } /** * Tell the optimizer whether it's needed to dump information for de-obfuscating. * Loading tools/aapt2/optimize/Obfuscator.h +3 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <set> #include <string> #include "ResourceMetadata.pb.h" #include "ResourceTable.h" #include "android-base/function_ref.h" #include "android-base/macros.h" Loading @@ -38,6 +39,8 @@ class Obfuscator : public IResourceTableConsumer { bool Consume(IAaptContext* context, ResourceTable* table) override; bool WriteObfuscationMap(const std::string& file_path) const; bool IsEnabled() const; enum class Result { Obfuscated, Keep_ExemptionList, Keep_Overlayable }; Loading tools/aapt2/optimize/Obfuscator_test.cpp +60 −0 Original line number Diff line number Diff line Loading @@ -21,10 +21,14 @@ #include <string> #include "ResourceTable.h" #include "android-base/file.h" #include "test/Test.h" using ::aapt::test::GetValue; using ::testing::AnyOf; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsTrue; using ::testing::Not; using ::testing::NotNull; Loading Loading @@ -236,4 +240,60 @@ TEST(ObfuscatorTest, IsEnabledWithShortenPathAndCollapseStringPoolOption) { ASSERT_THAT(obfuscatorWithCollapseStringPoolOption.IsEnabled(), Eq(true)); } static std::unique_ptr<ResourceTable> getProtocolBufferTableUnderTest() { std::string original_xml_path = "res/drawable/xmlfile.xml"; std::string original_png_path = "res/drawable/pngfile.png"; return test::ResourceTableBuilder() .AddFileReference("com.app.test:drawable/xmlfile", original_xml_path) .AddFileReference("com.app.test:drawable/pngfile", original_png_path) .AddValue("com.app.test:color/mycolor", aapt::ResourceId(0x7f020000), aapt::util::make_unique<aapt::BinaryPrimitive>( uint8_t(android::Res_value::TYPE_INT_COLOR_ARGB8), 0xffaabbcc)) .AddString("com.app.test:string/mystring", ResourceId(0x7f030000), "hello world") .Build(); } TEST(ObfuscatorTest, WriteObfuscationMapInProtocolBufferFormat) { OptimizeOptions options{.shorten_resource_paths = true}; options.table_flattener_options.collapse_key_stringpool = true; Obfuscator obfuscator(options); ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(), getProtocolBufferTableUnderTest().get())); obfuscator.WriteObfuscationMap("obfuscated_map.pb"); std::string pbOut; android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */); EXPECT_THAT(pbOut, HasSubstr("drawable/xmlfile.xml")); EXPECT_THAT(pbOut, HasSubstr("drawable/pngfile.png")); EXPECT_THAT(pbOut, HasSubstr("mycolor")); EXPECT_THAT(pbOut, HasSubstr("mystring")); pb::ResourceMappings resourceMappings; EXPECT_THAT(resourceMappings.ParseFromString(pbOut), IsTrue()); EXPECT_THAT(resourceMappings.collapsed_names().resource_names_size(), Eq(2)); auto& resource_names = resourceMappings.collapsed_names().resource_names(); EXPECT_THAT(resource_names.at(0).name(), AnyOf(Eq("mycolor"), Eq("mystring"))); EXPECT_THAT(resource_names.at(1).name(), AnyOf(Eq("mycolor"), Eq("mystring"))); auto& shortened_paths = resourceMappings.shortened_paths(); EXPECT_THAT(shortened_paths.resource_paths_size(), Eq(2)); EXPECT_THAT(shortened_paths.resource_paths(0).original_path(), AnyOf(Eq("res/drawable/pngfile.png"), Eq("res/drawable/xmlfile.xml"))); EXPECT_THAT(shortened_paths.resource_paths(1).original_path(), AnyOf(Eq("res/drawable/pngfile.png"), Eq("res/drawable/xmlfile.xml"))); } TEST(ObfuscatorTest, WriteObfuscatingMapWithNonEnabledOption) { OptimizeOptions options; Obfuscator obfuscator(options); ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(), getProtocolBufferTableUnderTest().get())); obfuscator.WriteObfuscationMap("obfuscated_map.pb"); std::string pbOut; android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */); ASSERT_THAT(pbOut, Eq("")); } } // namespace aapt Loading
tools/aapt2/cmd/Optimize.cpp +10 −0 Original line number Diff line number Diff line Loading @@ -161,6 +161,15 @@ class Optimizer { << "failed shortening resource paths"); return 1; } if (options_.obfuscation_map_path && !obfuscator.WriteObfuscationMap(options_.obfuscation_map_path.value())) { context_->GetDiagnostics()->Error(android::DiagMessage() << "failed to write the obfuscation map to file"); return 1; } // TODO(b/246489170): keep the old option and format until transform to the new one if (options_.shortened_paths_map_path && !WriteShortenedPathsMap(options_.table_flattener_options.shortened_path_map, options_.shortened_paths_map_path.value())) { Loading Loading @@ -292,6 +301,7 @@ class Optimizer { ArchiveEntry::kAlign, writer); } // TODO(b/246489170): keep the old option and format until transform to the new one bool WriteShortenedPathsMap(const std::map<std::string, std::string> &path_map, const std::string &file_path) { std::stringstream ss; Loading
tools/aapt2/cmd/Optimize.h +10 −2 Original line number Diff line number Diff line Loading @@ -58,6 +58,7 @@ struct OptimizeOptions { bool shorten_resource_paths = false; // Path to the output map of original resource paths to shortened paths. // TODO(b/246489170): keep the old option and format until transform to the new one std::optional<std::string> shortened_paths_map_path; // Whether sparse encoding should be used for O+ resources. Loading @@ -65,6 +66,9 @@ struct OptimizeOptions { // Whether sparse encoding should be used for all resources. bool force_sparse_encoding = false; // Path to the output map of original resource paths/names to obfuscated paths/names. std::optional<std::string> obfuscation_map_path; }; class OptimizeCommand : public Command { Loading Loading @@ -120,9 +124,13 @@ class OptimizeCommand : public Command { AddOptionalSwitch("--shorten-resource-paths", "Shortens the paths of resources inside the APK.", &options_.shorten_resource_paths); // TODO(b/246489170): keep the old option and format until transform to the new one AddOptionalFlag("--resource-path-shortening-map", "Path to output the map of old resource paths to shortened paths.", "[Deprecated]Path to output the map of old resource paths to shortened paths.", &options_.shortened_paths_map_path); AddOptionalFlag("--save-obfuscation-map", "Path to output the map of original paths/names to obfuscated paths/names.", &options_.obfuscation_map_path); AddOptionalSwitch( "--deduplicate-entry-values", "Whether to deduplicate pairs of resource entry and value for simple resources.\n" Loading
tools/aapt2/optimize/Obfuscator.cpp +24 −0 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include "optimize/Obfuscator.h" #include <fstream> #include <map> #include <set> #include <string> Loading Loading @@ -192,6 +193,29 @@ bool Obfuscator::Consume(IAaptContext* context, ResourceTable* table) { return true; } bool Obfuscator::WriteObfuscationMap(const std::string& file_path) const { pb::ResourceMappings resourceMappings; for (const auto& [id, name] : options_.id_resource_map) { auto* collapsedNameMapping = resourceMappings.mutable_collapsed_names()->add_resource_names(); collapsedNameMapping->set_id(id); collapsedNameMapping->set_name(name); } for (const auto& [original_path, shortened_path] : options_.shortened_path_map) { auto* resource_path = resourceMappings.mutable_shortened_paths()->add_resource_paths(); resource_path->set_original_path(original_path); resource_path->set_shortened_path(shortened_path); } { // RAII style, output the pb content to file and close fout in destructor std::ofstream fout(file_path, std::ios::out | std::ios::trunc | std::ios::binary); if (!fout.is_open()) { return false; } return resourceMappings.SerializeToOstream(&fout); } } /** * Tell the optimizer whether it's needed to dump information for de-obfuscating. * Loading
tools/aapt2/optimize/Obfuscator.h +3 −0 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ #include <set> #include <string> #include "ResourceMetadata.pb.h" #include "ResourceTable.h" #include "android-base/function_ref.h" #include "android-base/macros.h" Loading @@ -38,6 +39,8 @@ class Obfuscator : public IResourceTableConsumer { bool Consume(IAaptContext* context, ResourceTable* table) override; bool WriteObfuscationMap(const std::string& file_path) const; bool IsEnabled() const; enum class Result { Obfuscated, Keep_ExemptionList, Keep_Overlayable }; Loading
tools/aapt2/optimize/Obfuscator_test.cpp +60 −0 Original line number Diff line number Diff line Loading @@ -21,10 +21,14 @@ #include <string> #include "ResourceTable.h" #include "android-base/file.h" #include "test/Test.h" using ::aapt::test::GetValue; using ::testing::AnyOf; using ::testing::Eq; using ::testing::HasSubstr; using ::testing::IsTrue; using ::testing::Not; using ::testing::NotNull; Loading Loading @@ -236,4 +240,60 @@ TEST(ObfuscatorTest, IsEnabledWithShortenPathAndCollapseStringPoolOption) { ASSERT_THAT(obfuscatorWithCollapseStringPoolOption.IsEnabled(), Eq(true)); } static std::unique_ptr<ResourceTable> getProtocolBufferTableUnderTest() { std::string original_xml_path = "res/drawable/xmlfile.xml"; std::string original_png_path = "res/drawable/pngfile.png"; return test::ResourceTableBuilder() .AddFileReference("com.app.test:drawable/xmlfile", original_xml_path) .AddFileReference("com.app.test:drawable/pngfile", original_png_path) .AddValue("com.app.test:color/mycolor", aapt::ResourceId(0x7f020000), aapt::util::make_unique<aapt::BinaryPrimitive>( uint8_t(android::Res_value::TYPE_INT_COLOR_ARGB8), 0xffaabbcc)) .AddString("com.app.test:string/mystring", ResourceId(0x7f030000), "hello world") .Build(); } TEST(ObfuscatorTest, WriteObfuscationMapInProtocolBufferFormat) { OptimizeOptions options{.shorten_resource_paths = true}; options.table_flattener_options.collapse_key_stringpool = true; Obfuscator obfuscator(options); ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(), getProtocolBufferTableUnderTest().get())); obfuscator.WriteObfuscationMap("obfuscated_map.pb"); std::string pbOut; android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */); EXPECT_THAT(pbOut, HasSubstr("drawable/xmlfile.xml")); EXPECT_THAT(pbOut, HasSubstr("drawable/pngfile.png")); EXPECT_THAT(pbOut, HasSubstr("mycolor")); EXPECT_THAT(pbOut, HasSubstr("mystring")); pb::ResourceMappings resourceMappings; EXPECT_THAT(resourceMappings.ParseFromString(pbOut), IsTrue()); EXPECT_THAT(resourceMappings.collapsed_names().resource_names_size(), Eq(2)); auto& resource_names = resourceMappings.collapsed_names().resource_names(); EXPECT_THAT(resource_names.at(0).name(), AnyOf(Eq("mycolor"), Eq("mystring"))); EXPECT_THAT(resource_names.at(1).name(), AnyOf(Eq("mycolor"), Eq("mystring"))); auto& shortened_paths = resourceMappings.shortened_paths(); EXPECT_THAT(shortened_paths.resource_paths_size(), Eq(2)); EXPECT_THAT(shortened_paths.resource_paths(0).original_path(), AnyOf(Eq("res/drawable/pngfile.png"), Eq("res/drawable/xmlfile.xml"))); EXPECT_THAT(shortened_paths.resource_paths(1).original_path(), AnyOf(Eq("res/drawable/pngfile.png"), Eq("res/drawable/xmlfile.xml"))); } TEST(ObfuscatorTest, WriteObfuscatingMapWithNonEnabledOption) { OptimizeOptions options; Obfuscator obfuscator(options); ASSERT_TRUE(obfuscator.Consume(test::ContextBuilder().Build().get(), getProtocolBufferTableUnderTest().get())); obfuscator.WriteObfuscationMap("obfuscated_map.pb"); std::string pbOut; android::base::ReadFileToString("obfuscated_map.pb", &pbOut, false /* follow_symlinks */); ASSERT_THAT(pbOut, Eq("")); } } // namespace aapt