Merge "AAPT2: Support id reference chaining from AAPT" into pi-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
247ecfa498
@@ -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()});
|
||||
|
||||
Binary file not shown.
@@ -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>
|
||||
|
||||
@@ -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();
|
||||
out_resource->value = util::make_unique<Id>();
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user