Loading libs/androidfw/tests/AssetManager2_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,38 @@ TEST_F(AssetManager2Test, ResolveReferenceToBag) { EXPECT_EQ(basic::R::array::integerArray1, last_ref); } TEST_F(AssetManager2Test, ResolveDeepIdReference) { AssetManager2 assetmanager; assetmanager.SetApkAssets({basic_assets_.get()}); // Set up the resource ids const uint32_t high_ref = assetmanager .GetResourceId("@id/high_ref", "values", "com.android.basic"); ASSERT_NE(high_ref, 0u); const uint32_t middle_ref = assetmanager .GetResourceId("@id/middle_ref", "values", "com.android.basic"); ASSERT_NE(middle_ref, 0u); const uint32_t low_ref = assetmanager .GetResourceId("@id/low_ref", "values", "com.android.basic"); ASSERT_NE(low_ref, 0u); // Retrieve the most shallow resource Res_value value; ResTable_config config; uint32_t flags; ApkAssetsCookie cookie = assetmanager.GetResource(high_ref, false /*may_be_bag*/, 0 /*density_override*/, &value, &config, &flags); ASSERT_NE(kInvalidCookie, cookie); EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType); EXPECT_EQ(middle_ref, value.data); // Check that resolving the reference resolves to the deepest id uint32_t last_ref = high_ref; assetmanager.ResolveReference(cookie, &value, &config, &flags, &last_ref); EXPECT_EQ(last_ref, low_ref); } TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) { AssetManager2 assetmanager; assetmanager.SetApkAssets({basic_assets_.get()}); Loading libs/androidfw/tests/data/basic/basic.apk +188 B (5.32 KiB) File changed.No diff preview for this file type. View original file View changed file libs/androidfw/tests/data/basic/res/values/values.xml +4 −0 Original line number Diff line number Diff line Loading @@ -78,4 +78,8 @@ <item type="string" name="test2" /> <item type="array" name="integerArray1" /> </overlayable> <item name="high_ref" type="id">@id/middle_ref</item> <item name="middle_ref" type="id">@id/low_ref</item> <item name="low_ref" type="id"/> </resources> tools/aapt2/ResourceParser.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -586,7 +586,29 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, out_resource->name.type = ResourceType::kId; out_resource->name.entry = maybe_name.value().to_string(); // Ids either represent a unique resource id or reference another resource id auto item = ParseItem(parser, out_resource, resource_format); if (!item) { return false; } String* empty = ValueCast<String>(out_resource->value.get()); if (empty && *empty->value == "") { // If no inner element exists, represent a unique identifier out_resource->value = util::make_unique<Id>(); } else { // If an inner element exists, the inner element must be a reference to // another resource id Reference* ref = ValueCast<Reference>(out_resource->value.get()); if (!ref || ref->name.value().type != ResourceType::kId) { diag_->Error(DiagMessage(out_resource->source) << "<" << parser->element_name() << "> inner element must either be a resource reference or empty"); return false; } } return true; } Loading tools/aapt2/ResourceParser_test.cpp +28 −0 Original line number Diff line number Diff line Loading @@ -933,4 +933,32 @@ TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { EXPECT_FALSE(TestParse(input)); } TEST_F(ResourceParserTest, ParseIdItem) { std::string input = R"( <item name="foo" type="id">@id/bar</item> <item name="bar" type="id"/> <item name="baz" type="id"></item>)"; ASSERT_TRUE(TestParse(input)); ASSERT_THAT(test::GetValue<Reference>(&table_, "id/foo"), NotNull()); ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar"), NotNull()); ASSERT_THAT(test::GetValue<Id>(&table_, "id/baz"), NotNull()); // Reject attribute references input = R"(<item name="foo2" type="id">?attr/bar"</item>)"; ASSERT_FALSE(TestParse(input)); // Reject non-references input = R"(<item name="foo3" type="id">0x7f010001</item>)"; ASSERT_FALSE(TestParse(input)); input = R"(<item name="foo4" type="id">@drawable/my_image</item>)"; ASSERT_FALSE(TestParse(input)); input = R"(<item name="foo5" type="id"><string name="biz"></string></item>)"; ASSERT_FALSE(TestParse(input)); // Ids that reference other resource ids cannot be public input = R"(<public name="foo6" type="id">@id/bar6</item>)"; ASSERT_FALSE(TestParse(input)); } } // namespace aapt Loading
libs/androidfw/tests/AssetManager2_test.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -386,6 +386,38 @@ TEST_F(AssetManager2Test, ResolveReferenceToBag) { EXPECT_EQ(basic::R::array::integerArray1, last_ref); } TEST_F(AssetManager2Test, ResolveDeepIdReference) { AssetManager2 assetmanager; assetmanager.SetApkAssets({basic_assets_.get()}); // Set up the resource ids const uint32_t high_ref = assetmanager .GetResourceId("@id/high_ref", "values", "com.android.basic"); ASSERT_NE(high_ref, 0u); const uint32_t middle_ref = assetmanager .GetResourceId("@id/middle_ref", "values", "com.android.basic"); ASSERT_NE(middle_ref, 0u); const uint32_t low_ref = assetmanager .GetResourceId("@id/low_ref", "values", "com.android.basic"); ASSERT_NE(low_ref, 0u); // Retrieve the most shallow resource Res_value value; ResTable_config config; uint32_t flags; ApkAssetsCookie cookie = assetmanager.GetResource(high_ref, false /*may_be_bag*/, 0 /*density_override*/, &value, &config, &flags); ASSERT_NE(kInvalidCookie, cookie); EXPECT_EQ(Res_value::TYPE_REFERENCE, value.dataType); EXPECT_EQ(middle_ref, value.data); // Check that resolving the reference resolves to the deepest id uint32_t last_ref = high_ref; assetmanager.ResolveReference(cookie, &value, &config, &flags, &last_ref); EXPECT_EQ(last_ref, low_ref); } TEST_F(AssetManager2Test, KeepLastReferenceIdUnmodifiedIfNoReferenceIsResolved) { AssetManager2 assetmanager; assetmanager.SetApkAssets({basic_assets_.get()}); Loading
libs/androidfw/tests/data/basic/basic.apk +188 B (5.32 KiB) File changed.No diff preview for this file type. View original file View changed file
libs/androidfw/tests/data/basic/res/values/values.xml +4 −0 Original line number Diff line number Diff line Loading @@ -78,4 +78,8 @@ <item type="string" name="test2" /> <item type="array" name="integerArray1" /> </overlayable> <item name="high_ref" type="id">@id/middle_ref</item> <item name="middle_ref" type="id">@id/low_ref</item> <item name="low_ref" type="id"/> </resources>
tools/aapt2/ResourceParser.cpp +23 −1 Original line number Diff line number Diff line Loading @@ -586,7 +586,29 @@ bool ResourceParser::ParseResource(xml::XmlPullParser* parser, out_resource->name.type = ResourceType::kId; out_resource->name.entry = maybe_name.value().to_string(); // Ids either represent a unique resource id or reference another resource id auto item = ParseItem(parser, out_resource, resource_format); if (!item) { return false; } String* empty = ValueCast<String>(out_resource->value.get()); if (empty && *empty->value == "") { // If no inner element exists, represent a unique identifier out_resource->value = util::make_unique<Id>(); } else { // If an inner element exists, the inner element must be a reference to // another resource id Reference* ref = ValueCast<Reference>(out_resource->value.get()); if (!ref || ref->name.value().type != ResourceType::kId) { diag_->Error(DiagMessage(out_resource->source) << "<" << parser->element_name() << "> inner element must either be a resource reference or empty"); return false; } } return true; } Loading
tools/aapt2/ResourceParser_test.cpp +28 −0 Original line number Diff line number Diff line Loading @@ -933,4 +933,32 @@ TEST_F(ResourceParserTest, DuplicateOverlayableIsError) { EXPECT_FALSE(TestParse(input)); } TEST_F(ResourceParserTest, ParseIdItem) { std::string input = R"( <item name="foo" type="id">@id/bar</item> <item name="bar" type="id"/> <item name="baz" type="id"></item>)"; ASSERT_TRUE(TestParse(input)); ASSERT_THAT(test::GetValue<Reference>(&table_, "id/foo"), NotNull()); ASSERT_THAT(test::GetValue<Id>(&table_, "id/bar"), NotNull()); ASSERT_THAT(test::GetValue<Id>(&table_, "id/baz"), NotNull()); // Reject attribute references input = R"(<item name="foo2" type="id">?attr/bar"</item>)"; ASSERT_FALSE(TestParse(input)); // Reject non-references input = R"(<item name="foo3" type="id">0x7f010001</item>)"; ASSERT_FALSE(TestParse(input)); input = R"(<item name="foo4" type="id">@drawable/my_image</item>)"; ASSERT_FALSE(TestParse(input)); input = R"(<item name="foo5" type="id"><string name="biz"></string></item>)"; ASSERT_FALSE(TestParse(input)); // Ids that reference other resource ids cannot be public input = R"(<public name="foo6" type="id">@id/bar6</item>)"; ASSERT_FALSE(TestParse(input)); } } // namespace aapt