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

Commit 18b15bb3 authored by Clark DuVall's avatar Clark DuVall
Browse files

Reorder style items in shared libraries

AssetManager2.cpp expects style attribute IDs to be in sorted order when
applying a style (see AssetManager2::GetBag). Shared libraries have a
package ID of 0x00, which will mean any attribute defined in a shared
library will be put before all other attributes. Once the attribute ID
is looked up in the dynamic ref table, the package ID is no longer 0x00,
which means this ID is no longer in sorted order. This messes up the
logic in AssetManager2::GetBag, and results in some style attributes
getting dropped from shared libraries.

This change modifies how aapt2 sorts the style entries, sorting entries
with dynamic IDs after entries with the android framework ID. This means
the entries will still be in sorted order when the IDs are looked up.

Bug: 147674078
Test: TableFlattenerTest.FlattenSharedLibraryWithStyle
Change-Id: Ic4f4004b6d9cecde9325dcdb37f71138857f8236
parent 2bb9f65c
Loading
Loading
Loading
Loading
+13 −1
Original line number Diff line number Diff line
@@ -59,10 +59,22 @@ static void strcpy16_htod(uint16_t* dst, size_t len, const StringPiece16& src) {
  dst[i] = 0;
}

static bool cmp_style_ids(ResourceId a, ResourceId b) {
  // If one of a and b is from the framework package (package ID 0x01), and the
  // other is a dynamic ID (package ID 0x00), then put the dynamic ID after the
  // framework ID. This ensures that when AssetManager resolves the dynamic IDs,
  // they will be in sorted order as expected by AssetManager.
  if ((a.package_id() == kFrameworkPackageId && b.package_id() == 0x00) ||
      (a.package_id() == 0x00 && b.package_id() == kFrameworkPackageId)) {
    return b < a;
  }
  return a < b;
}

static bool cmp_style_entries(const Style::Entry& a, const Style::Entry& b) {
  if (a.key.id) {
    if (b.key.id) {
      return a.key.id.value() < b.key.id.value();
      return cmp_style_ids(a.key.id.value(), b.key.id.value());
    }
    return true;
  } else if (!b.key.id) {
+41 −0
Original line number Diff line number Diff line
@@ -431,6 +431,47 @@ TEST_F(TableFlattenerTest, FlattenSharedLibrary) {
  EXPECT_EQ("lib", iter->second);
}

TEST_F(TableFlattenerTest, FlattenSharedLibraryWithStyle) {
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build();
  std::unique_ptr<ResourceTable> table =
      test::ResourceTableBuilder()
          .SetPackageId("lib", 0x00)
          .AddValue("lib:style/Theme",
                    ResourceId(0x00030001),
                    test::StyleBuilder()
                    .AddItem("lib:attr/bar", ResourceId(0x00010002),
                             ResourceUtils::TryParseInt("2"))
                    .AddItem("lib:attr/foo", ResourceId(0x00010001),
                             ResourceUtils::TryParseInt("1"))
                    .AddItem("android:attr/bar", ResourceId(0x01010002),
                             ResourceUtils::TryParseInt("4"))
                    .AddItem("android:attr/foo", ResourceId(0x01010001),
                             ResourceUtils::TryParseInt("3"))
                    .Build())
          .Build();
  ResourceTable result;
  ASSERT_TRUE(Flatten(context.get(), {}, table.get(), &result));

  Maybe<ResourceTable::SearchResult> search_result =
      result.FindResource(test::ParseNameOrDie("lib:style/Theme"));
  ASSERT_TRUE(search_result);
  EXPECT_EQ(0x00u, search_result.value().package->id.value());
  EXPECT_EQ(0x03u, search_result.value().type->id.value());
  EXPECT_EQ(0x01u, search_result.value().entry->id.value());
  ASSERT_EQ(1u, search_result.value().entry->values.size());
  Value* value = search_result.value().entry->values[0]->value.get();
  Style* style = ValueCast<Style>(value);
  ASSERT_TRUE(style);
  ASSERT_EQ(4u, style->entries.size());
  // Ensure the attributes from the shared library come after the items from
  // android.
  EXPECT_EQ(0x01010001, style->entries[0].key.id.value());
  EXPECT_EQ(0x01010002, style->entries[1].key.id.value());
  EXPECT_EQ(0x00010001, style->entries[2].key.id.value());
  EXPECT_EQ(0x00010002, style->entries[3].key.id.value());
}

TEST_F(TableFlattenerTest, FlattenTableReferencingSharedLibraries) {
  std::unique_ptr<IAaptContext> context =
      test::ContextBuilder().SetCompilationPackage("app").SetPackageId(0x7f).Build();