diff options
-rw-r--r-- | tools/aapt2/cmd/Optimize.cpp | 10 | ||||
-rw-r--r-- | tools/aapt2/cmd/Optimize.h | 12 | ||||
-rw-r--r-- | tools/aapt2/optimize/Obfuscator.cpp | 24 | ||||
-rw-r--r-- | tools/aapt2/optimize/Obfuscator.h | 3 | ||||
-rw-r--r-- | tools/aapt2/optimize/Obfuscator_test.cpp | 60 |
5 files changed, 107 insertions, 2 deletions
diff --git a/tools/aapt2/cmd/Optimize.cpp b/tools/aapt2/cmd/Optimize.cpp index f7f2f22ca293..d7a39bfb8c0b 100644 --- a/tools/aapt2/cmd/Optimize.cpp +++ b/tools/aapt2/cmd/Optimize.cpp @@ -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())) { @@ -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; diff --git a/tools/aapt2/cmd/Optimize.h b/tools/aapt2/cmd/Optimize.h index 794a87b0faa5..1879f25bc1b0 100644 --- a/tools/aapt2/cmd/Optimize.h +++ b/tools/aapt2/cmd/Optimize.h @@ -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. @@ -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 { @@ -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.", - &options_.shortened_paths_map_path); + "[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" diff --git a/tools/aapt2/optimize/Obfuscator.cpp b/tools/aapt2/optimize/Obfuscator.cpp index 2533f8079c39..cc21093084b5 100644 --- a/tools/aapt2/optimize/Obfuscator.cpp +++ b/tools/aapt2/optimize/Obfuscator.cpp @@ -16,6 +16,7 @@ #include "optimize/Obfuscator.h" +#include <fstream> #include <map> #include <set> #include <string> @@ -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. * diff --git a/tools/aapt2/optimize/Obfuscator.h b/tools/aapt2/optimize/Obfuscator.h index 786bf8c9ed93..5ccf54383aae 100644 --- a/tools/aapt2/optimize/Obfuscator.h +++ b/tools/aapt2/optimize/Obfuscator.h @@ -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" @@ -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 }; diff --git a/tools/aapt2/optimize/Obfuscator_test.cpp b/tools/aapt2/optimize/Obfuscator_test.cpp index 17d1e5262b76..7f57b71ddf76 100644 --- a/tools/aapt2/optimize/Obfuscator_test.cpp +++ b/tools/aapt2/optimize/Obfuscator_test.cpp @@ -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; @@ -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 |