summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--tools/aapt2/StringPool_test.cpp10
-rw-r--r--tools/aapt2/flatten/XmlFlattener.cpp30
-rw-r--r--tools/aapt2/flatten/XmlFlattener_test.cpp19
3 files changed, 46 insertions, 13 deletions
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 2b2d348fd17c..562d80ed8cdb 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -208,7 +208,8 @@ TEST(StringPoolTest, FlattenUtf8) {
StringPool::Ref ref1 = pool.makeRef(u"hello");
StringPool::Ref ref2 = pool.makeRef(u"goodbye");
StringPool::Ref ref3 = pool.makeRef(sLongString);
- StringPool::StyleRef ref4 = pool.makeRef(StyleString{
+ StringPool::Ref ref4 = pool.makeRef(u"");
+ StringPool::StyleRef ref5 = pool.makeRef(StyleString{
{ u"style" },
{ Span{ { u"b" }, 0, 1 }, Span{ { u"i" }, 2, 3 } }
});
@@ -217,6 +218,7 @@ TEST(StringPoolTest, FlattenUtf8) {
EXPECT_EQ(1u, ref2.getIndex());
EXPECT_EQ(2u, ref3.getIndex());
EXPECT_EQ(3u, ref4.getIndex());
+ EXPECT_EQ(4u, ref5.getIndex());
BigBuffer buffer(1024);
StringPool::flattenUtf8(&buffer, pool);
@@ -229,9 +231,11 @@ TEST(StringPoolTest, FlattenUtf8) {
EXPECT_EQ(util::getString(test, 0), u"hello");
EXPECT_EQ(util::getString(test, 1), u"goodbye");
EXPECT_EQ(util::getString(test, 2), sLongString);
- EXPECT_EQ(util::getString(test, 3), u"style");
+ size_t len;
+ EXPECT_NE(nullptr, test.stringAt(3, &len));
+ EXPECT_EQ(util::getString(test, 4), u"style");
- const ResStringPool_span* span = test.styleAt(3);
+ const ResStringPool_span* span = test.styleAt(4);
ASSERT_NE(nullptr, span);
EXPECT_EQ(util::getString(test, span->name.index), u"b");
EXPECT_EQ(0u, span->firstChar);
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index cc457890ff6f..2cf7ddaa2cc6 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -57,14 +57,15 @@ struct XmlFlattenerVisitor : public xml::Visitor {
mBuffer(buffer), mOptions(options) {
}
- void addString(const StringPiece16& str, uint32_t priority, android::ResStringPool_ref* dest) {
- if (!str.empty()) {
+ void addString(const StringPiece16& str, uint32_t priority, android::ResStringPool_ref* dest,
+ bool treatEmptyStringAsNull = false) {
+ if (str.empty() && treatEmptyStringAsNull) {
+ // Some parts of the runtime treat null differently than empty string.
+ dest->index = util::deviceToHost32(-1);
+ } else {
mStringRefs.push_back(StringFlattenDest{
mPool.makeRef(str, StringPool::Context{ priority }),
dest });
- } else {
- // The device doesn't think a string of size 0 is the same as null.
- dest->index = util::deviceToHost32(-1);
}
}
@@ -118,8 +119,14 @@ struct XmlFlattenerVisitor : public xml::Visitor {
flatNode->comment.index = util::hostToDevice32(-1);
ResXMLTree_attrExt* flatElem = startWriter.nextBlock<ResXMLTree_attrExt>();
- addString(node->namespaceUri, kLowPriority, &flatElem->ns);
- addString(node->name, kLowPriority, &flatElem->name);
+
+ // A missing namespace must be null, not an empty string. Otherwise the runtime
+ // complains.
+ addString(node->namespaceUri, kLowPriority, &flatElem->ns,
+ true /* treatEmptyStringAsNull */);
+ addString(node->name, kLowPriority, &flatElem->name,
+ true /* treatEmptyStringAsNull */);
+
flatElem->attributeStart = util::hostToDevice16(sizeof(*flatElem));
flatElem->attributeSize = util::hostToDevice16(sizeof(ResXMLTree_attribute));
@@ -138,7 +145,8 @@ struct XmlFlattenerVisitor : public xml::Visitor {
flatEndNode->comment.index = util::hostToDevice32(-1);
ResXMLTree_endElementExt* flatEndElem = endWriter.nextBlock<ResXMLTree_endElementExt>();
- addString(node->namespaceUri, kLowPriority, &flatEndElem->ns);
+ addString(node->namespaceUri, kLowPriority, &flatEndElem->ns,
+ true /* treatEmptyStringAsNull */);
addString(node->name, kLowPriority, &flatEndElem->name);
endWriter.finish();
@@ -205,8 +213,10 @@ struct XmlFlattenerVisitor : public xml::Visitor {
}
attributeIndex++;
- // Add the namespaceUri to the list of StringRefs to encode.
- addString(xmlAttr->namespaceUri, kLowPriority, &flatAttr->ns);
+ // Add the namespaceUri to the list of StringRefs to encode. Use null if the namespace
+ // is empty (doesn't exist).
+ addString(xmlAttr->namespaceUri, kLowPriority, &flatAttr->ns,
+ true /* treatEmptyStringAsNull */);
flatAttr->rawValue.index = util::hostToDevice32(-1);
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 4e6eb811e572..ef06528e236e 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -207,4 +207,23 @@ TEST_F(XmlFlattenerTest, NoNamespaceIsNotTheSameAsEmptyNamespace) {
EXPECT_GE(tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size()), 0);
}
+TEST_F(XmlFlattenerTest, EmptyStringValueInAttributeIsNotNull) {
+ std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom("<View package=\"\"/>");
+
+ android::ResXMLTree tree;
+ ASSERT_TRUE(flatten(doc.get(), &tree));
+
+ while (tree.next() != android::ResXMLTree::START_TAG) {
+ ASSERT_NE(tree.getEventType(), android::ResXMLTree::BAD_DOCUMENT);
+ ASSERT_NE(tree.getEventType(), android::ResXMLTree::END_DOCUMENT);
+ }
+
+ const StringPiece16 kPackage = u"package";
+ ssize_t idx = tree.indexOfAttribute(nullptr, 0, kPackage.data(), kPackage.size());
+ ASSERT_GE(idx, 0);
+
+ size_t len;
+ EXPECT_NE(nullptr, tree.getAttributeStringValue(idx, &len));
+}
+
} // namespace aapt