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
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user