Escape single quotes in aapt2

Using #normalizeForOutput to normalize a string for output in order
to escape some special char.

Fix: 140373430
Test: atest libaapt_tests aapt2_tests
Change-Id: Ic49dbaaccd8e4b1c51a87de9f0e2e5f4a8da7d3d
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 8b7eadf9..dd60f17 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -349,7 +349,8 @@
         size_t len;
         const char16_t* str16 = tree.getText(&len);
         if (str16) {
-          text->text = util::Utf16ToUtf8(StringPiece16(str16, len));
+          text->text =
+              ResTable::normalizeForOutput(util::Utf16ToUtf8(StringPiece16(str16, len)).c_str());
         }
         CHECK(!node_stack.empty());
         node_stack.top()->AppendChild(std::move(text));
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index 6c717dc..3a2d656 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -139,6 +139,19 @@
   EXPECT_THAT(attr->value, Eq("\""));
 }
 
+TEST(XmlDomTest, XmlEscapeSingleQuotes) {
+  std::unique_ptr<XmlResource> doc = test::BuildXmlDom(R"(
+    <foo><![CDATA[oh no' (line=1001)
+E: this-is-not-an-element (line=88)
+    T: 'blah]]></foo>)");
+
+  Element* el = doc->root.get();
+  Text* text = xml::NodeCast<xml::Text>(el->children[0].get());
+  ASSERT_THAT(text, NotNull());
+  EXPECT_THAT(text->text,
+              Eq("oh no' (line=1001)\nE: this-is-not-an-element (line=88)\n    T: 'blah"));
+}
+
 class TestVisitor : public PackageAwareVisitor {
  public:
   using PackageAwareVisitor::Visit;