AAPT2: Strip dedicated tools namespace from XML
Android has a dedicated XML namespace dedicated for tools that should not be
included in the final APK. AAPT strips this out, but the feature was missing
from AAPT2. See: http://tools.android.com/tech-docs/tools-attributes
Bug: 29115919
Change-Id: I8f4fc79e6c8592a313a691134e44d16fd91f36ed
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 3c1750c..ed5b60f 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -88,9 +88,14 @@
}
void visit(xml::Namespace* node) override {
- writeNamespace(node, android::RES_XML_START_NAMESPACE_TYPE);
- xml::Visitor::visit(node);
- writeNamespace(node, android::RES_XML_END_NAMESPACE_TYPE);
+ if (node->namespaceUri == xml::kSchemaTools) {
+ // Skip dedicated tools namespace.
+ xml::Visitor::visit(node);
+ } else {
+ writeNamespace(node, android::RES_XML_START_NAMESPACE_TYPE);
+ xml::Visitor::visit(node);
+ writeNamespace(node, android::RES_XML_END_NAMESPACE_TYPE);
+ }
}
void visit(xml::Text* node) override {
@@ -183,6 +188,9 @@
continue;
}
}
+ if (attr.namespaceUri == xml::kSchemaTools) {
+ continue;
+ }
mFilteredAttrs.push_back(&attr);
}
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index 8b3378f..d26f2e4 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -167,6 +167,33 @@
EXPECT_EQ(uint32_t(0x010103b3), tree.getAttributeNameResID(0));
}
+TEST_F(XmlFlattenerTest, FlattenCompiledXmlAndStripOnlyTools) {
+ std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(R"EOF(
+ <View xmlns:tools="http://schemas.android.com/tools"
+ xmlns:foo="http://schemas.android.com/foo"
+ foo:bar="Foo"
+ tools:ignore="MissingTranslation"/>)EOF");
+
+ android::ResXMLTree tree;
+ ASSERT_TRUE(flatten(doc.get(), &tree));
+
+ ASSERT_EQ(tree.next(), android::ResXMLTree::START_NAMESPACE);
+
+ size_t len;
+ const char16_t* namespacePrefix = tree.getNamespacePrefix(&len);
+ EXPECT_EQ(StringPiece16(namespacePrefix, len), u"foo");
+
+ const char16_t* namespaceUri = tree.getNamespaceUri(&len);
+ ASSERT_EQ(StringPiece16(namespaceUri, len), u"http://schemas.android.com/foo");
+
+ ASSERT_EQ(tree.next(), android::ResXMLTree::START_TAG);
+
+ EXPECT_EQ(
+ tree.indexOfAttribute("http://schemas.android.com/tools", "ignore"),
+ android::NAME_NOT_FOUND);
+ EXPECT_GE(tree.indexOfAttribute("http://schemas.android.com/foo", "bar"), 0);
+}
+
TEST_F(XmlFlattenerTest, AssignSpecialAttributeIndices) {
std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(R"EOF(
<View xmlns:android="http://schemas.android.com/apk/res/android"
diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h
index f0d59b7..b75d8ac 100644
--- a/tools/aapt2/xml/XmlUtil.h
+++ b/tools/aapt2/xml/XmlUtil.h
@@ -29,6 +29,7 @@
constexpr const char* kSchemaPublicPrefix = "http://schemas.android.com/apk/res/";
constexpr const char* kSchemaPrivatePrefix = "http://schemas.android.com/apk/prv/res/";
constexpr const char* kSchemaAndroid = "http://schemas.android.com/apk/res/android";
+constexpr const char* kSchemaTools = "http://schemas.android.com/tools";
/**
* Result of extracting a package name from a namespace URI declaration.