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

Commit 4bdd3ac4 authored by felkachang's avatar felkachang
Browse files

Rename ResourcePathShortener to Obfuscator

ResourcePathShortener is a part of Obfuscator. Obfuscator will not
only shorten the path but also handle obfuscating resource names.

Format C++ code by clang-format.

Bug: 228192695

Test: atest aapt2_test idmap2_test
Change-Id: I27b4b1af44061e3cd8a6717ffd46b8a187cdc41d
parent c0009623
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -130,7 +130,7 @@ cc_library_host_static {
        "optimize/MultiApkGenerator.cpp",
        "optimize/ResourceDeduper.cpp",
        "optimize/ResourceFilter.cpp",
        "optimize/ResourcePathShortener.cpp",
        "optimize/Obfuscator.cpp",
        "optimize/VersionCollapser.cpp",
        "process/SymbolTable.cpp",
        "split/TableSplitter.cpp",
+9 −5
Original line number Diff line number Diff line
@@ -16,7 +16,11 @@

#include "Optimize.h"

#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "Diagnostics.h"
@@ -38,9 +42,9 @@
#include "io/BigBufferStream.h"
#include "io/Util.h"
#include "optimize/MultiApkGenerator.h"
#include "optimize/Obfuscator.h"
#include "optimize/ResourceDeduper.h"
#include "optimize/ResourceFilter.h"
#include "optimize/ResourcePathShortener.h"
#include "optimize/VersionCollapser.h"
#include "split/TableSplitter.h"
#include "util/Files.h"
@@ -114,11 +118,11 @@ class OptimizeContext : public IAaptContext {
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(OptimizeContext);

  StdErrDiagnostics diagnostics_;
  bool verbose_ = false;
  int sdk_version_ = 0;

  DISALLOW_COPY_AND_ASSIGN(OptimizeContext);
};

class Optimizer {
@@ -151,8 +155,8 @@ class Optimizer {
    }

    if (options_.shorten_resource_paths) {
      ResourcePathShortener shortener(options_.table_flattener_options.shortened_path_map);
      if (!shortener.Consume(context_, apk->GetResourceTable())) {
      Obfuscator obfuscator(options_.table_flattener_options.shortened_path_map);
      if (!obfuscator.Consume(context_, apk->GetResourceTable())) {
        context_->GetDiagnostics()->Error(android::DiagMessage()
                                          << "failed shortening resource paths");
        return 1;
+14 −19
Original line number Diff line number Diff line
@@ -14,28 +14,25 @@
 * limitations under the License.
 */

#include "optimize/ResourcePathShortener.h"
#include "optimize/Obfuscator.h"

#include <set>
#include <string>
#include <unordered_set>

#include "androidfw/StringPiece.h"

#include "ResourceTable.h"
#include "ValueVisitor.h"
#include "androidfw/StringPiece.h"
#include "util/Util.h"


static const std::string base64_chars =
static const char base64_chars[] =
    "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    "abcdefghijklmnopqrstuvwxyz"
    "0123456789-_";

namespace aapt {

ResourcePathShortener::ResourcePathShortener(
    std::map<std::string, std::string>& path_map_out)
    : path_map_(path_map_out) {
Obfuscator::Obfuscator(std::map<std::string, std::string>& path_map_out) : path_map_(path_map_out) {
}

std::string ShortenFileName(const android::StringPiece& file_path, int output_length) {
@@ -50,7 +47,6 @@ std::string ShortenFileName(const android::StringPiece& file_path, int output_le
  return result;
}


// Return the optimal hash length such that at most 10% of resources collide in
// their shortened path.
// Reference: http://matt.might.net/articles/counting-hash-collisions/
@@ -81,7 +77,7 @@ struct PathComparator {
  }
};

bool ResourcePathShortener::Consume(IAaptContext* context, ResourceTable* table) {
bool Obfuscator::Consume(IAaptContext* context, ResourceTable* table) {
  // used to detect collisions
  std::unordered_set<std::string> shortened_paths;
  std::set<FileReference*, PathComparator> file_refs;
@@ -103,8 +99,7 @@ bool ResourcePathShortener::Consume(IAaptContext* context, ResourceTable* table)
    util::ExtractResFilePathParts(*file_ref->path, &res_subdir, &actual_filename, &extension);

    // Android detects ColorStateLists via pathname, skip res/color*
    if (util::StartsWith(res_subdir, "res/color"))
      continue;
    if (util::StartsWith(res_subdir, "res/color")) continue;

    std::string shortened_filename = ShortenFileName(*file_ref->path, num_chars);
    int collision_count = 0;
+8 −8
Original line number Diff line number Diff line
@@ -14,13 +14,13 @@
 * limitations under the License.
 */

#ifndef AAPT_OPTIMIZE_RESOURCEPATHSHORTENER_H
#define AAPT_OPTIMIZE_RESOURCEPATHSHORTENER_H
#ifndef TOOLS_AAPT2_OPTIMIZE_OBFUSCATOR_H_
#define TOOLS_AAPT2_OPTIMIZE_OBFUSCATOR_H_

#include <map>
#include <string>

#include "android-base/macros.h"

#include "process/IResourceTableConsumer.h"

namespace aapt {
@@ -28,17 +28,17 @@ namespace aapt {
class ResourceTable;

// Maps resources in the apk to shortened paths.
class ResourcePathShortener : public IResourceTableConsumer {
class Obfuscator : public IResourceTableConsumer {
 public:
  explicit ResourcePathShortener(std::map<std::string, std::string>& path_map_out);
  explicit Obfuscator(std::map<std::string, std::string>& path_map_out);

  bool Consume(IAaptContext* context, ResourceTable* table) override;

 private:
  DISALLOW_COPY_AND_ASSIGN(ResourcePathShortener);
  std::map<std::string, std::string>& path_map_;
  DISALLOW_COPY_AND_ASSIGN(Obfuscator);
};

}  // namespace aapt

#endif  // AAPT_OPTIMIZE_RESOURCEPATHSHORTENER_H
#endif  // TOOLS_AAPT2_OPTIMIZE_OBFUSCATOR_H_
+23 −24
Original line number Diff line number Diff line
@@ -14,15 +14,18 @@
 * limitations under the License.
 */

#include "optimize/ResourcePathShortener.h"
#include "optimize/Obfuscator.h"

#include <memory>
#include <string>

#include "ResourceTable.h"
#include "test/Test.h"

using ::aapt::test::GetValue;
using ::testing::Eq;
using ::testing::Not;
using ::testing::NotNull;
using ::testing::Eq;

android::StringPiece GetExtension(android::StringPiece path) {
  auto iter = std::find(path.begin(), path.end(), '.');
@@ -31,15 +34,14 @@ android::StringPiece GetExtension(android::StringPiece path) {

void FillTable(aapt::test::ResourceTableBuilder& builder, int start, int end) {
  for (int i = start; i < end; i++) {
    builder.AddFileReference(
        "android:drawable/xmlfile" + std::to_string(i),
    builder.AddFileReference("android:drawable/xmlfile" + std::to_string(i),
                             "res/drawable/xmlfile" + std::to_string(i) + ".xml");
  }
}

namespace aapt {

TEST(ResourcePathShortenerTest, FileRefPathsChangedInResourceTable) {
TEST(ObfuscatorTest, FileRefPathsChangedInResourceTable) {
  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();

  std::unique_ptr<ResourceTable> table =
@@ -50,7 +52,7 @@ TEST(ResourcePathShortenerTest, FileRefPathsChangedInResourceTable) {
          .Build();

  std::map<std::string, std::string> path_map;
  ASSERT_TRUE(ResourcePathShortener(path_map).Consume(context.get(), table.get()));
  ASSERT_TRUE(Obfuscator(path_map).Consume(context.get(), table.get()));

  // Expect that the path map is populated
  ASSERT_THAT(path_map.find("res/drawables/xmlfile.xml"), Not(Eq(path_map.end())));
@@ -64,39 +66,36 @@ TEST(ResourcePathShortenerTest, FileRefPathsChangedInResourceTable) {
  EXPECT_THAT(path_map["res/drawables/xmlfile.xml"],
              Not(Eq(path_map["res/drawables/xmlfile2.xml"])));

  FileReference* ref =
      GetValue<FileReference>(table.get(), "android:drawable/xmlfile");
  FileReference* ref = GetValue<FileReference>(table.get(), "android:drawable/xmlfile");
  ASSERT_THAT(ref, NotNull());
  // The map correctly points to the new location of the file
  EXPECT_THAT(path_map["res/drawables/xmlfile.xml"], Eq(*ref->path));

  // Strings should not be affected, only file paths
  EXPECT_THAT(
      *GetValue<String>(table.get(), "android:string/string")->value,
  EXPECT_THAT(*GetValue<String>(table.get(), "android:string/string")->value,
              Eq("res/should/still/be/the/same.png"));
  EXPECT_THAT(path_map.find("res/should/still/be/the/same.png"), Eq(path_map.end()));
}

TEST(ResourcePathShortenerTest, SkipColorFileRefPaths) {
TEST(ObfuscatorTest, SkipColorFileRefPaths) {
  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();

  std::unique_ptr<ResourceTable> table =
      test::ResourceTableBuilder()
          .AddFileReference("android:color/colorlist", "res/color/colorlist.xml")
          .AddFileReference("android:color/colorlist",
                            "res/color-mdp-v21/colorlist.xml",
          .AddFileReference("android:color/colorlist", "res/color-mdp-v21/colorlist.xml",
                            test::ParseConfigOrDie("mdp-v21"))
          .Build();

  std::map<std::string, std::string> path_map;
  ASSERT_TRUE(ResourcePathShortener(path_map).Consume(context.get(), table.get()));
  ASSERT_TRUE(Obfuscator(path_map).Consume(context.get(), table.get()));

  // Expect that the path map to not contain the ColorStateList
  ASSERT_THAT(path_map.find("res/color/colorlist.xml"), Eq(path_map.end()));
  ASSERT_THAT(path_map.find("res/color-mdp-v21/colorlist.xml"), Eq(path_map.end()));
}

TEST(ResourcePathShortenerTest, KeepExtensions) {
TEST(ObfuscatorTest, KeepExtensions) {
  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();

  std::string original_xml_path = "res/drawable/xmlfile.xml";
@@ -109,7 +108,7 @@ TEST(ResourcePathShortenerTest, KeepExtensions) {
          .Build();

  std::map<std::string, std::string> path_map;
  ASSERT_TRUE(ResourcePathShortener(path_map).Consume(context.get(), table.get()));
  ASSERT_TRUE(Obfuscator(path_map).Consume(context.get(), table.get()));

  // Expect that the path map is populated
  ASSERT_THAT(path_map.find("res/drawable/xmlfile.xml"), Not(Eq(path_map.end())));
@@ -122,7 +121,7 @@ TEST(ResourcePathShortenerTest, KeepExtensions) {
  EXPECT_THAT(GetExtension(path_map[original_png_path]), Eq(android::StringPiece(".png")));
}

TEST(ResourcePathShortenerTest, DeterministicallyHandleCollisions) {
TEST(ObfuscatorTest, DeterministicallyHandleCollisions) {
  std::unique_ptr<IAaptContext> context = test::ContextBuilder().Build();

  // 4000 resources is the limit at which the hash space is expanded to 3
@@ -135,7 +134,7 @@ TEST(ResourcePathShortenerTest, DeterministicallyHandleCollisions) {
  FillTable(builder1, 0, kNumResources);
  std::unique_ptr<ResourceTable> table1 = builder1.Build();
  std::map<std::string, std::string> expected_mapping;
  ASSERT_TRUE(ResourcePathShortener(expected_mapping).Consume(context.get(), table1.get()));
  ASSERT_TRUE(Obfuscator(expected_mapping).Consume(context.get(), table1.get()));

  // We are trying to ensure lack of non-determinism, it is not simple to prove
  // a negative, thus we must try the test a few times so that the test itself
@@ -155,7 +154,7 @@ TEST(ResourcePathShortenerTest, DeterministicallyHandleCollisions) {
    std::unique_ptr<ResourceTable> table2 = builder2.Build();

    std::map<std::string, std::string> actual_mapping;
    ASSERT_TRUE(ResourcePathShortener(actual_mapping).Consume(context.get(), table2.get()));
    ASSERT_TRUE(Obfuscator(actual_mapping).Consume(context.get(), table2.get()));

    for (auto& item : actual_mapping) {
      ASSERT_THAT(expected_mapping[item.first], Eq(item.second));