From 18b15bb3a6f97fdfc378472df0162a61361eaab9 Mon Sep 17 00:00:00 2001 From: Clark DuVall Date: Thu, 16 Jan 2020 11:28:13 -0800 Subject: [PATCH] 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 --- tools/aapt2/format/binary/TableFlattener.cpp | 14 ++++++- .../format/binary/TableFlattener_test.cpp | 41 +++++++++++++++++++ 2 files changed, 54 insertions(+), 1 deletion(-) diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp index 58e232c339854..cbce8a59bae39 100644 --- a/tools/aapt2/format/binary/TableFlattener.cpp +++ b/tools/aapt2/format/binary/TableFlattener.cpp @@ -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) { diff --git a/tools/aapt2/format/binary/TableFlattener_test.cpp b/tools/aapt2/format/binary/TableFlattener_test.cpp index 8fbdd7f270419..af2293f0f82b5 100644 --- a/tools/aapt2/format/binary/TableFlattener_test.cpp +++ b/tools/aapt2/format/binary/TableFlattener_test.cpp @@ -431,6 +431,47 @@ TEST_F(TableFlattenerTest, FlattenSharedLibrary) { EXPECT_EQ("lib", iter->second); } +TEST_F(TableFlattenerTest, FlattenSharedLibraryWithStyle) { + std::unique_ptr context = + test::ContextBuilder().SetCompilationPackage("lib").SetPackageId(0x00).Build(); + std::unique_ptr 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 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