AAPT2: Add Inline Complex XML support

See: https://developer.android.com/guide/topics/resources/complex-xml-resources.html

Change-Id: I8274c85e25cabf90423141c228697e873167d136
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 39bd5bf..28de78a 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -322,6 +322,21 @@
     return util::make_unique<XmlResource>(ResourceFile{}, std::move(root));
 }
 
+std::unique_ptr<Node> Namespace::clone() {
+    auto ns = util::make_unique<Namespace>();
+    ns->comment = comment;
+    ns->lineNumber = lineNumber;
+    ns->columnNumber = columnNumber;
+    ns->namespacePrefix = namespacePrefix;
+    ns->namespaceUri = namespaceUri;
+
+    ns->children.reserve(children.size());
+    for (const std::unique_ptr<xml::Node>& child : children) {
+        ns->addChild(child->clone());
+    }
+    return std::move(ns);
+}
+
 Element* findRootElement(XmlResource* doc) {
     return findRootElement(doc->root.get());
 }
@@ -406,6 +421,36 @@
     return elements;
 }
 
+std::unique_ptr<Node> Element::clone() {
+    auto el = util::make_unique<Element>();
+    el->comment = comment;
+    el->lineNumber = lineNumber;
+    el->columnNumber = columnNumber;
+    el->name = name;
+    el->namespaceUri = namespaceUri;
+
+    el->attributes.reserve(attributes.size());
+    for (xml::Attribute& attr : attributes) {
+        // Don't copy compiled values or attributes.
+        el->attributes.push_back(xml::Attribute{ attr.namespaceUri, attr.name, attr.value });
+    }
+
+    el->children.reserve(children.size());
+    for (const std::unique_ptr<xml::Node>& child : children) {
+        el->addChild(child->clone());
+    }
+    return std::move(el);
+}
+
+std::unique_ptr<Node> Text::clone() {
+    auto t = util::make_unique<Text>();
+    t->comment = comment;
+    t->lineNumber = lineNumber;
+    t->columnNumber = columnNumber;
+    t->text = text;
+    return std::move(t);
+}
+
 void PackageAwareVisitor::visit(Namespace* ns) {
    bool added = false;
    if (Maybe<ExtractedPackage> maybePackage = extractPackageFromNamespace(ns->namespaceUri)) {
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index d083d82..e4f41b0 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -32,12 +32,13 @@
 namespace aapt {
 namespace xml {
 
-struct RawVisitor;
+class RawVisitor;
 
 /**
  * Base class for all XML nodes.
  */
-struct Node {
+class Node {
+public:
     Node* parent = nullptr;
     size_t lineNumber = 0;
     size_t columnNumber = 0;
@@ -48,6 +49,7 @@
 
     void addChild(std::unique_ptr<Node> child);
     virtual void accept(RawVisitor* visitor) = 0;
+    virtual std::unique_ptr<Node> clone() = 0;
 };
 
 /**
@@ -55,16 +57,20 @@
  * subclass of Node.
  */
 template <typename Derived>
-struct BaseNode : public Node {
+class BaseNode : public Node {
+public:
     virtual void accept(RawVisitor* visitor) override;
 };
 
 /**
  * A Namespace XML node. Can only have one child.
  */
-struct Namespace : public BaseNode<Namespace> {
+class Namespace : public BaseNode<Namespace> {
+public:
     std::string namespacePrefix;
     std::string namespaceUri;
+
+    std::unique_ptr<Node> clone() override;
 };
 
 struct AaptAttribute {
@@ -87,7 +93,8 @@
 /**
  * An Element XML node.
  */
-struct Element : public BaseNode<Element> {
+class Element : public BaseNode<Element> {
+public:
     std::string namespaceUri;
     std::string name;
     std::vector<Attribute> attributes;
@@ -99,19 +106,24 @@
                                          const StringPiece& attrName,
                                          const StringPiece& attrValue);
     std::vector<xml::Element*> getChildElements();
+    std::unique_ptr<Node> clone() override;
 };
 
 /**
  * A Text (CDATA) XML node. Can not have any children.
  */
-struct Text : public BaseNode<Text> {
+class Text : public BaseNode<Text> {
+public:
     std::string text;
+
+    std::unique_ptr<Node> clone() override;
 };
 
 /**
  * An XML resource with a source, name, and XML tree.
  */
-struct XmlResource {
+class XmlResource {
+public:
     ResourceFile file;
     std::unique_ptr<xml::Node> root;
 };
@@ -136,7 +148,8 @@
  * A visitor interface for the different XML Node subtypes. This will not traverse into
  * children. Use Visitor for that.
  */
-struct RawVisitor {
+class RawVisitor {
+public:
     virtual ~RawVisitor() = default;
 
     virtual void visit(Namespace* node) {}
@@ -147,7 +160,8 @@
 /**
  * Visitor whose default implementation visits the children nodes of any node.
  */
-struct Visitor : public RawVisitor {
+class Visitor : public RawVisitor {
+public:
     using RawVisitor::visit;
 
     void visit(Namespace* node) override {
@@ -173,6 +187,13 @@
  * An XML DOM visitor that will record the package name for a namespace prefix.
  */
 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
+public:
+    using Visitor::visit;
+
+    void visit(Namespace* ns) override;
+    Maybe<ExtractedPackage> transformPackageAlias(
+            const StringPiece& alias, const StringPiece& localPackage) const override;
+
 private:
     struct PackageDecl {
         std::string prefix;
@@ -180,13 +201,6 @@
     };
 
     std::vector<PackageDecl> mPackageDecls;
-
-public:
-    using Visitor::visit;
-
-    void visit(Namespace* ns) override;
-    Maybe<ExtractedPackage> transformPackageAlias(
-            const StringPiece& alias, const StringPiece& localPackage) const override;
 };
 
 // Implementations
@@ -197,7 +211,8 @@
 }
 
 template <typename T>
-struct NodeCastImpl : public RawVisitor {
+class NodeCastImpl : public RawVisitor {
+public:
     using RawVisitor::visit;
 
     T* value = nullptr;
diff --git a/tools/aapt2/xml/XmlUtil.cpp b/tools/aapt2/xml/XmlUtil.cpp
index 0e9d005..b570fd7 100644
--- a/tools/aapt2/xml/XmlUtil.cpp
+++ b/tools/aapt2/xml/XmlUtil.cpp
@@ -23,8 +23,8 @@
 namespace aapt {
 namespace xml {
 
-std::string buildPackageNamespace(const StringPiece& package) {
-    std::string result = kSchemaPublicPrefix;
+std::string buildPackageNamespace(const StringPiece& package, bool privateReference) {
+    std::string result = privateReference ? kSchemaPrivatePrefix : kSchemaPublicPrefix;
     result.append(package.data(), package.size());
     return result;
 }
diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h
index b75d8ac..a6ad79d 100644
--- a/tools/aapt2/xml/XmlUtil.h
+++ b/tools/aapt2/xml/XmlUtil.h
@@ -30,6 +30,7 @@
 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";
+constexpr const char* kSchemaAapt = "http://schemas.android.com/aapt";
 
 /**
  * Result of extracting a package name from a namespace URI declaration.
@@ -62,8 +63,12 @@
  * Returns an XML Android namespace for the given package of the form:
  *
  * http://schemas.android.com/apk/res/<package>
+ *
+ * If privateReference == true, the package will be of the form:
+ *
+ * http://schemas.android.com/apk/prv/res/<package>
  */
-std::string buildPackageNamespace(const StringPiece& package);
+std::string buildPackageNamespace(const StringPiece& package, bool privateReference=false);
 
 /**
  * Interface representing a stack of XML namespace declarations. When looking up the package