Retain parsed attribute type
If the value of an attribute enum is defined as a hexadecimal integer,
flatten uses of the attribute as with the
android::Res_value::TYPE_INT_HEX type.
This change adds a "type" field to pb::Attribute::Symbol, which if left
unset, will have a default value of android::Res_value::TYPE_INT_DEC
when deserialized by aapt2.
Bug: 124474141
Test: aapt2_tests and manual compilation of files and inspection using
`aapt2 dump chunks`
Change-Id: Ibf12394284fdbe3a8047f7ecf4fe68517dfc3abb
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index 859fe80..c557656 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -1387,7 +1387,7 @@
return Attribute::Symbol{
Reference(ResourceNameRef({}, ResourceType::kId, maybe_name.value())),
- val.data};
+ val.data, val.dataType};
}
bool ResourceParser::ParseStyleItem(xml::XmlPullParser* parser, Style* style) {
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 464225f..4237469 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -401,7 +401,7 @@
std::string input = R"(
<attr name="foo">
<enum name="bar" value="0"/>
- <enum name="bat" value="1"/>
+ <enum name="bat" value="0x1"/>
<enum name="baz" value="2"/>
</attr>)";
ASSERT_TRUE(TestParse(input));
@@ -414,14 +414,17 @@
ASSERT_TRUE(enum_attr->symbols[0].symbol.name);
EXPECT_THAT(enum_attr->symbols[0].symbol.name.value().entry, Eq("bar"));
EXPECT_THAT(enum_attr->symbols[0].value, Eq(0u));
+ EXPECT_THAT(enum_attr->symbols[0].type, Eq(Res_value::TYPE_INT_DEC));
ASSERT_TRUE(enum_attr->symbols[1].symbol.name);
EXPECT_THAT(enum_attr->symbols[1].symbol.name.value().entry, Eq("bat"));
EXPECT_THAT(enum_attr->symbols[1].value, Eq(1u));
+ EXPECT_THAT(enum_attr->symbols[1].type, Eq(Res_value::TYPE_INT_HEX));
ASSERT_TRUE(enum_attr->symbols[2].symbol.name);
EXPECT_THAT(enum_attr->symbols[2].symbol.name.value().entry, Eq("baz"));
EXPECT_THAT(enum_attr->symbols[2].value, Eq(2u));
+ EXPECT_THAT(enum_attr->symbols[2].type, Eq(Res_value::TYPE_INT_DEC));
}
TEST_F(ResourceParserTest, ParseFlagAttr) {
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index e0040e4..bd2ab53 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -378,7 +378,7 @@
const ResourceName& enum_symbol_resource_name = symbol.symbol.name.value();
if (trimmed_str == enum_symbol_resource_name.entry) {
android::Res_value value = {};
- value.dataType = android::Res_value::TYPE_INT_DEC;
+ value.dataType = symbol.type;
value.data = symbol.value;
return util::make_unique<BinaryPrimitive>(value);
}
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index 168ad61..fe0883b 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -292,6 +292,7 @@
struct Symbol {
Reference symbol;
uint32_t value;
+ uint8_t type;
friend std::ostream& operator<<(std::ostream& out, const Symbol& symbol);
};
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index b2fc084..65f4652 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -388,6 +388,9 @@
// The value of the enum/flag.
uint32 value = 4;
+
+ // The data type of the enum/flag as defined in android::Res_value.
+ uint32 type = 5;
}
// Bitmask of formats allowed for an attribute.
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index fd8e36e..fcd6aaa 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -614,6 +614,7 @@
if (attr->type_mask & (ResTable_map::TYPE_ENUM | ResTable_map::TYPE_FLAGS)) {
Attribute::Symbol symbol;
symbol.value = util::DeviceToHost32(map_entry.value.data);
+ symbol.type = map_entry.value.dataType;
symbol.symbol = Reference(util::DeviceToHost32(map_entry.name.ident));
attr->symbols.push_back(std::move(symbol));
}
diff --git a/tools/aapt2/format/binary/TableFlattener.cpp b/tools/aapt2/format/binary/TableFlattener.cpp
index f2e72da..b932117 100644
--- a/tools/aapt2/format/binary/TableFlattener.cpp
+++ b/tools/aapt2/format/binary/TableFlattener.cpp
@@ -107,7 +107,7 @@
}
for (Attribute::Symbol& s : attr->symbols) {
- BinaryPrimitive val(Res_value::TYPE_INT_DEC, s.value);
+ BinaryPrimitive val(s.type, s.value);
FlattenEntry(&s.symbol, &val);
}
}
diff --git a/tools/aapt2/format/proto/ProtoDeserialize.cpp b/tools/aapt2/format/proto/ProtoDeserialize.cpp
index bb21c1c..efbf636 100644
--- a/tools/aapt2/format/proto/ProtoDeserialize.cpp
+++ b/tools/aapt2/format/proto/ProtoDeserialize.cpp
@@ -708,6 +708,8 @@
return {};
}
symbol.value = pb_symbol.value();
+ symbol.type = pb_symbol.type() != 0U ? pb_symbol.type()
+ : android::Res_value::TYPE_INT_DEC;
attr->symbols.push_back(std::move(symbol));
}
value = std::move(attr);
diff --git a/tools/aapt2/format/proto/ProtoSerialize.cpp b/tools/aapt2/format/proto/ProtoSerialize.cpp
index a54822b..aa6547e 100644
--- a/tools/aapt2/format/proto/ProtoSerialize.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize.cpp
@@ -552,6 +552,7 @@
SerializeItemMetaDataToPb(symbol.symbol, pb_symbol, src_pool_);
SerializeReferenceToPb(symbol.symbol, pb_symbol->mutable_name());
pb_symbol->set_value(symbol.value);
+ pb_symbol->set_type(symbol.type);
}
}
diff --git a/tools/aapt2/format/proto/ProtoSerialize_test.cpp b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
index f252f33..e7f2330 100644
--- a/tools/aapt2/format/proto/ProtoSerialize_test.cpp
+++ b/tools/aapt2/format/proto/ProtoSerialize_test.cpp
@@ -80,7 +80,7 @@
test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 123u), context->GetDiagnostics()));
ASSERT_TRUE(table->AddResource(
test::ParseNameOrDie("com.app.a:integer/one"), test::ParseConfigOrDie("land"), "tablet",
- test::BuildPrimitive(android::Res_value::TYPE_INT_DEC, 321u), context->GetDiagnostics()));
+ test::BuildPrimitive(android::Res_value::TYPE_INT_HEX, 321u), context->GetDiagnostics()));
// Make a reference with both resource name and resource ID.
// The reference should point to a resource outside of this table to test that both name and id
@@ -133,11 +133,13 @@
&new_table, "com.app.a:integer/one", test::ParseConfigOrDie("land"), "");
ASSERT_THAT(prim, NotNull());
EXPECT_THAT(prim->value.data, Eq(123u));
+ EXPECT_THAT(prim->value.dataType, Eq(0x10));
prim = test::GetValueForConfigAndProduct<BinaryPrimitive>(
&new_table, "com.app.a:integer/one", test::ParseConfigOrDie("land"), "tablet");
ASSERT_THAT(prim, NotNull());
EXPECT_THAT(prim->value.data, Eq(321u));
+ EXPECT_THAT(prim->value.dataType, Eq(0x11));
Reference* actual_ref = test::GetValue<Reference>(&new_table, "com.app.a:layout/abc");
ASSERT_THAT(actual_ref, NotNull());
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index 61a8fbb..bc09f19 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -313,6 +313,7 @@
symbol.symbol.name = parsed_name.value();
symbol.symbol.id = ResourceId(map_entry.key);
symbol.value = map_entry.value.data;
+ symbol.type = map_entry.value.dataType;
s->attribute->symbols.push_back(std::move(symbol));
}
}