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

Commit 7c757304 authored by Mohamed Heikal's avatar Mohamed Heikal
Browse files

Fix bug where path shortening breaks ColorStateLists

Android resource loader uses the file path to check if a resource is a
ColorStateList. Path shortening removed that part of the path and thus
broke the resource loader of APKs optimized with path shortening. This
cl skips path shortening for resources under "res/color/"

Test: make aapt2_tests
Bug: b/75965637

Change-Id: If94dfa398efd81522d4faed157afd35f6dabe856
parent cad94f96
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -95,6 +95,10 @@ bool ResourcePathShortener::Consume(IAaptContext* context, ResourceTable* table)
    android::StringPiece res_subdir, actual_filename, extension;
    util::ExtractResFilePathParts(*file_ref->path, &res_subdir, &actual_filename, &extension);

    // Android detects ColorStateLists via pathname, skip res/color/*
    if (res_subdir == android::StringPiece("res/color/"))
      continue;

    std::string shortened_filename = ShortenFileName(*file_ref->path, num_chars);
    int collision_count = 0;
    std::string shortened_path = GetShortenedPath(shortened_filename, extension, collision_count);
+46 −0
Original line number Diff line number Diff line
@@ -24,6 +24,11 @@ using ::testing::Not;
using ::testing::NotNull;
using ::testing::Eq;

android::StringPiece GetExtension(android::StringPiece path) {
  auto iter = std::find(path.begin(), path.end(), '.');
  return android::StringPiece(iter, path.end() - iter);
}

namespace aapt {

TEST(ResourcePathShortenerTest, FileRefPathsChangedInResourceTable) {
@@ -64,4 +69,45 @@ TEST(ResourcePathShortenerTest, FileRefPathsChangedInResourceTable) {
  EXPECT_THAT(path_map.find("res/should/still/be/the/same.png"), Eq(path_map.end()));
}

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

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

  std::map<std::string, std::string> path_map;
  ASSERT_TRUE(ResourcePathShortener(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()));
}

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

  std::string original_xml_path = "res/drawable/xmlfile.xml";
  std::string original_png_path = "res/drawable/pngfile.png";

  std::unique_ptr<ResourceTable> table =
      test::ResourceTableBuilder()
          .AddFileReference("android:color/xmlfile", original_xml_path)
          .AddFileReference("android:color/pngfile", original_png_path)
          .Build();

  std::map<std::string, std::string> path_map;
  ASSERT_TRUE(ResourcePathShortener(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())));
  ASSERT_THAT(path_map.find("res/drawable/pngfile.png"), Not(Eq(path_map.end())));

  auto shortend_xml_path = path_map[original_xml_path];
  auto shortend_png_path = path_map[original_png_path];

  EXPECT_THAT(GetExtension(path_map[original_xml_path]), Eq(android::StringPiece(".xml")));
  EXPECT_THAT(GetExtension(path_map[original_png_path]), Eq(android::StringPiece(".png")));
}

}   // namespace aapt