AAPT2: Remove usage of u16string

For legacy reasons, we kept around the use of UTF-16 internally
in AAPT2. We don't need this and this CL removes all instances of
std::u16string and StringPiece16. The only places still needed
are when interacting with the ResTable APIs that only operate in
UTF16.

Change-Id: I492475b84bb9014fa13bf992cff447ee7a5fe588
diff --git a/tools/aapt2/Android.mk b/tools/aapt2/Android.mk
index f2c13ba..bbb9a51 100644
--- a/tools/aapt2/Android.mk
+++ b/tools/aapt2/Android.mk
@@ -103,6 +103,7 @@
 	java/JavaClassGenerator_test.cpp \
 	java/ManifestClassGenerator_test.cpp \
 	Locale_test.cpp \
+	NameMangler_test.cpp \
 	Resource_test.cpp \
 	ResourceParser_test.cpp \
 	ResourceTable_test.cpp \
diff --git a/tools/aapt2/AppInfo.h b/tools/aapt2/AppInfo.h
index 51d8ca6..1d39b72 100644
--- a/tools/aapt2/AppInfo.h
+++ b/tools/aapt2/AppInfo.h
@@ -31,12 +31,12 @@
     /**
      * App's package name.
      */
-    std::u16string package;
+    std::string package;
 
     /**
      * The App's minimum SDK version.
      */
-    Maybe<std::u16string> minSdkVersion;
+    Maybe<std::string> minSdkVersion;
 };
 
 } // namespace aapt
diff --git a/tools/aapt2/ConfigDescription_test.cpp b/tools/aapt2/ConfigDescription_test.cpp
index e68d6be..455a57f 100644
--- a/tools/aapt2/ConfigDescription_test.cpp
+++ b/tools/aapt2/ConfigDescription_test.cpp
@@ -16,10 +16,9 @@
 
 #include "ConfigDescription.h"
 #include "SdkConstants.h"
-
+#include "test/Test.h"
 #include "util/StringPiece.h"
 
-#include <gtest/gtest.h>
 #include <string>
 
 namespace aapt {
diff --git a/tools/aapt2/Flags.cpp b/tools/aapt2/Flags.cpp
index 666e8a8e..2033a4c 100644
--- a/tools/aapt2/Flags.cpp
+++ b/tools/aapt2/Flags.cpp
@@ -101,7 +101,7 @@
         // Split the description by newlines and write out the argument (which is empty after
         // the first line) followed by the description line. This will make sure that multiline
         // descriptions are still right justified and aligned.
-        for (StringPiece line : util::tokenize<char>(flag.description, '\n')) {
+        for (StringPiece line : util::tokenize(flag.description, '\n')) {
             *out << " " << std::setw(kWidth) << std::left << argLine << line << "\n";
             argLine = " ";
         }
diff --git a/tools/aapt2/Locale_test.cpp b/tools/aapt2/Locale_test.cpp
index 758e1e3..e4b8ce7 100644
--- a/tools/aapt2/Locale_test.cpp
+++ b/tools/aapt2/Locale_test.cpp
@@ -23,7 +23,7 @@
 namespace aapt {
 
 static ::testing::AssertionResult TestLanguage(const char* input, const char* lang) {
-    std::vector<std::string> parts = util::splitAndLowercase(std::string(input), '-');
+    std::vector<std::string> parts = util::splitAndLowercase(input, '-');
     LocaleValue lv;
     ssize_t count = lv.initFromParts(std::begin(parts), std::end(parts));
     if (count < 0) {
@@ -45,7 +45,7 @@
 
 static ::testing::AssertionResult TestLanguageRegion(const char* input, const char* lang,
                                                      const char* region) {
-    std::vector<std::string> parts = util::splitAndLowercase(std::string(input), '-');
+    std::vector<std::string> parts = util::splitAndLowercase(input, '-');
     LocaleValue lv;
     ssize_t count = lv.initFromParts(std::begin(parts), std::end(parts));
     if (count < 0) {
diff --git a/tools/aapt2/NameMangler.h b/tools/aapt2/NameMangler.h
index 054b9ee..505a982e 100644
--- a/tools/aapt2/NameMangler.h
+++ b/tools/aapt2/NameMangler.h
@@ -18,7 +18,6 @@
 #define AAPT_NAME_MANGLER_H
 
 #include "Resource.h"
-
 #include "util/Maybe.h"
 
 #include <set>
@@ -31,12 +30,12 @@
      * Represents the package we are trying to build. References pointing
      * to this package are not mangled, and mangled references inherit this package name.
      */
-    std::u16string targetPackageName;
+    std::string targetPackageName;
 
     /**
      * We must know which references to mangle, and which to keep (android vs. com.android.support).
      */
-    std::set<std::u16string> packagesToMangle;
+    std::set<std::string> packagesToMangle;
 };
 
 class NameMangler {
@@ -53,14 +52,11 @@
             return {};
         }
 
-        return ResourceName{
-                mPolicy.targetPackageName,
-                name.type,
-                mangleEntry(name.package, name.entry)
-        };
+        std::string mangledEntryName = mangleEntry(name.package, name.entry);
+        return ResourceName(mPolicy.targetPackageName, name.type, mangledEntryName);
     }
 
-    bool shouldMangle(const std::u16string& package) const {
+    bool shouldMangle(const std::string& package) const {
         if (package.empty() || mPolicy.targetPackageName == package) {
             return false;
         }
@@ -72,8 +68,8 @@
      * The mangled name should contain symbols that are illegal to define in XML,
      * so that there will never be name mangling collisions.
      */
-    static std::u16string mangleEntry(const std::u16string& package, const std::u16string& name) {
-        return package + u"$" + name;
+    static std::string mangleEntry(const std::string& package, const std::string& name) {
+        return package + "$" + name;
     }
 
     /**
@@ -81,8 +77,8 @@
      * and the package in `outPackage`. Returns true if the name was unmangled or
      * false if the name was never mangled to begin with.
      */
-    static bool unmangle(std::u16string* outName, std::u16string* outPackage) {
-        size_t pivot = outName->find(u'$');
+    static bool unmangle(std::string* outName, std::string* outPackage) {
+        size_t pivot = outName->find('$');
         if (pivot == std::string::npos) {
             return false;
         }
diff --git a/tools/aapt2/NameMangler_test.cpp b/tools/aapt2/NameMangler_test.cpp
index 6103655..f624df2 100644
--- a/tools/aapt2/NameMangler_test.cpp
+++ b/tools/aapt2/NameMangler_test.cpp
@@ -15,31 +15,32 @@
  */
 
 #include "NameMangler.h"
+#include "test/Test.h"
 
-#include <gtest/gtest.h>
 #include <string>
 
 namespace aapt {
 
 TEST(NameManglerTest, MangleName) {
-    std::u16string package = u"android.appcompat";
-    std::u16string name = u"Platform.AppCompat";
+    std::string package = "android.appcompat";
+    std::string name = "Platform.AppCompat";
 
-    NameMangler::mangle(package, &name);
-    EXPECT_EQ(name, u"android.appcompat$Platform.AppCompat");
+    std::string mangledName = NameMangler::mangleEntry(package, name);
+    EXPECT_EQ(mangledName, "android.appcompat$Platform.AppCompat");
 
-    std::u16string newPackage;
-    ASSERT_TRUE(NameMangler::unmangle(&name, &newPackage));
-    EXPECT_EQ(name, u"Platform.AppCompat");
-    EXPECT_EQ(newPackage, u"android.appcompat");
+    std::string unmangledPackage;
+    std::string unmangledName = mangledName;
+    ASSERT_TRUE(NameMangler::unmangle(&unmangledName, &unmangledPackage));
+    EXPECT_EQ(unmangledName, "Platform.AppCompat");
+    EXPECT_EQ(unmangledPackage, "android.appcompat");
 }
 
 TEST(NameManglerTest, IgnoreUnmangledName) {
-    std::u16string package;
-    std::u16string name = u"foo_bar";
+    std::string package;
+    std::string name = "foo_bar";
 
     EXPECT_FALSE(NameMangler::unmangle(&name, &package));
-    EXPECT_EQ(name, u"foo_bar");
+    EXPECT_EQ(name, "foo_bar");
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/Resource.cpp b/tools/aapt2/Resource.cpp
index 9328b69..b7a091e 100644
--- a/tools/aapt2/Resource.cpp
+++ b/tools/aapt2/Resource.cpp
@@ -22,62 +22,62 @@
 
 namespace aapt {
 
-StringPiece16 toString(ResourceType type) {
+StringPiece toString(ResourceType type) {
     switch (type) {
-        case ResourceType::kAnim:          return u"anim";
-        case ResourceType::kAnimator:      return u"animator";
-        case ResourceType::kArray:         return u"array";
-        case ResourceType::kAttr:          return u"attr";
-        case ResourceType::kAttrPrivate:   return u"^attr-private";
-        case ResourceType::kBool:          return u"bool";
-        case ResourceType::kColor:         return u"color";
-        case ResourceType::kDimen:         return u"dimen";
-        case ResourceType::kDrawable:      return u"drawable";
-        case ResourceType::kFraction:      return u"fraction";
-        case ResourceType::kId:            return u"id";
-        case ResourceType::kInteger:       return u"integer";
-        case ResourceType::kInterpolator:  return u"interpolator";
-        case ResourceType::kLayout:        return u"layout";
-        case ResourceType::kMenu:          return u"menu";
-        case ResourceType::kMipmap:        return u"mipmap";
-        case ResourceType::kPlurals:       return u"plurals";
-        case ResourceType::kRaw:           return u"raw";
-        case ResourceType::kString:        return u"string";
-        case ResourceType::kStyle:         return u"style";
-        case ResourceType::kStyleable:     return u"styleable";
-        case ResourceType::kTransition:    return u"transition";
-        case ResourceType::kXml:           return u"xml";
+        case ResourceType::kAnim:          return "anim";
+        case ResourceType::kAnimator:      return "animator";
+        case ResourceType::kArray:         return "array";
+        case ResourceType::kAttr:          return "attr";
+        case ResourceType::kAttrPrivate:   return "^attr-private";
+        case ResourceType::kBool:          return "bool";
+        case ResourceType::kColor:         return "color";
+        case ResourceType::kDimen:         return "dimen";
+        case ResourceType::kDrawable:      return "drawable";
+        case ResourceType::kFraction:      return "fraction";
+        case ResourceType::kId:            return "id";
+        case ResourceType::kInteger:       return "integer";
+        case ResourceType::kInterpolator:  return "interpolator";
+        case ResourceType::kLayout:        return "layout";
+        case ResourceType::kMenu:          return "menu";
+        case ResourceType::kMipmap:        return "mipmap";
+        case ResourceType::kPlurals:       return "plurals";
+        case ResourceType::kRaw:           return "raw";
+        case ResourceType::kString:        return "string";
+        case ResourceType::kStyle:         return "style";
+        case ResourceType::kStyleable:     return "styleable";
+        case ResourceType::kTransition:    return "transition";
+        case ResourceType::kXml:           return "xml";
     }
     return {};
 }
 
-static const std::map<StringPiece16, ResourceType> sResourceTypeMap {
-        { u"anim", ResourceType::kAnim },
-        { u"animator", ResourceType::kAnimator },
-        { u"array", ResourceType::kArray },
-        { u"attr", ResourceType::kAttr },
-        { u"^attr-private", ResourceType::kAttrPrivate },
-        { u"bool", ResourceType::kBool },
-        { u"color", ResourceType::kColor },
-        { u"dimen", ResourceType::kDimen },
-        { u"drawable", ResourceType::kDrawable },
-        { u"fraction", ResourceType::kFraction },
-        { u"id", ResourceType::kId },
-        { u"integer", ResourceType::kInteger },
-        { u"interpolator", ResourceType::kInterpolator },
-        { u"layout", ResourceType::kLayout },
-        { u"menu", ResourceType::kMenu },
-        { u"mipmap", ResourceType::kMipmap },
-        { u"plurals", ResourceType::kPlurals },
-        { u"raw", ResourceType::kRaw },
-        { u"string", ResourceType::kString },
-        { u"style", ResourceType::kStyle },
-        { u"styleable", ResourceType::kStyleable },
-        { u"transition", ResourceType::kTransition },
-        { u"xml", ResourceType::kXml },
+static const std::map<StringPiece, ResourceType> sResourceTypeMap {
+        { "anim", ResourceType::kAnim },
+        { "animator", ResourceType::kAnimator },
+        { "array", ResourceType::kArray },
+        { "attr", ResourceType::kAttr },
+        { "^attr-private", ResourceType::kAttrPrivate },
+        { "bool", ResourceType::kBool },
+        { "color", ResourceType::kColor },
+        { "dimen", ResourceType::kDimen },
+        { "drawable", ResourceType::kDrawable },
+        { "fraction", ResourceType::kFraction },
+        { "id", ResourceType::kId },
+        { "integer", ResourceType::kInteger },
+        { "interpolator", ResourceType::kInterpolator },
+        { "layout", ResourceType::kLayout },
+        { "menu", ResourceType::kMenu },
+        { "mipmap", ResourceType::kMipmap },
+        { "plurals", ResourceType::kPlurals },
+        { "raw", ResourceType::kRaw },
+        { "string", ResourceType::kString },
+        { "style", ResourceType::kStyle },
+        { "styleable", ResourceType::kStyleable },
+        { "transition", ResourceType::kTransition },
+        { "xml", ResourceType::kXml },
 };
 
-const ResourceType* parseResourceType(const StringPiece16& str) {
+const ResourceType* parseResourceType(const StringPiece& str) {
     auto iter = sResourceTypeMap.find(str);
     if (iter == std::end(sResourceTypeMap)) {
         return nullptr;
diff --git a/tools/aapt2/Resource.h b/tools/aapt2/Resource.h
index 03ca42b..22d75a2 100644
--- a/tools/aapt2/Resource.h
+++ b/tools/aapt2/Resource.h
@@ -24,6 +24,7 @@
 
 #include <iomanip>
 #include <limits>
+#include <sstream>
 #include <string>
 #include <tuple>
 #include <vector>
@@ -60,28 +61,28 @@
     kXml,
 };
 
-StringPiece16 toString(ResourceType type);
+StringPiece toString(ResourceType type);
 
 /**
  * Returns a pointer to a valid ResourceType, or nullptr if
  * the string was invalid.
  */
-const ResourceType* parseResourceType(const StringPiece16& str);
+const ResourceType* parseResourceType(const StringPiece& str);
 
 /**
  * A resource's name. This can uniquely identify
  * a resource in the ResourceTable.
  */
 struct ResourceName {
-    std::u16string package;
+    std::string package;
     ResourceType type;
-    std::u16string entry;
+    std::string entry;
 
     ResourceName() : type(ResourceType::kRaw) {}
-    ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e);
+    ResourceName(const StringPiece& p, ResourceType t, const StringPiece& e);
 
     bool isValid() const;
-    std::u16string toString() const;
+    std::string toString() const;
 };
 
 /**
@@ -91,15 +92,15 @@
  * of the original string.
  */
 struct ResourceNameRef {
-    StringPiece16 package;
+    StringPiece package;
     ResourceType type;
-    StringPiece16 entry;
+    StringPiece entry;
 
     ResourceNameRef() = default;
     ResourceNameRef(const ResourceNameRef&) = default;
     ResourceNameRef(ResourceNameRef&&) = default;
     ResourceNameRef(const ResourceName& rhs);
-    ResourceNameRef(const StringPiece16& p, ResourceType t, const StringPiece16& e);
+    ResourceNameRef(const StringPiece& p, ResourceType t, const StringPiece& e);
     ResourceNameRef& operator=(const ResourceNameRef& rhs) = default;
     ResourceNameRef& operator=(ResourceNameRef&& rhs) = default;
     ResourceNameRef& operator=(const ResourceName& rhs);
@@ -252,7 +253,7 @@
 // ResourceName implementation.
 //
 
-inline ResourceName::ResourceName(const StringPiece16& p, ResourceType t, const StringPiece16& e) :
+inline ResourceName::ResourceName(const StringPiece& p, ResourceType t, const StringPiece& e) :
         package(p.toString()), type(t), entry(e.toString()) {
 }
 
@@ -275,14 +276,6 @@
             != std::tie(rhs.package, rhs.type, rhs.entry);
 }
 
-inline std::u16string ResourceName::toString() const {
-    std::u16string result;
-    if (!package.empty()) {
-        result = package + u":";
-    }
-    return result + aapt::toString(type).toString() + u"/" + entry;
-}
-
 inline ::std::ostream& operator<<(::std::ostream& out, const ResourceName& name) {
     if (!name.package.empty()) {
         out << name.package << ":";
@@ -290,6 +283,11 @@
     return out << name.type << "/" << name.entry;
 }
 
+inline std::string ResourceName::toString() const {
+    std::stringstream stream;
+    stream << *this;
+    return stream.str();
+}
 
 //
 // ResourceNameRef implementation.
@@ -299,8 +297,8 @@
         package(rhs.package), type(rhs.type), entry(rhs.entry) {
 }
 
-inline ResourceNameRef::ResourceNameRef(const StringPiece16& p, ResourceType t,
-                                        const StringPiece16& e) :
+inline ResourceNameRef::ResourceNameRef(const StringPiece& p, ResourceType t,
+                                        const StringPiece& e) :
         package(p), type(t), entry(e) {
 }
 
@@ -312,7 +310,7 @@
 }
 
 inline ResourceName ResourceNameRef::toResourceName() const {
-    return { package.toString(), type, entry.toString() };
+    return ResourceName(package, type, entry);
 }
 
 inline bool ResourceNameRef::isValid() const {
diff --git a/tools/aapt2/ResourceParser.cpp b/tools/aapt2/ResourceParser.cpp
index a84c306..45d3db9 100644
--- a/tools/aapt2/ResourceParser.cpp
+++ b/tools/aapt2/ResourceParser.cpp
@@ -28,33 +28,33 @@
 
 namespace aapt {
 
-constexpr const char16_t* sXliffNamespaceUri = u"urn:oasis:names:tc:xliff:document:1.2";
+constexpr const char* sXliffNamespaceUri = "urn:oasis:names:tc:xliff:document:1.2";
 
 /**
  * Returns true if the element is <skip> or <eat-comment> and can be safely ignored.
  */
-static bool shouldIgnoreElement(const StringPiece16& ns, const StringPiece16& name) {
-    return ns.empty() && (name == u"skip" || name == u"eat-comment");
+static bool shouldIgnoreElement(const StringPiece& ns, const StringPiece& name) {
+    return ns.empty() && (name == "skip" || name == "eat-comment");
 }
 
-static uint32_t parseFormatType(const StringPiece16& piece) {
-    if (piece == u"reference")      return android::ResTable_map::TYPE_REFERENCE;
-    else if (piece == u"string")    return android::ResTable_map::TYPE_STRING;
-    else if (piece == u"integer")   return android::ResTable_map::TYPE_INTEGER;
-    else if (piece == u"boolean")   return android::ResTable_map::TYPE_BOOLEAN;
-    else if (piece == u"color")     return android::ResTable_map::TYPE_COLOR;
-    else if (piece == u"float")     return android::ResTable_map::TYPE_FLOAT;
-    else if (piece == u"dimension") return android::ResTable_map::TYPE_DIMENSION;
-    else if (piece == u"fraction")  return android::ResTable_map::TYPE_FRACTION;
-    else if (piece == u"enum")      return android::ResTable_map::TYPE_ENUM;
-    else if (piece == u"flags")     return android::ResTable_map::TYPE_FLAGS;
+static uint32_t parseFormatType(const StringPiece& piece) {
+    if (piece == "reference")      return android::ResTable_map::TYPE_REFERENCE;
+    else if (piece == "string")    return android::ResTable_map::TYPE_STRING;
+    else if (piece == "integer")   return android::ResTable_map::TYPE_INTEGER;
+    else if (piece == "boolean")   return android::ResTable_map::TYPE_BOOLEAN;
+    else if (piece == "color")     return android::ResTable_map::TYPE_COLOR;
+    else if (piece == "float")     return android::ResTable_map::TYPE_FLOAT;
+    else if (piece == "dimension") return android::ResTable_map::TYPE_DIMENSION;
+    else if (piece == "fraction")  return android::ResTable_map::TYPE_FRACTION;
+    else if (piece == "enum")      return android::ResTable_map::TYPE_ENUM;
+    else if (piece == "flags")     return android::ResTable_map::TYPE_FLAGS;
     return 0;
 }
 
-static uint32_t parseFormatAttribute(const StringPiece16& str) {
+static uint32_t parseFormatAttribute(const StringPiece& str) {
     uint32_t mask = 0;
-    for (StringPiece16 part : util::tokenize(str, u'|')) {
-        StringPiece16 trimmedPart = util::trimWhitespace(part);
+    for (StringPiece part : util::tokenize(str, '|')) {
+        StringPiece trimmedPart = util::trimWhitespace(part);
         uint32_t type = parseFormatType(trimmedPart);
         if (type == 0) {
             return 0;
@@ -74,14 +74,14 @@
     Source source;
     ResourceId id;
     Maybe<SymbolState> symbolState;
-    std::u16string comment;
+    std::string comment;
     std::unique_ptr<Value> value;
     std::list<ParsedResource> childResources;
 };
 
 // Recursively adds resources to the ResourceTable.
 static bool addResourcesToTable(ResourceTable* table, IDiagnostics* diag, ParsedResource* res) {
-    StringPiece16 trimmedComment = util::trimWhitespace(res->comment);
+    StringPiece trimmedComment = util::trimWhitespace(res->comment);
     if (trimmedComment.size() != res->comment.size()) {
         // Only if there was a change do we re-assign.
         res->comment = trimmedComment.toString();
@@ -130,7 +130,7 @@
 /**
  * Build a string from XML that converts nested elements into Span objects.
  */
-bool ResourceParser::flattenXmlSubtree(xml::XmlPullParser* parser, std::u16string* outRawString,
+bool ResourceParser::flattenXmlSubtree(xml::XmlPullParser* parser, std::string* outRawString,
                                        StyleString* outStyleString) {
     std::vector<Span> spanStack;
 
@@ -176,12 +176,12 @@
             depth++;
 
             // Build a span object out of the nested element.
-            std::u16string spanName = parser->getElementName();
+            std::string spanName = parser->getElementName();
             const auto endAttrIter = parser->endAttributes();
             for (auto attrIter = parser->beginAttributes(); attrIter != endAttrIter; ++attrIter) {
-                spanName += u";";
+                spanName += ";";
                 spanName += attrIter->name;
-                spanName += u"=";
+                spanName += "=";
                 spanName += attrIter->value;
             }
 
@@ -214,7 +214,7 @@
             continue;
         }
 
-        if (!parser->getElementNamespace().empty() || parser->getElementName() != u"resources") {
+        if (!parser->getElementNamespace().empty() || parser->getElementName() != "resources") {
             mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
                          << "root element must be <resources>");
             return false;
@@ -236,7 +236,7 @@
     std::set<ResourceName> strippedResources;
 
     bool error = false;
-    std::u16string comment;
+    std::string comment;
     const size_t depth = parser->getDepth();
     while (xml::XmlPullParser::nextChildNode(parser, depth)) {
         const xml::XmlPullParser::Event event = parser->getEvent();
@@ -261,9 +261,9 @@
             continue;
         }
 
-        std::u16string elementName = parser->getElementName();
-        if (elementName == u"skip" || elementName == u"eat-comment") {
-            comment = u"";
+        std::string elementName = parser->getElementName();
+        if (elementName == "skip" || elementName == "eat-comment") {
+            comment = "";
             continue;
         }
 
@@ -273,8 +273,8 @@
         parsedResource.comment = std::move(comment);
 
         // Extract the product name if it exists.
-        if (Maybe<StringPiece16> maybeProduct = xml::findNonEmptyAttribute(parser, u"product")) {
-            parsedResource.product = util::utf16ToUtf8(maybeProduct.value());
+        if (Maybe<StringPiece> maybeProduct = xml::findNonEmptyAttribute(parser, "product")) {
+            parsedResource.product = maybeProduct.value().toString();
         }
 
         // Parse the resource regardless of product.
@@ -310,43 +310,43 @@
 
     using BagParseFunc = std::function<bool(ResourceParser*, xml::XmlPullParser*, ParsedResource*)>;
 
-    static const auto elToItemMap = ImmutableMap<std::u16string, ItemTypeFormat>::createPreSorted({
-            { u"bool",      { ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN } },
-            { u"color",     { ResourceType::kColor, android::ResTable_map::TYPE_COLOR } },
-            { u"dimen",     { ResourceType::kDimen, android::ResTable_map::TYPE_FLOAT
+    static const auto elToItemMap = ImmutableMap<std::string, ItemTypeFormat>::createPreSorted({
+            { "bool",      { ResourceType::kBool, android::ResTable_map::TYPE_BOOLEAN } },
+            { "color",     { ResourceType::kColor, android::ResTable_map::TYPE_COLOR } },
+            { "dimen",     { ResourceType::kDimen, android::ResTable_map::TYPE_FLOAT
                                                     | android::ResTable_map::TYPE_FRACTION
                                                     | android::ResTable_map::TYPE_DIMENSION } },
-            { u"drawable",  { ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR } },
-            { u"fraction",  { ResourceType::kFraction, android::ResTable_map::TYPE_FLOAT
+            { "drawable",  { ResourceType::kDrawable, android::ResTable_map::TYPE_COLOR } },
+            { "fraction",  { ResourceType::kFraction, android::ResTable_map::TYPE_FLOAT
                                                        | android::ResTable_map::TYPE_FRACTION
                                                        | android::ResTable_map::TYPE_DIMENSION } },
-            { u"integer",   { ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER } },
-            { u"string",    { ResourceType::kString, android::ResTable_map::TYPE_STRING } },
+            { "integer",   { ResourceType::kInteger, android::ResTable_map::TYPE_INTEGER } },
+            { "string",    { ResourceType::kString, android::ResTable_map::TYPE_STRING } },
     });
 
-    static const auto elToBagMap = ImmutableMap<std::u16string, BagParseFunc>::createPreSorted({
-            { u"add-resource",      std::mem_fn(&ResourceParser::parseAddResource) },
-            { u"array",             std::mem_fn(&ResourceParser::parseArray) },
-            { u"attr",              std::mem_fn(&ResourceParser::parseAttr) },
-            { u"declare-styleable", std::mem_fn(&ResourceParser::parseDeclareStyleable) },
-            { u"integer-array",     std::mem_fn(&ResourceParser::parseIntegerArray) },
-            { u"java-symbol",       std::mem_fn(&ResourceParser::parseSymbol) },
-            { u"plurals",           std::mem_fn(&ResourceParser::parsePlural) },
-            { u"public",            std::mem_fn(&ResourceParser::parsePublic) },
-            { u"public-group",      std::mem_fn(&ResourceParser::parsePublicGroup) },
-            { u"string-array",      std::mem_fn(&ResourceParser::parseStringArray) },
-            { u"style",             std::mem_fn(&ResourceParser::parseStyle) },
-            { u"symbol",            std::mem_fn(&ResourceParser::parseSymbol) },
+    static const auto elToBagMap = ImmutableMap<std::string, BagParseFunc>::createPreSorted({
+            { "add-resource",      std::mem_fn(&ResourceParser::parseAddResource) },
+            { "array",             std::mem_fn(&ResourceParser::parseArray) },
+            { "attr",              std::mem_fn(&ResourceParser::parseAttr) },
+            { "declare-styleable", std::mem_fn(&ResourceParser::parseDeclareStyleable) },
+            { "integer-array",     std::mem_fn(&ResourceParser::parseIntegerArray) },
+            { "java-symbol",       std::mem_fn(&ResourceParser::parseSymbol) },
+            { "plurals",           std::mem_fn(&ResourceParser::parsePlural) },
+            { "public",            std::mem_fn(&ResourceParser::parsePublic) },
+            { "public-group",      std::mem_fn(&ResourceParser::parsePublicGroup) },
+            { "string-array",      std::mem_fn(&ResourceParser::parseStringArray) },
+            { "style",             std::mem_fn(&ResourceParser::parseStyle) },
+            { "symbol",            std::mem_fn(&ResourceParser::parseSymbol) },
     });
 
-    std::u16string resourceType = parser->getElementName();
+    std::string resourceType = parser->getElementName();
 
     // The value format accepted for this resource.
     uint32_t resourceFormat = 0u;
 
-    if (resourceType == u"item") {
+    if (resourceType == "item") {
         // Items have their type encoded in the type attribute.
-        if (Maybe<StringPiece16> maybeType = xml::findNonEmptyAttribute(parser, u"type")) {
+        if (Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type")) {
             resourceType = maybeType.value().toString();
         } else {
             mDiag->error(DiagMessage(mSource.withLine(parser->getLineNumber()))
@@ -354,7 +354,7 @@
             return false;
         }
 
-        if (Maybe<StringPiece16> maybeFormat = xml::findNonEmptyAttribute(parser, u"format")) {
+        if (Maybe<StringPiece> maybeFormat = xml::findNonEmptyAttribute(parser, "format")) {
             // An explicit format for this resource was specified. The resource will retain
             // its type in its name, but the accepted value for this type is overridden.
             resourceFormat = parseFormatType(maybeFormat.value());
@@ -368,9 +368,9 @@
 
     // Get the name of the resource. This will be checked later, because not all
     // XML elements require a name.
-    Maybe<StringPiece16> maybeName = xml::findNonEmptyAttribute(parser, u"name");
+    Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
 
-    if (resourceType == u"id") {
+    if (resourceType == "id") {
         if (!maybeName) {
             mDiag->error(DiagMessage(outResource->source)
                          << "<" << parser->getElementName() << "> missing 'name' attribute");
@@ -411,7 +411,7 @@
     const auto bagIter = elToBagMap.find(resourceType);
     if (bagIter != elToBagMap.end()) {
         // Ensure we have a name (unless this is a <public-group>).
-        if (resourceType != u"public-group") {
+        if (resourceType != "public-group") {
             if (!maybeName) {
                 mDiag->error(DiagMessage(outResource->source)
                              << "<" << parser->getElementName() << "> missing 'name' attribute");
@@ -480,7 +480,7 @@
                                                const bool allowRawValue) {
     const size_t beginXmlLine = parser->getLineNumber();
 
-    std::u16string rawValue;
+    std::string rawValue;
     StyleString styleString;
     if (!flattenXmlSubtree(parser, &rawValue, &styleString)) {
         return {};
@@ -505,7 +505,7 @@
     if (processedItem) {
         // Fix up the reference.
         if (Reference* ref = valueCast<Reference>(processedItem.get())) {
-            transformReferenceFromNamespace(parser, u"", ref);
+            transformReferenceFromNamespace(parser, "", ref);
         }
         return processedItem;
     }
@@ -527,7 +527,7 @@
 
 bool ResourceParser::parseString(xml::XmlPullParser* parser, ParsedResource* outResource) {
     bool formatted = true;
-    if (Maybe<StringPiece16> formattedAttr = xml::findAttribute(parser, u"formatted")) {
+    if (Maybe<StringPiece> formattedAttr = xml::findAttribute(parser, "formatted")) {
         if (!ResourceUtils::tryParseBool(formattedAttr.value(), &formatted)) {
             mDiag->error(DiagMessage(outResource->source)
                          << "invalid value for 'formatted'. Must be a boolean");
@@ -536,7 +536,7 @@
     }
 
     bool translateable = mOptions.translatable;
-    if (Maybe<StringPiece16> translateableAttr = xml::findAttribute(parser, u"translatable")) {
+    if (Maybe<StringPiece> translateableAttr = xml::findAttribute(parser, "translatable")) {
         if (!ResourceUtils::tryParseBool(translateableAttr.value(), &translateable)) {
             mDiag->error(DiagMessage(outResource->source)
                          << "invalid value for 'translatable'. Must be a boolean");
@@ -574,7 +574,7 @@
 }
 
 bool ResourceParser::parsePublic(xml::XmlPullParser* parser, ParsedResource* outResource) {
-    Maybe<StringPiece16> maybeType = xml::findNonEmptyAttribute(parser, u"type");
+    Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
     if (!maybeType) {
         mDiag->error(DiagMessage(outResource->source) << "<public> must have a 'type' attribute");
         return false;
@@ -589,10 +589,10 @@
 
     outResource->name.type = *parsedType;
 
-    if (Maybe<StringPiece16> maybeId = xml::findNonEmptyAttribute(parser, u"id")) {
+    if (Maybe<StringPiece> maybeId = xml::findNonEmptyAttribute(parser, "id")) {
         android::Res_value val;
-        bool result = android::ResTable::stringToInt(maybeId.value().data(),
-                                                     maybeId.value().size(), &val);
+        std::u16string idStr16 = util::utf8ToUtf16(maybeId.value());
+        bool result = android::ResTable::stringToInt(idStr16.data(), idStr16.size(), &val);
         ResourceId resourceId(val.data);
         if (!result || !resourceId.isValid()) {
             mDiag->error(DiagMessage(outResource->source)
@@ -612,7 +612,7 @@
 }
 
 bool ResourceParser::parsePublicGroup(xml::XmlPullParser* parser, ParsedResource* outResource) {
-    Maybe<StringPiece16> maybeType = xml::findNonEmptyAttribute(parser, u"type");
+    Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
     if (!maybeType) {
         mDiag->error(DiagMessage(outResource->source)
                      << "<public-group> must have a 'type' attribute");
@@ -626,7 +626,7 @@
         return false;
     }
 
-    Maybe<StringPiece16> maybeId = xml::findNonEmptyAttribute(parser, u"first-id");
+    Maybe<StringPiece> maybeId = xml::findNonEmptyAttribute(parser, "first-id");
     if (!maybeId) {
         mDiag->error(DiagMessage(outResource->source)
                      << "<public-group> must have a 'first-id' attribute");
@@ -634,8 +634,8 @@
     }
 
     android::Res_value val;
-    bool result = android::ResTable::stringToInt(maybeId.value().data(),
-                                                 maybeId.value().size(), &val);
+    std::u16string idStr16 = util::utf8ToUtf16(maybeId.value());
+    bool result = android::ResTable::stringToInt(idStr16.data(), idStr16.size(), &val);
     ResourceId nextId(val.data);
     if (!result || !nextId.isValid()) {
         mDiag->error(DiagMessage(outResource->source)
@@ -643,7 +643,7 @@
         return false;
     }
 
-    std::u16string comment;
+    std::string comment;
     bool error = false;
     const size_t depth = parser->getDepth();
     while (xml::XmlPullParser::nextChildNode(parser, depth)) {
@@ -656,23 +656,23 @@
         }
 
         const Source itemSource = mSource.withLine(parser->getLineNumber());
-        const std::u16string& elementNamespace = parser->getElementNamespace();
-        const std::u16string& elementName = parser->getElementName();
-        if (elementNamespace.empty() && elementName == u"public") {
-            Maybe<StringPiece16> maybeName = xml::findNonEmptyAttribute(parser, u"name");
+        const std::string& elementNamespace = parser->getElementNamespace();
+        const std::string& elementName = parser->getElementName();
+        if (elementNamespace.empty() && elementName == "public") {
+            Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
             if (!maybeName) {
                 mDiag->error(DiagMessage(itemSource) << "<public> must have a 'name' attribute");
                 error = true;
                 continue;
             }
 
-            if (xml::findNonEmptyAttribute(parser, u"id")) {
+            if (xml::findNonEmptyAttribute(parser, "id")) {
                 mDiag->error(DiagMessage(itemSource) << "'id' is ignored within <public-group>");
                 error = true;
                 continue;
             }
 
-            if (xml::findNonEmptyAttribute(parser, u"type")) {
+            if (xml::findNonEmptyAttribute(parser, "type")) {
                 mDiag->error(DiagMessage(itemSource) << "'type' is ignored within <public-group>");
                 error = true;
                 continue;
@@ -698,7 +698,7 @@
 }
 
 bool ResourceParser::parseSymbolImpl(xml::XmlPullParser* parser, ParsedResource* outResource) {
-    Maybe<StringPiece16> maybeType = xml::findNonEmptyAttribute(parser, u"type");
+    Maybe<StringPiece> maybeType = xml::findNonEmptyAttribute(parser, "type");
     if (!maybeType) {
         mDiag->error(DiagMessage(outResource->source)
                      << "<" << parser->getElementName() << "> must have a 'type' attribute");
@@ -751,7 +751,7 @@
 
     uint32_t typeMask = 0;
 
-    Maybe<StringPiece16> maybeFormat = xml::findAttribute(parser, u"format");
+    Maybe<StringPiece> maybeFormat = xml::findAttribute(parser, "format");
     if (maybeFormat) {
         typeMask = parseFormatAttribute(maybeFormat.value());
         if (typeMask == 0) {
@@ -763,11 +763,12 @@
 
     Maybe<int32_t> maybeMin, maybeMax;
 
-    if (Maybe<StringPiece16> maybeMinStr = xml::findAttribute(parser, u"min")) {
-        StringPiece16 minStr = util::trimWhitespace(maybeMinStr.value());
+    if (Maybe<StringPiece> maybeMinStr = xml::findAttribute(parser, "min")) {
+        StringPiece minStr = util::trimWhitespace(maybeMinStr.value());
         if (!minStr.empty()) {
+            std::u16string minStr16 = util::utf8ToUtf16(minStr);
             android::Res_value value;
-            if (android::ResTable::stringToInt(minStr.data(), minStr.size(), &value)) {
+            if (android::ResTable::stringToInt(minStr16.data(), minStr16.size(), &value)) {
                 maybeMin = static_cast<int32_t>(value.data);
             }
         }
@@ -779,11 +780,12 @@
         }
     }
 
-    if (Maybe<StringPiece16> maybeMaxStr = xml::findAttribute(parser, u"max")) {
-        StringPiece16 maxStr = util::trimWhitespace(maybeMaxStr.value());
+    if (Maybe<StringPiece> maybeMaxStr = xml::findAttribute(parser, "max")) {
+        StringPiece maxStr = util::trimWhitespace(maybeMaxStr.value());
         if (!maxStr.empty()) {
+            std::u16string maxStr16 = util::utf8ToUtf16(maxStr);
             android::Res_value value;
-            if (android::ResTable::stringToInt(maxStr.data(), maxStr.size(), &value)) {
+            if (android::ResTable::stringToInt(maxStr16.data(), maxStr16.size(), &value)) {
                 maybeMax = static_cast<int32_t>(value.data);
             }
         }
@@ -809,7 +811,7 @@
 
     std::set<Attribute::Symbol, SymbolComparator> items;
 
-    std::u16string comment;
+    std::string comment;
     bool error = false;
     const size_t depth = parser->getDepth();
     while (xml::XmlPullParser::nextChildNode(parser, depth)) {
@@ -822,10 +824,10 @@
         }
 
         const Source itemSource = mSource.withLine(parser->getLineNumber());
-        const std::u16string& elementNamespace = parser->getElementNamespace();
-        const std::u16string& elementName = parser->getElementName();
-        if (elementNamespace.empty() && (elementName == u"flag" || elementName == u"enum")) {
-            if (elementName == u"enum") {
+        const std::string& elementNamespace = parser->getElementNamespace();
+        const std::string& elementName = parser->getElementName();
+        if (elementNamespace.empty() && (elementName == "flag" || elementName == "enum")) {
+            if (elementName == "enum") {
                 if (typeMask & android::ResTable_map::TYPE_FLAGS) {
                     mDiag->error(DiagMessage(itemSource)
                                  << "can not define an <enum>; already defined a <flag>");
@@ -834,7 +836,7 @@
                 }
                 typeMask |= android::ResTable_map::TYPE_ENUM;
 
-            } else if (elementName == u"flag") {
+            } else if (elementName == "flag") {
                 if (typeMask & android::ResTable_map::TYPE_ENUM) {
                     mDiag->error(DiagMessage(itemSource)
                                  << "can not define a <flag>; already defined an <enum>");
@@ -896,24 +898,24 @@
 }
 
 Maybe<Attribute::Symbol> ResourceParser::parseEnumOrFlagItem(xml::XmlPullParser* parser,
-                                                             const StringPiece16& tag) {
+                                                             const StringPiece& tag) {
     const Source source = mSource.withLine(parser->getLineNumber());
 
-    Maybe<StringPiece16> maybeName = xml::findNonEmptyAttribute(parser, u"name");
+    Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
     if (!maybeName) {
         mDiag->error(DiagMessage(source) << "no attribute 'name' found for tag <" << tag << ">");
         return {};
     }
 
-    Maybe<StringPiece16> maybeValue = xml::findNonEmptyAttribute(parser, u"value");
+    Maybe<StringPiece> maybeValue = xml::findNonEmptyAttribute(parser, "value");
     if (!maybeValue) {
         mDiag->error(DiagMessage(source) << "no attribute 'value' found for tag <" << tag << ">");
         return {};
     }
 
+    std::u16string value16 = util::utf8ToUtf16(maybeValue.value());
     android::Res_value val;
-    if (!android::ResTable::stringToInt(maybeValue.value().data(),
-                                        maybeValue.value().size(), &val)) {
+    if (!android::ResTable::stringToInt(value16.data(), value16.size(), &val)) {
         mDiag->error(DiagMessage(source) << "invalid value '" << maybeValue.value()
                      << "' for <" << tag << ">; must be an integer");
         return {};
@@ -923,25 +925,25 @@
             Reference(ResourceNameRef({}, ResourceType::kId, maybeName.value())), val.data };
 }
 
-static Maybe<Reference> parseXmlAttributeName(StringPiece16 str) {
+static Maybe<Reference> parseXmlAttributeName(StringPiece str) {
     str = util::trimWhitespace(str);
-    const char16_t* start = str.data();
-    const char16_t* const end = start + str.size();
-    const char16_t* p = start;
+    const char* start = str.data();
+    const char* const end = start + str.size();
+    const char* p = start;
 
     Reference ref;
-    if (p != end && *p == u'*') {
+    if (p != end && *p == '*') {
         ref.privateReference = true;
         start++;
         p++;
     }
 
-    StringPiece16 package;
-    StringPiece16 name;
+    StringPiece package;
+    StringPiece name;
     while (p != end) {
-        if (*p == u':') {
-            package = StringPiece16(start, p - start);
-            name = StringPiece16(p + 1, end - (p + 1));
+        if (*p == ':') {
+            package = StringPiece(start, p - start);
+            name = StringPiece(p + 1, end - (p + 1));
             break;
         }
         p++;
@@ -955,7 +957,7 @@
 bool ResourceParser::parseStyleItem(xml::XmlPullParser* parser, Style* style) {
     const Source source = mSource.withLine(parser->getLineNumber());
 
-    Maybe<StringPiece16> maybeName = xml::findNonEmptyAttribute(parser, u"name");
+    Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
     if (!maybeName) {
         mDiag->error(DiagMessage(source) << "<item> must have a 'name' attribute");
         return false;
@@ -967,7 +969,7 @@
         return false;
     }
 
-    transformReferenceFromNamespace(parser, u"", &maybeKey.value());
+    transformReferenceFromNamespace(parser, "", &maybeKey.value());
     maybeKey.value().setSource(source);
 
     std::unique_ptr<Item> value = parseXml(parser, 0, kAllowRawString);
@@ -985,7 +987,7 @@
 
     std::unique_ptr<Style> style = util::make_unique<Style>();
 
-    Maybe<StringPiece16> maybeParent = xml::findAttribute(parser, u"parent");
+    Maybe<StringPiece> maybeParent = xml::findAttribute(parser, "parent");
     if (maybeParent) {
         // If the parent is empty, we don't have a parent, but we also don't infer either.
         if (!maybeParent.value().empty()) {
@@ -998,12 +1000,12 @@
 
             // Transform the namespace prefix to the actual package name, and mark the reference as
             // private if appropriate.
-            transformReferenceFromNamespace(parser, u"", &style->parent.value());
+            transformReferenceFromNamespace(parser, "", &style->parent.value());
         }
 
     } else {
         // No parent was specified, so try inferring it from the style name.
-        std::u16string styleName = outResource->name.entry;
+        std::string styleName = outResource->name.entry;
         size_t pos = styleName.find_last_of(u'.');
         if (pos != std::string::npos) {
             style->parentInferred = true;
@@ -1020,9 +1022,9 @@
             continue;
         }
 
-        const std::u16string& elementNamespace = parser->getElementNamespace();
-        const std::u16string& elementName = parser->getElementName();
-        if (elementNamespace == u"" && elementName == u"item") {
+        const std::string& elementNamespace = parser->getElementNamespace();
+        const std::string& elementName = parser->getElementName();
+        if (elementNamespace == "" && elementName == "item") {
             error |= !parseStyleItem(parser, style.get());
 
         } else if (!shouldIgnoreElement(elementNamespace, elementName)) {
@@ -1059,7 +1061,7 @@
     std::unique_ptr<Array> array = util::make_unique<Array>();
 
     bool translateable = mOptions.translatable;
-    if (Maybe<StringPiece16> translateableAttr = xml::findAttribute(parser, u"translatable")) {
+    if (Maybe<StringPiece> translateableAttr = xml::findAttribute(parser, "translatable")) {
         if (!ResourceUtils::tryParseBool(translateableAttr.value(), &translateable)) {
             mDiag->error(DiagMessage(outResource->source)
                          << "invalid value for 'translatable'. Must be a boolean");
@@ -1077,9 +1079,9 @@
         }
 
         const Source itemSource = mSource.withLine(parser->getLineNumber());
-        const std::u16string& elementNamespace = parser->getElementNamespace();
-        const std::u16string& elementName = parser->getElementName();
-        if (elementNamespace.empty() && elementName == u"item") {
+        const std::string& elementNamespace = parser->getElementNamespace();
+        const std::string& elementName = parser->getElementName();
+        if (elementNamespace.empty() && elementName == "item") {
             std::unique_ptr<Item> item = parseXml(parser, typeMask, kNoRawString);
             if (!item) {
                 mDiag->error(DiagMessage(itemSource) << "could not parse array item");
@@ -1118,10 +1120,10 @@
         }
 
         const Source itemSource = mSource.withLine(parser->getLineNumber());
-        const std::u16string& elementNamespace = parser->getElementNamespace();
-        const std::u16string& elementName = parser->getElementName();
-        if (elementNamespace.empty() && elementName == u"item") {
-            Maybe<StringPiece16> maybeQuantity = xml::findNonEmptyAttribute(parser, u"quantity");
+        const std::string& elementNamespace = parser->getElementNamespace();
+        const std::string& elementName = parser->getElementName();
+        if (elementNamespace.empty() && elementName == "item") {
+            Maybe<StringPiece> maybeQuantity = xml::findNonEmptyAttribute(parser, "quantity");
             if (!maybeQuantity) {
                 mDiag->error(DiagMessage(itemSource) << "<item> in <plurals> requires attribute "
                              << "'quantity'");
@@ -1129,19 +1131,19 @@
                 continue;
             }
 
-            StringPiece16 trimmedQuantity = util::trimWhitespace(maybeQuantity.value());
+            StringPiece trimmedQuantity = util::trimWhitespace(maybeQuantity.value());
             size_t index = 0;
-            if (trimmedQuantity == u"zero") {
+            if (trimmedQuantity == "zero") {
                 index = Plural::Zero;
-            } else if (trimmedQuantity == u"one") {
+            } else if (trimmedQuantity == "one") {
                 index = Plural::One;
-            } else if (trimmedQuantity == u"two") {
+            } else if (trimmedQuantity == "two") {
                 index = Plural::Two;
-            } else if (trimmedQuantity == u"few") {
+            } else if (trimmedQuantity == "few") {
                 index = Plural::Few;
-            } else if (trimmedQuantity == u"many") {
+            } else if (trimmedQuantity == "many") {
                 index = Plural::Many;
-            } else if (trimmedQuantity == u"other") {
+            } else if (trimmedQuantity == "other") {
                 index = Plural::Other;
             } else {
                 mDiag->error(DiagMessage(itemSource)
@@ -1196,7 +1198,7 @@
 
     std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
 
-    std::u16string comment;
+    std::string comment;
     bool error = false;
     const size_t depth = parser->getDepth();
     while (xml::XmlPullParser::nextChildNode(parser, depth)) {
@@ -1209,10 +1211,10 @@
         }
 
         const Source itemSource = mSource.withLine(parser->getLineNumber());
-        const std::u16string& elementNamespace = parser->getElementNamespace();
-        const std::u16string& elementName = parser->getElementName();
-        if (elementNamespace.empty() && elementName == u"attr") {
-            Maybe<StringPiece16> maybeName = xml::findNonEmptyAttribute(parser, u"name");
+        const std::string& elementNamespace = parser->getElementNamespace();
+        const std::string& elementName = parser->getElementName();
+        if (elementNamespace.empty() && elementName == "attr") {
+            Maybe<StringPiece> maybeName = xml::findNonEmptyAttribute(parser, "name");
             if (!maybeName) {
                 mDiag->error(DiagMessage(itemSource) << "<attr> tag must have a 'name' attribute");
                 error = true;
@@ -1230,7 +1232,7 @@
             }
 
             Reference& childRef = maybeRef.value();
-            xml::transformReferenceFromNamespace(parser, u"", &childRef);
+            xml::transformReferenceFromNamespace(parser, "", &childRef);
 
             // Create the ParsedResource that will add the attribute to the table.
             ParsedResource childResource;
diff --git a/tools/aapt2/ResourceParser.h b/tools/aapt2/ResourceParser.h
index ee5b337..ece3090 100644
--- a/tools/aapt2/ResourceParser.h
+++ b/tools/aapt2/ResourceParser.h
@@ -63,7 +63,7 @@
      * contains the escaped and whitespace trimmed text, while `outRawString`
      * contains the unescaped text. Returns true on success.
      */
-    bool flattenXmlSubtree(xml::XmlPullParser* parser, std::u16string* outRawString,
+    bool flattenXmlSubtree(xml::XmlPullParser* parser, std::string* outRawString,
                            StyleString* outStyleString);
 
     /*
@@ -89,7 +89,7 @@
     bool parseAttr(xml::XmlPullParser* parser, ParsedResource* outResource);
     bool parseAttrImpl(xml::XmlPullParser* parser, ParsedResource* outResource, bool weak);
     Maybe<Attribute::Symbol> parseEnumOrFlagItem(xml::XmlPullParser* parser,
-                                                 const StringPiece16& tag);
+                                                 const StringPiece& tag);
     bool parseStyle(xml::XmlPullParser* parser, ParsedResource* outResource);
     bool parseStyleItem(xml::XmlPullParser* parser, Style* style);
     bool parseDeclareStyleable(xml::XmlPullParser* parser, ParsedResource* outResource);
diff --git a/tools/aapt2/ResourceParser_test.cpp b/tools/aapt2/ResourceParser_test.cpp
index 3450de9..b456c04 100644
--- a/tools/aapt2/ResourceParser_test.cpp
+++ b/tools/aapt2/ResourceParser_test.cpp
@@ -18,10 +18,9 @@
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
-#include "test/Context.h"
+#include "test/Test.h"
 #include "xml/XmlPullParser.h"
 
-#include <gtest/gtest.h>
 #include <sstream>
 #include <string>
 
@@ -69,18 +68,18 @@
     std::string input = "<string name=\"foo\">   \"  hey there \" </string>";
     ASSERT_TRUE(testParse(input));
 
-    String* str = test::getValue<String>(&mTable, u"@string/foo");
+    String* str = test::getValue<String>(&mTable, "@string/foo");
     ASSERT_NE(nullptr, str);
-    EXPECT_EQ(std::u16string(u"  hey there "), *str->value);
+    EXPECT_EQ(std::string("  hey there "), *str->value);
 }
 
 TEST_F(ResourceParserTest, ParseEscapedString) {
     std::string input = "<string name=\"foo\">\\?123</string>";
     ASSERT_TRUE(testParse(input));
 
-    String* str = test::getValue<String>(&mTable, u"@string/foo");
+    String* str = test::getValue<String>(&mTable, "@string/foo");
     ASSERT_NE(nullptr, str);
-    EXPECT_EQ(std::u16string(u"?123"), *str->value);
+    EXPECT_EQ(std::string("?123"), *str->value);
 }
 
 TEST_F(ResourceParserTest, ParseFormattedString) {
@@ -97,9 +96,9 @@
                         "  There are <xliff:g id=\"count\">%1$d</xliff:g> apples</string>";
     ASSERT_TRUE(testParse(input));
 
-    String* str = test::getValue<String>(&mTable, u"@string/foo");
+    String* str = test::getValue<String>(&mTable, "@string/foo");
     ASSERT_NE(nullptr, str);
-    EXPECT_EQ(StringPiece16(u"There are %1$d apples"), StringPiece16(*str->value));
+    EXPECT_EQ(StringPiece("There are %1$d apples"), StringPiece(*str->value));
 }
 
 TEST_F(ResourceParserTest, ParseNull) {
@@ -110,7 +109,7 @@
     // a non-existing value, and this causes problems in styles when trying to resolve
     // an attribute. Null values must be encoded as android::Res_value::TYPE_REFERENCE
     // with a data value of 0.
-    BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo");
+    BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, "@integer/foo");
     ASSERT_NE(nullptr, integer);
     EXPECT_EQ(uint16_t(android::Res_value::TYPE_REFERENCE), integer->value.dataType);
     EXPECT_EQ(0u, integer->value.data);
@@ -120,7 +119,7 @@
     std::string input = "<integer name=\"foo\">@empty</integer>";
     ASSERT_TRUE(testParse(input));
 
-    BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo");
+    BinaryPrimitive* integer = test::getValue<BinaryPrimitive>(&mTable, "@integer/foo");
     ASSERT_NE(nullptr, integer);
     EXPECT_EQ(uint16_t(android::Res_value::TYPE_NULL), integer->value.dataType);
     EXPECT_EQ(uint32_t(android::Res_value::DATA_NULL_EMPTY), integer->value.data);
@@ -131,11 +130,11 @@
                         "<attr name=\"bar\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+    Attribute* attr = test::getValue<Attribute>(&mTable, "@attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask);
 
-    attr = test::getValue<Attribute>(&mTable, u"@attr/bar");
+    attr = test::getValue<Attribute>(&mTable, "@attr/bar");
     ASSERT_NE(nullptr, attr);
     EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_ANY), attr->typeMask);
 }
@@ -151,20 +150,20 @@
         </declare-styleable>)EOF";
     ASSERT_TRUE(testParse(input, watchConfig));
 
-    EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, u"@attr/foo", watchConfig));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, u"@attr/baz", watchConfig));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Styleable>(&mTable, u"@styleable/bar", watchConfig));
+    EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, "@attr/foo", watchConfig));
+    EXPECT_EQ(nullptr, test::getValueForConfig<Attribute>(&mTable, "@attr/baz", watchConfig));
+    EXPECT_EQ(nullptr, test::getValueForConfig<Styleable>(&mTable, "@styleable/bar", watchConfig));
 
-    EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, u"@attr/foo"));
-    EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, u"@attr/baz"));
-    EXPECT_NE(nullptr, test::getValue<Styleable>(&mTable, u"@styleable/bar"));
+    EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, "@attr/foo"));
+    EXPECT_NE(nullptr, test::getValue<Attribute>(&mTable, "@attr/baz"));
+    EXPECT_NE(nullptr, test::getValue<Styleable>(&mTable, "@styleable/bar"));
 }
 
 TEST_F(ResourceParserTest, ParseAttrWithMinMax) {
     std::string input = "<attr name=\"foo\" min=\"10\" max=\"23\" format=\"integer\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+    Attribute* attr = test::getValue<Attribute>(&mTable, "@attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_INTEGER), attr->typeMask);
     EXPECT_EQ(10, attr->minInt);
@@ -183,7 +182,7 @@
                         "<attr name=\"foo\" format=\"string\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+    Attribute* attr = test::getValue<Attribute>(&mTable, "@attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_STRING), attr->typeMask);
 }
@@ -197,7 +196,7 @@
                         "</declare-styleable>";
     ASSERT_TRUE(testParse(input));
 
-    Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+    Attribute* attr = test::getValue<Attribute>(&mTable, "@attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_EQ(uint32_t(android::ResTable_map::TYPE_BOOLEAN), attr->typeMask);
 }
@@ -210,21 +209,21 @@
                         "</attr>";
     ASSERT_TRUE(testParse(input));
 
-    Attribute* enumAttr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+    Attribute* enumAttr = test::getValue<Attribute>(&mTable, "@attr/foo");
     ASSERT_NE(enumAttr, nullptr);
     EXPECT_EQ(enumAttr->typeMask, android::ResTable_map::TYPE_ENUM);
     ASSERT_EQ(enumAttr->symbols.size(), 3u);
 
     AAPT_ASSERT_TRUE(enumAttr->symbols[0].symbol.name);
-    EXPECT_EQ(enumAttr->symbols[0].symbol.name.value().entry, u"bar");
+    EXPECT_EQ(enumAttr->symbols[0].symbol.name.value().entry, "bar");
     EXPECT_EQ(enumAttr->symbols[0].value, 0u);
 
     AAPT_ASSERT_TRUE(enumAttr->symbols[1].symbol.name);
-    EXPECT_EQ(enumAttr->symbols[1].symbol.name.value().entry, u"bat");
+    EXPECT_EQ(enumAttr->symbols[1].symbol.name.value().entry, "bat");
     EXPECT_EQ(enumAttr->symbols[1].value, 1u);
 
     AAPT_ASSERT_TRUE(enumAttr->symbols[2].symbol.name);
-    EXPECT_EQ(enumAttr->symbols[2].symbol.name.value().entry, u"baz");
+    EXPECT_EQ(enumAttr->symbols[2].symbol.name.value().entry, "baz");
     EXPECT_EQ(enumAttr->symbols[2].value, 2u);
 }
 
@@ -236,25 +235,25 @@
                         "</attr>";
     ASSERT_TRUE(testParse(input));
 
-    Attribute* flagAttr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+    Attribute* flagAttr = test::getValue<Attribute>(&mTable, "@attr/foo");
     ASSERT_NE(nullptr, flagAttr);
     EXPECT_EQ(flagAttr->typeMask, android::ResTable_map::TYPE_FLAGS);
     ASSERT_EQ(flagAttr->symbols.size(), 3u);
 
     AAPT_ASSERT_TRUE(flagAttr->symbols[0].symbol.name);
-    EXPECT_EQ(flagAttr->symbols[0].symbol.name.value().entry, u"bar");
+    EXPECT_EQ(flagAttr->symbols[0].symbol.name.value().entry, "bar");
     EXPECT_EQ(flagAttr->symbols[0].value, 0u);
 
     AAPT_ASSERT_TRUE(flagAttr->symbols[1].symbol.name);
-    EXPECT_EQ(flagAttr->symbols[1].symbol.name.value().entry, u"bat");
+    EXPECT_EQ(flagAttr->symbols[1].symbol.name.value().entry, "bat");
     EXPECT_EQ(flagAttr->symbols[1].value, 1u);
 
     AAPT_ASSERT_TRUE(flagAttr->symbols[2].symbol.name);
-    EXPECT_EQ(flagAttr->symbols[2].symbol.name.value().entry, u"baz");
+    EXPECT_EQ(flagAttr->symbols[2].symbol.name.value().entry, "baz");
     EXPECT_EQ(flagAttr->symbols[2].value, 2u);
 
     std::unique_ptr<BinaryPrimitive> flagValue = ResourceUtils::tryParseFlagSymbol(flagAttr,
-                                                                                   u"baz|bat");
+                                                                                   "baz|bat");
     ASSERT_NE(nullptr, flagValue);
     EXPECT_EQ(flagValue->value.data, 1u | 2u);
 }
@@ -276,32 +275,32 @@
                         "</style>";
     ASSERT_TRUE(testParse(input));
 
-    Style* style = test::getValue<Style>(&mTable, u"@style/foo");
+    Style* style = test::getValue<Style>(&mTable, "@style/foo");
     ASSERT_NE(nullptr, style);
     AAPT_ASSERT_TRUE(style->parent);
     AAPT_ASSERT_TRUE(style->parent.value().name);
-    EXPECT_EQ(test::parseNameOrDie(u"@style/fu"), style->parent.value().name.value());
+    EXPECT_EQ(test::parseNameOrDie("@style/fu"), style->parent.value().name.value());
     ASSERT_EQ(3u, style->entries.size());
 
     AAPT_ASSERT_TRUE(style->entries[0].key.name);
-    EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), style->entries[0].key.name.value());
+    EXPECT_EQ(test::parseNameOrDie("@attr/bar"), style->entries[0].key.name.value());
 
     AAPT_ASSERT_TRUE(style->entries[1].key.name);
-    EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), style->entries[1].key.name.value());
+    EXPECT_EQ(test::parseNameOrDie("@attr/bat"), style->entries[1].key.name.value());
 
     AAPT_ASSERT_TRUE(style->entries[2].key.name);
-    EXPECT_EQ(test::parseNameOrDie(u"@attr/baz"), style->entries[2].key.name.value());
+    EXPECT_EQ(test::parseNameOrDie("@attr/baz"), style->entries[2].key.name.value());
 }
 
 TEST_F(ResourceParserTest, ParseStyleWithShorthandParent) {
     std::string input = "<style name=\"foo\" parent=\"com.app:Theme\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Style* style = test::getValue<Style>(&mTable, u"@style/foo");
+    Style* style = test::getValue<Style>(&mTable, "@style/foo");
     ASSERT_NE(nullptr, style);
     AAPT_ASSERT_TRUE(style->parent);
     AAPT_ASSERT_TRUE(style->parent.value().name);
-    EXPECT_EQ(test::parseNameOrDie(u"@com.app:style/Theme"), style->parent.value().name.value());
+    EXPECT_EQ(test::parseNameOrDie("@com.app:style/Theme"), style->parent.value().name.value());
 }
 
 TEST_F(ResourceParserTest, ParseStyleWithPackageAliasedParent) {
@@ -309,11 +308,11 @@
                         "       name=\"foo\" parent=\"app:Theme\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Style* style = test::getValue<Style>(&mTable, u"@style/foo");
+    Style* style = test::getValue<Style>(&mTable, "@style/foo");
     ASSERT_NE(nullptr, style);
     AAPT_ASSERT_TRUE(style->parent);
     AAPT_ASSERT_TRUE(style->parent.value().name);
-    EXPECT_EQ(test::parseNameOrDie(u"@android:style/Theme"), style->parent.value().name.value());
+    EXPECT_EQ(test::parseNameOrDie("@android:style/Theme"), style->parent.value().name.value());
 }
 
 TEST_F(ResourceParserTest, ParseStyleWithPackageAliasedItems) {
@@ -323,21 +322,21 @@
             "</style>";
     ASSERT_TRUE(testParse(input));
 
-    Style* style = test::getValue<Style>(&mTable, u"@style/foo");
+    Style* style = test::getValue<Style>(&mTable, "@style/foo");
     ASSERT_NE(nullptr, style);
     ASSERT_EQ(1u, style->entries.size());
-    EXPECT_EQ(test::parseNameOrDie(u"@android:attr/bar"), style->entries[0].key.name.value());
+    EXPECT_EQ(test::parseNameOrDie("@android:attr/bar"), style->entries[0].key.name.value());
 }
 
 TEST_F(ResourceParserTest, ParseStyleWithInferredParent) {
     std::string input = "<style name=\"foo.bar\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar");
+    Style* style = test::getValue<Style>(&mTable, "@style/foo.bar");
     ASSERT_NE(nullptr, style);
     AAPT_ASSERT_TRUE(style->parent);
     AAPT_ASSERT_TRUE(style->parent.value().name);
-    EXPECT_EQ(style->parent.value().name.value(), test::parseNameOrDie(u"@style/foo"));
+    EXPECT_EQ(style->parent.value().name.value(), test::parseNameOrDie("@style/foo"));
     EXPECT_TRUE(style->parentInferred);
 }
 
@@ -345,7 +344,7 @@
     std::string input = "<style name=\"foo.bar\" parent=\"\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Style* style = test::getValue<Style>(&mTable, u"@style/foo.bar");
+    Style* style = test::getValue<Style>(&mTable, "@style/foo.bar");
     ASSERT_NE(nullptr, style);
     AAPT_EXPECT_FALSE(style->parent);
     EXPECT_FALSE(style->parentInferred);
@@ -355,7 +354,7 @@
     std::string input = R"EOF(<style name="foo" parent="*android:style/bar" />)EOF";
     ASSERT_TRUE(testParse(input));
 
-    Style* style = test::getValue<Style>(&mTable, u"@style/foo");
+    Style* style = test::getValue<Style>(&mTable, "@style/foo");
     ASSERT_NE(nullptr, style);
     AAPT_ASSERT_TRUE(style->parent);
     EXPECT_TRUE(style->parent.value().privateReference);
@@ -365,7 +364,7 @@
     std::string input = "<string name=\"foo\">@+id/bar</string>";
     ASSERT_TRUE(testParse(input));
 
-    Id* id = test::getValue<Id>(&mTable, u"@id/bar");
+    Id* id = test::getValue<Id>(&mTable, "@id/bar");
     ASSERT_NE(id, nullptr);
 }
 
@@ -380,31 +379,31 @@
     ASSERT_TRUE(testParse(input));
 
     Maybe<ResourceTable::SearchResult> result =
-            mTable.findResource(test::parseNameOrDie(u"@styleable/foo"));
+            mTable.findResource(test::parseNameOrDie("@styleable/foo"));
     AAPT_ASSERT_TRUE(result);
     EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbolStatus.state);
 
-    Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/bar");
+    Attribute* attr = test::getValue<Attribute>(&mTable, "@attr/bar");
     ASSERT_NE(attr, nullptr);
     EXPECT_TRUE(attr->isWeak());
 
-    attr = test::getValue<Attribute>(&mTable, u"@attr/bat");
+    attr = test::getValue<Attribute>(&mTable, "@attr/bat");
     ASSERT_NE(attr, nullptr);
     EXPECT_TRUE(attr->isWeak());
 
-    attr = test::getValue<Attribute>(&mTable, u"@attr/baz");
+    attr = test::getValue<Attribute>(&mTable, "@attr/baz");
     ASSERT_NE(attr, nullptr);
     EXPECT_TRUE(attr->isWeak());
     EXPECT_EQ(1u, attr->symbols.size());
 
-    EXPECT_NE(nullptr, test::getValue<Id>(&mTable, u"@id/foo"));
+    EXPECT_NE(nullptr, test::getValue<Id>(&mTable, "@id/foo"));
 
-    Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo");
+    Styleable* styleable = test::getValue<Styleable>(&mTable, "@styleable/foo");
     ASSERT_NE(styleable, nullptr);
     ASSERT_EQ(3u, styleable->entries.size());
 
-    EXPECT_EQ(test::parseNameOrDie(u"@attr/bar"), styleable->entries[0].name.value());
-    EXPECT_EQ(test::parseNameOrDie(u"@attr/bat"), styleable->entries[1].name.value());
+    EXPECT_EQ(test::parseNameOrDie("@attr/bar"), styleable->entries[0].name.value());
+    EXPECT_EQ(test::parseNameOrDie("@attr/bat"), styleable->entries[1].name.value());
 }
 
 TEST_F(ResourceParserTest, ParsePrivateAttributesDeclareStyleable) {
@@ -413,17 +412,17 @@
                         "  <attr name=\"privAndroid:bat\" />\n"
                         "</declare-styleable>";
     ASSERT_TRUE(testParse(input));
-    Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo");
+    Styleable* styleable = test::getValue<Styleable>(&mTable, "@styleable/foo");
     ASSERT_NE(nullptr, styleable);
     ASSERT_EQ(2u, styleable->entries.size());
 
     EXPECT_TRUE(styleable->entries[0].privateReference);
     AAPT_ASSERT_TRUE(styleable->entries[0].name);
-    EXPECT_EQ(std::u16string(u"android"), styleable->entries[0].name.value().package);
+    EXPECT_EQ(std::string("android"), styleable->entries[0].name.value().package);
 
     EXPECT_TRUE(styleable->entries[1].privateReference);
     AAPT_ASSERT_TRUE(styleable->entries[1].name);
-    EXPECT_EQ(std::u16string(u"android"), styleable->entries[1].name.value().package);
+    EXPECT_EQ(std::string("android"), styleable->entries[1].name.value().package);
 }
 
 TEST_F(ResourceParserTest, ParseArray) {
@@ -434,7 +433,7 @@
                         "</array>";
     ASSERT_TRUE(testParse(input));
 
-    Array* array = test::getValue<Array>(&mTable, u"@array/foo");
+    Array* array = test::getValue<Array>(&mTable, "@array/foo");
     ASSERT_NE(array, nullptr);
     ASSERT_EQ(3u, array->items.size());
 
@@ -448,7 +447,7 @@
                         "  <item>\"Werk\"</item>\n"
                         "</string-array>\n";
     ASSERT_TRUE(testParse(input));
-    EXPECT_NE(nullptr, test::getValue<Array>(&mTable, u"@array/foo"));
+    EXPECT_NE(nullptr, test::getValue<Array>(&mTable, "@array/foo"));
 }
 
 TEST_F(ResourceParserTest, ParsePlural) {
@@ -464,9 +463,9 @@
                         "<string name=\"foo\">Hi</string>";
     ASSERT_TRUE(testParse(input));
 
-    String* value = test::getValue<String>(&mTable, u"@string/foo");
+    String* value = test::getValue<String>(&mTable, "@string/foo");
     ASSERT_NE(nullptr, value);
-    EXPECT_EQ(value->getComment(), u"This is a comment");
+    EXPECT_EQ(value->getComment(), "This is a comment");
 }
 
 TEST_F(ResourceParserTest, DoNotCombineMultipleComments) {
@@ -476,9 +475,9 @@
 
     ASSERT_TRUE(testParse(input));
 
-    String* value = test::getValue<String>(&mTable, u"@string/foo");
+    String* value = test::getValue<String>(&mTable, "@string/foo");
     ASSERT_NE(nullptr, value);
-    EXPECT_EQ(value->getComment(), u"Two");
+    EXPECT_EQ(value->getComment(), "Two");
 }
 
 TEST_F(ResourceParserTest, IgnoreCommentBeforeEndTag) {
@@ -490,9 +489,9 @@
 
     ASSERT_TRUE(testParse(input));
 
-    String* value = test::getValue<String>(&mTable, u"@string/foo");
+    String* value = test::getValue<String>(&mTable, "@string/foo");
     ASSERT_NE(nullptr, value);
-    EXPECT_EQ(value->getComment(), u"One");
+    EXPECT_EQ(value->getComment(), "One");
 }
 
 TEST_F(ResourceParserTest, ParseNestedComments) {
@@ -510,17 +509,17 @@
         </attr>)EOF";
     ASSERT_TRUE(testParse(input));
 
-    Styleable* styleable = test::getValue<Styleable>(&mTable, u"@styleable/foo");
+    Styleable* styleable = test::getValue<Styleable>(&mTable, "@styleable/foo");
     ASSERT_NE(nullptr, styleable);
     ASSERT_EQ(1u, styleable->entries.size());
 
-    EXPECT_EQ(StringPiece16(u"The name of the bar"), styleable->entries.front().getComment());
+    EXPECT_EQ(StringPiece("The name of the bar"), styleable->entries.front().getComment());
 
-    Attribute* attr = test::getValue<Attribute>(&mTable, u"@attr/foo");
+    Attribute* attr = test::getValue<Attribute>(&mTable, "@attr/foo");
     ASSERT_NE(nullptr, attr);
     ASSERT_EQ(1u, attr->symbols.size());
 
-    EXPECT_EQ(StringPiece16(u"The very first"), attr->symbols.front().symbol.getComment());
+    EXPECT_EQ(StringPiece("The very first"), attr->symbols.front().symbol.getComment());
 }
 
 /*
@@ -531,7 +530,7 @@
     std::string input = "<public type=\"id\" name=\"foo\"/>";
     ASSERT_TRUE(testParse(input));
 
-    Id* id = test::getValue<Id>(&mTable, u"@id/foo");
+    Id* id = test::getValue<Id>(&mTable, "@id/foo");
     ASSERT_NE(nullptr, id);
 }
 
@@ -546,22 +545,22 @@
     )EOF";
     ASSERT_TRUE(testParse(input));
 
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/foo",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, "@string/foo",
                                                                  ConfigDescription::defaultConfig(),
                                                                  "phone"));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/foo",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, "@string/foo",
                                                                  ConfigDescription::defaultConfig(),
                                                                  "no-sdcard"));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bar",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, "@string/bar",
                                                                  ConfigDescription::defaultConfig(),
                                                                  ""));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/baz",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, "@string/baz",
                                                                  ConfigDescription::defaultConfig(),
                                                                  ""));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bit",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, "@string/bit",
                                                                  ConfigDescription::defaultConfig(),
                                                                  "phablet"));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, u"@string/bot",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<String>(&mTable, "@string/bot",
                                                                  ConfigDescription::defaultConfig(),
                                                                  "default"));
 }
@@ -575,7 +574,7 @@
     ASSERT_TRUE(testParse(input));
 
     Maybe<ResourceTable::SearchResult> result = mTable.findResource(
-            test::parseNameOrDie(u"@attr/foo"));
+            test::parseNameOrDie("@attr/foo"));
     AAPT_ASSERT_TRUE(result);
 
     AAPT_ASSERT_TRUE(result.value().package->id);
@@ -586,7 +585,7 @@
                         result.value().entry->id.value());
     EXPECT_EQ(ResourceId(0x01010040), actualId);
 
-    result = mTable.findResource(test::parseNameOrDie(u"@attr/bar"));
+    result = mTable.findResource(test::parseNameOrDie("@attr/bar"));
     AAPT_ASSERT_TRUE(result);
 
     AAPT_ASSERT_TRUE(result.value().package->id);
@@ -611,7 +610,7 @@
     ASSERT_TRUE(testParse(input));
 
     Maybe<ResourceTable::SearchResult> result = mTable.findResource(
-            test::parseNameOrDie(u"@string/bar"));
+            test::parseNameOrDie("@string/bar"));
     AAPT_ASSERT_TRUE(result);
     const ResourceEntry* entry = result.value().entry;
     ASSERT_NE(nullptr, entry);
@@ -622,7 +621,7 @@
     std::string input = R"EOF(<item name="foo" type="integer" format="float">0.3</item>)EOF";
     ASSERT_TRUE(testParse(input));
 
-    BinaryPrimitive* val = test::getValue<BinaryPrimitive>(&mTable, u"@integer/foo");
+    BinaryPrimitive* val = test::getValue<BinaryPrimitive>(&mTable, "@integer/foo");
     ASSERT_NE(nullptr, val);
 
     EXPECT_EQ(uint32_t(android::Res_value::TYPE_FLOAT), val->value.dataType);
diff --git a/tools/aapt2/ResourceTable.cpp b/tools/aapt2/ResourceTable.cpp
index e700ed9..4d418d9 100644
--- a/tools/aapt2/ResourceTable.cpp
+++ b/tools/aapt2/ResourceTable.cpp
@@ -35,11 +35,11 @@
 
 template <typename T>
 static bool lessThanStructWithName(const std::unique_ptr<T>& lhs,
-                                   const StringPiece16& rhs) {
+                                   const StringPiece& rhs) {
     return lhs->name.compare(0, lhs->name.size(), rhs.data(), rhs.size()) < 0;
 }
 
-ResourceTablePackage* ResourceTable::findPackage(const StringPiece16& name) {
+ResourceTablePackage* ResourceTable::findPackage(const StringPiece& name) {
     const auto last = packages.end();
     auto iter = std::lower_bound(packages.begin(), last, name,
                                  lessThanStructWithName<ResourceTablePackage>);
@@ -58,7 +58,7 @@
     return nullptr;
 }
 
-ResourceTablePackage* ResourceTable::createPackage(const StringPiece16& name, Maybe<uint8_t> id) {
+ResourceTablePackage* ResourceTable::createPackage(const StringPiece& name, Maybe<uint8_t> id) {
     ResourceTablePackage* package = findOrCreatePackage(name);
     if (id && !package->id) {
         package->id = id;
@@ -71,7 +71,7 @@
     return package;
 }
 
-ResourceTablePackage* ResourceTable::findOrCreatePackage(const StringPiece16& name) {
+ResourceTablePackage* ResourceTable::findOrCreatePackage(const StringPiece& name) {
     const auto last = packages.end();
     auto iter = std::lower_bound(packages.begin(), last, name,
                                  lessThanStructWithName<ResourceTablePackage>);
@@ -102,7 +102,7 @@
     return types.emplace(iter, new ResourceTableType(type))->get();
 }
 
-ResourceEntry* ResourceTableType::findEntry(const StringPiece16& name) {
+ResourceEntry* ResourceTableType::findEntry(const StringPiece& name) {
     const auto last = entries.end();
     auto iter = std::lower_bound(entries.begin(), last, name,
                                  lessThanStructWithName<ResourceEntry>);
@@ -112,7 +112,7 @@
     return nullptr;
 }
 
-ResourceEntry* ResourceTableType::findOrCreateEntry(const StringPiece16& name) {
+ResourceEntry* ResourceTableType::findOrCreateEntry(const StringPiece& name) {
     auto last = entries.end();
     auto iter = std::lower_bound(entries.begin(), last, name,
                                  lessThanStructWithName<ResourceEntry>);
@@ -261,8 +261,8 @@
     return 0;
 }
 
-static constexpr const char16_t* kValidNameChars = u"._-";
-static constexpr const char16_t* kValidNameMangledChars = u"._-$";
+static constexpr const char* kValidNameChars = "._-";
+static constexpr const char* kValidNameMangledChars = "._-$";
 
 bool ResourceTable::addResource(const ResourceNameRef& name,
                                 const ConfigDescription& config,
@@ -286,7 +286,7 @@
 bool ResourceTable::addFileReference(const ResourceNameRef& name,
                                      const ConfigDescription& config,
                                      const Source& source,
-                                     const StringPiece16& path,
+                                     const StringPiece& path,
                                      IDiagnostics* diag) {
     return addFileReferenceImpl(name, config, source, path, nullptr, kValidNameChars, diag);
 }
@@ -294,7 +294,7 @@
 bool ResourceTable::addFileReferenceAllowMangled(const ResourceNameRef& name,
                                                  const ConfigDescription& config,
                                                  const Source& source,
-                                                 const StringPiece16& path,
+                                                 const StringPiece& path,
                                                  io::IFile* file,
                                                  IDiagnostics* diag) {
     return addFileReferenceImpl(name, config, source, path, file, kValidNameMangledChars, diag);
@@ -303,9 +303,9 @@
 bool ResourceTable::addFileReferenceImpl(const ResourceNameRef& name,
                                          const ConfigDescription& config,
                                          const Source& source,
-                                         const StringPiece16& path,
+                                         const StringPiece& path,
                                          io::IFile* file,
-                                         const char16_t* validChars,
+                                         const char* validChars,
                                          IDiagnostics* diag) {
     std::unique_ptr<FileReference> fileRef = util::make_unique<FileReference>(
             stringPool.makeRef(path));
@@ -339,7 +339,7 @@
                                     const ConfigDescription& config,
                                     const StringPiece& product,
                                     std::unique_ptr<Value> value,
-                                    const char16_t* validChars,
+                                    const char* validChars,
                                     std::function<int(Value*,Value*)> conflictResolver,
                                     IDiagnostics* diag) {
     assert(value && "value can't be nullptr");
@@ -353,7 +353,7 @@
                     << "' has invalid entry name '"
                     << name.entry
                     << "'. Invalid character '"
-                    << StringPiece16(badCharIter, 1)
+                    << StringPiece(badCharIter, 1)
                     << "'");
         return false;
     }
@@ -438,7 +438,7 @@
 }
 
 bool ResourceTable::setSymbolStateImpl(const ResourceNameRef& name, const ResourceId resId,
-                                       const Symbol& symbol, const char16_t* validChars,
+                                       const Symbol& symbol, const char* validChars,
                                        IDiagnostics* diag) {
     assert(diag && "diagnostics can't be nullptr");
 
@@ -450,7 +450,7 @@
                     << "' has invalid entry name '"
                     << name.entry
                     << "'. Invalid character '"
-                    << StringPiece16(badCharIter, 1)
+                    << StringPiece(badCharIter, 1)
                     << "'");
         return false;
     }
diff --git a/tools/aapt2/ResourceTable.h b/tools/aapt2/ResourceTable.h
index 5690ea6..a5efe35 100644
--- a/tools/aapt2/ResourceTable.h
+++ b/tools/aapt2/ResourceTable.h
@@ -48,7 +48,7 @@
 struct Symbol {
     SymbolState state = SymbolState::kUndefined;
     Source source;
-    std::u16string comment;
+    std::string comment;
 };
 
 class ResourceConfigValue {
@@ -86,7 +86,7 @@
      * this determines the order of this resource
      * when doing lookups.
      */
-    const std::u16string name;
+    const std::string name;
 
     /**
      * The entry ID for this resource.
@@ -103,7 +103,7 @@
      */
     std::vector<std::unique_ptr<ResourceConfigValue>> values;
 
-    ResourceEntry(const StringPiece16& name) : name(name.toString()) { }
+    ResourceEntry(const StringPiece& name) : name(name.toString()) { }
 
     ResourceConfigValue* findValue(const ConfigDescription& config);
     ResourceConfigValue* findValue(const ConfigDescription& config, const StringPiece& product);
@@ -147,8 +147,8 @@
 
     explicit ResourceTableType(const ResourceType type) : type(type) { }
 
-    ResourceEntry* findEntry(const StringPiece16& name);
-    ResourceEntry* findOrCreateEntry(const StringPiece16& name);
+    ResourceEntry* findEntry(const StringPiece& name);
+    ResourceEntry* findOrCreateEntry(const StringPiece& name);
 
 private:
     DISALLOW_COPY_AND_ASSIGN(ResourceTableType);
@@ -165,7 +165,7 @@
 public:
     PackageType type = PackageType::App;
     Maybe<uint8_t> id;
-    std::u16string name;
+    std::string name;
 
     std::vector<std::unique_ptr<ResourceTableType>> types;
 
@@ -209,13 +209,13 @@
     bool addFileReference(const ResourceNameRef& name,
                               const ConfigDescription& config,
                               const Source& source,
-                              const StringPiece16& path,
+                              const StringPiece& path,
                               IDiagnostics* diag);
 
     bool addFileReferenceAllowMangled(const ResourceNameRef& name,
                                       const ConfigDescription& config,
                                       const Source& source,
-                                      const StringPiece16& path,
+                                      const StringPiece& path,
                                       io::IFile* file,
                                       IDiagnostics* diag);
 
@@ -276,21 +276,21 @@
      * exist. The empty string is a valid package and typically is used to represent the
      * 'current' package before it is known to the ResourceTable.
      */
-    ResourceTablePackage* findPackage(const StringPiece16& name);
+    ResourceTablePackage* findPackage(const StringPiece& name);
 
     ResourceTablePackage* findPackageById(uint8_t id);
 
-    ResourceTablePackage* createPackage(const StringPiece16& name, Maybe<uint8_t> id = {});
+    ResourceTablePackage* createPackage(const StringPiece& name, Maybe<uint8_t> id = {});
 
 private:
-    ResourceTablePackage* findOrCreatePackage(const StringPiece16& name);
+    ResourceTablePackage* findOrCreatePackage(const StringPiece& name);
 
     bool addFileReferenceImpl(const ResourceNameRef& name,
                               const ConfigDescription& config,
                               const Source& source,
-                              const StringPiece16& path,
+                              const StringPiece& path,
                               io::IFile* file,
-                              const char16_t* validChars,
+                              const char* validChars,
                               IDiagnostics* diag);
 
     bool addResourceImpl(const ResourceNameRef& name,
@@ -298,14 +298,14 @@
                          const ConfigDescription& config,
                          const StringPiece& product,
                          std::unique_ptr<Value> value,
-                         const char16_t* validChars,
+                         const char* validChars,
                          std::function<int(Value*,Value*)> conflictResolver,
                          IDiagnostics* diag);
 
     bool setSymbolStateImpl(const ResourceNameRef& name,
                             ResourceId resId,
                             const Symbol& symbol,
-                            const char16_t* validChars,
+                            const char* validChars,
                             IDiagnostics* diag);
 
     DISALLOW_COPY_AND_ASSIGN(ResourceTable);
diff --git a/tools/aapt2/ResourceTable_test.cpp b/tools/aapt2/ResourceTable_test.cpp
index d6c52ab..cf6660c 100644
--- a/tools/aapt2/ResourceTable_test.cpp
+++ b/tools/aapt2/ResourceTable_test.cpp
@@ -17,12 +17,10 @@
 #include "Diagnostics.h"
 #include "ResourceTable.h"
 #include "ResourceValues.h"
+#include "test/Test.h"
 #include "util/Util.h"
 
-#include "test/Builders.h"
-
 #include <algorithm>
-#include <gtest/gtest.h>
 #include <ostream>
 #include <string>
 
@@ -32,13 +30,13 @@
     ResourceTable table;
 
     EXPECT_FALSE(table.addResource(
-            ResourceNameRef(u"android", ResourceType::kId, u"hey,there"),
+            test::parseNameOrDie("@android:id/hey,there"),
             ConfigDescription{}, "",
             test::ValueBuilder<Id>().setSource("test.xml", 21u).build(),
             test::getDiagnostics()));
 
     EXPECT_FALSE(table.addResource(
-            ResourceNameRef(u"android", ResourceType::kId, u"hey:there"),
+            test::parseNameOrDie("@android:id/hey:there"),
             ConfigDescription{}, "",
             test::ValueBuilder<Id>().setSource("test.xml", 21u).build(),
             test::getDiagnostics()));
@@ -47,14 +45,13 @@
 TEST(ResourceTableTest, AddOneResource) {
     ResourceTable table;
 
-    EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/id"),
-                                  ConfigDescription{},
-                                  "",
-                                  test::ValueBuilder<Id>()
-                                          .setSource("test/path/file.xml", 23u).build(),
-                                  test::getDiagnostics()));
+    EXPECT_TRUE(table.addResource(
+            test::parseNameOrDie("@android:attr/id"),
+            ConfigDescription{}, "",
+            test::ValueBuilder<Id>().setSource("test/path/file.xml", 23u).build(),
+            test::getDiagnostics()));
 
-    ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id"));
+    ASSERT_NE(nullptr, test::getValue<Id>(&table, "@android:attr/id"));
 }
 
 TEST(ResourceTableTest, AddMultipleResources) {
@@ -65,56 +62,58 @@
     memcpy(languageConfig.language, "pl", sizeof(languageConfig.language));
 
     EXPECT_TRUE(table.addResource(
-            test::parseNameOrDie(u"@android:attr/layout_width"),
-            config,
-            "",
+            test::parseNameOrDie("@android:attr/layout_width"),
+            config, "",
             test::ValueBuilder<Id>().setSource("test/path/file.xml", 10u).build(),
             test::getDiagnostics()));
 
     EXPECT_TRUE(table.addResource(
-            test::parseNameOrDie(u"@android:attr/id"),
-            config,
-            "",
+            test::parseNameOrDie("@android:attr/id"),
+            config, "",
             test::ValueBuilder<Id>().setSource("test/path/file.xml", 12u).build(),
             test::getDiagnostics()));
 
     EXPECT_TRUE(table.addResource(
-            test::parseNameOrDie(u"@android:string/ok"),
-            config,
-            "",
+            test::parseNameOrDie("@android:string/ok"),
+            config, "",
             test::ValueBuilder<Id>().setSource("test/path/file.xml", 14u).build(),
             test::getDiagnostics()));
 
     EXPECT_TRUE(table.addResource(
-            test::parseNameOrDie(u"@android:string/ok"),
-            languageConfig,
-            "",
+            test::parseNameOrDie("@android:string/ok"),
+            languageConfig, "",
             test::ValueBuilder<BinaryPrimitive>(android::Res_value{})
                     .setSource("test/path/file.xml", 20u)
                     .build(),
             test::getDiagnostics()));
 
-    ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/layout_width"));
-    ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:attr/id"));
-    ASSERT_NE(nullptr, test::getValue<Id>(&table, u"@android:string/ok"));
-    ASSERT_NE(nullptr, test::getValueForConfig<BinaryPrimitive>(&table, u"@android:string/ok",
+    ASSERT_NE(nullptr, test::getValue<Id>(&table, "@android:attr/layout_width"));
+    ASSERT_NE(nullptr, test::getValue<Id>(&table, "@android:attr/id"));
+    ASSERT_NE(nullptr, test::getValue<Id>(&table, "@android:string/ok"));
+    ASSERT_NE(nullptr, test::getValueForConfig<BinaryPrimitive>(&table, "@android:string/ok",
                                                                 languageConfig));
 }
 
 TEST(ResourceTableTest, OverrideWeakResourceValue) {
     ResourceTable table;
 
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{},
-                                  "", util::make_unique<Attribute>(true), test::getDiagnostics()));
+    ASSERT_TRUE(table.addResource(
+            test::parseNameOrDie("@android:attr/foo"),
+            ConfigDescription{}, "",
+            util::make_unique<Attribute>(true),
+            test::getDiagnostics()));
 
-    Attribute* attr = test::getValue<Attribute>(&table, u"@android:attr/foo");
+    Attribute* attr = test::getValue<Attribute>(&table, "@android:attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_TRUE(attr->isWeak());
 
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:attr/foo"), ConfigDescription{},
-                                  "", util::make_unique<Attribute>(false), test::getDiagnostics()));
+    ASSERT_TRUE(table.addResource(
+            test::parseNameOrDie("@android:attr/foo"),
+            ConfigDescription{}, "",
+            util::make_unique<Attribute>(false),
+            test::getDiagnostics()));
 
-    attr = test::getValue<Attribute>(&table, u"@android:attr/foo");
+    attr = test::getValue<Attribute>(&table, "@android:attr/foo");
     ASSERT_NE(nullptr, attr);
     EXPECT_FALSE(attr->isWeak());
 }
@@ -122,26 +121,24 @@
 TEST(ResourceTableTest, ProductVaryingValues) {
     ResourceTable table;
 
-    EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"),
-                                  test::parseConfigOrDie("land"),
-                                  "tablet",
+    EXPECT_TRUE(table.addResource(test::parseNameOrDie("@android:string/foo"),
+                                  test::parseConfigOrDie("land"), "tablet",
                                   util::make_unique<Id>(),
                                   test::getDiagnostics()));
-    EXPECT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/foo"),
-                                  test::parseConfigOrDie("land"),
-                                  "phone",
+    EXPECT_TRUE(table.addResource(test::parseNameOrDie("@android:string/foo"),
+                                  test::parseConfigOrDie("land"), "phone",
                                   util::make_unique<Id>(),
                                   test::getDiagnostics()));
 
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/foo",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/foo",
                                                              test::parseConfigOrDie("land"),
                                                              "tablet"));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/foo",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/foo",
                                                              test::parseConfigOrDie("land"),
                                                              "phone"));
 
     Maybe<ResourceTable::SearchResult> sr = table.findResource(
-            test::parseNameOrDie(u"@android:string/foo"));
+            test::parseNameOrDie("@android:string/foo"));
     AAPT_ASSERT_TRUE(sr);
     std::vector<ResourceConfigValue*> values = sr.value().entry->findAllValues(
             test::parseConfigOrDie("land"));
diff --git a/tools/aapt2/ResourceUtils.cpp b/tools/aapt2/ResourceUtils.cpp
index 302c04f..31d6435a6 100644
--- a/tools/aapt2/ResourceUtils.cpp
+++ b/tools/aapt2/ResourceUtils.cpp
@@ -27,19 +27,52 @@
 namespace aapt {
 namespace ResourceUtils {
 
-bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage,
-                         StringPiece16* outType, StringPiece16* outEntry) {
+Maybe<ResourceName> toResourceName(const android::ResTable::resource_name& nameIn) {
+    ResourceName nameOut;
+    if (!nameIn.package) {
+        return {};
+    }
+
+    nameOut.package = util::utf16ToUtf8(StringPiece16(nameIn.package, nameIn.packageLen));
+
+    const ResourceType* type;
+    if (nameIn.type) {
+        type = parseResourceType(util::utf16ToUtf8(StringPiece16(nameIn.type, nameIn.typeLen)));
+    } else if (nameIn.type8) {
+        type = parseResourceType(StringPiece(nameIn.type8, nameIn.typeLen));
+    } else {
+        return {};
+    }
+
+    if (!type) {
+        return {};
+    }
+
+    nameOut.type = *type;
+
+    if (nameIn.name) {
+        nameOut.entry = util::utf16ToUtf8(StringPiece16(nameIn.name, nameIn.nameLen));
+    } else if (nameIn.name8) {
+        nameOut.entry = StringPiece(nameIn.name8, nameIn.nameLen).toString();
+    } else {
+        return {};
+    }
+    return nameOut;
+}
+
+bool extractResourceName(const StringPiece& str, StringPiece* outPackage,
+                         StringPiece* outType, StringPiece* outEntry) {
     bool hasPackageSeparator = false;
     bool hasTypeSeparator = false;
-    const char16_t* start = str.data();
-    const char16_t* end = start + str.size();
-    const char16_t* current = start;
+    const char* start = str.data();
+    const char* end = start + str.size();
+    const char* current = start;
     while (current != end) {
-        if (outType->size() == 0 && *current == u'/') {
+        if (outType->size() == 0 && *current == '/') {
             hasTypeSeparator = true;
             outType->assign(start, current - start);
             start = current + 1;
-        } else if (outPackage->size() == 0 && *current == u':') {
+        } else if (outPackage->size() == 0 && *current == ':') {
             hasPackageSeparator = true;
             outPackage->assign(start, current - start);
             start = current + 1;
@@ -51,21 +84,21 @@
     return !(hasPackageSeparator && outPackage->empty()) && !(hasTypeSeparator && outType->empty());
 }
 
-bool parseResourceName(const StringPiece16& str, ResourceNameRef* outRef, bool* outPrivate) {
+bool parseResourceName(const StringPiece& str, ResourceNameRef* outRef, bool* outPrivate) {
     if (str.empty()) {
         return false;
     }
 
     size_t offset = 0;
     bool priv = false;
-    if (str.data()[0] == u'*') {
+    if (str.data()[0] == '*') {
         priv = true;
         offset = 1;
     }
 
-    StringPiece16 package;
-    StringPiece16 type;
-    StringPiece16 entry;
+    StringPiece package;
+    StringPiece type;
+    StringPiece entry;
     if (!extractResourceName(str.substr(offset, str.size() - offset), &package, &type, &entry)) {
         return false;
     }
@@ -91,18 +124,18 @@
     return true;
 }
 
-bool tryParseReference(const StringPiece16& str, ResourceNameRef* outRef, bool* outCreate,
+bool tryParseReference(const StringPiece& str, ResourceNameRef* outRef, bool* outCreate,
                        bool* outPrivate) {
-    StringPiece16 trimmedStr(util::trimWhitespace(str));
+    StringPiece trimmedStr(util::trimWhitespace(str));
     if (trimmedStr.empty()) {
         return false;
     }
 
     bool create = false;
     bool priv = false;
-    if (trimmedStr.data()[0] == u'@') {
+    if (trimmedStr.data()[0] == '@') {
         size_t offset = 1;
-        if (trimmedStr.data()[1] == u'+') {
+        if (trimmedStr.data()[1] == '+') {
             create = true;
             offset += 1;
         }
@@ -137,26 +170,26 @@
     return false;
 }
 
-bool isReference(const StringPiece16& str) {
+bool isReference(const StringPiece& str) {
     return tryParseReference(str, nullptr, nullptr, nullptr);
 }
 
-bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outRef) {
-    StringPiece16 trimmedStr(util::trimWhitespace(str));
+bool tryParseAttributeReference(const StringPiece& str, ResourceNameRef* outRef) {
+    StringPiece trimmedStr(util::trimWhitespace(str));
     if (trimmedStr.empty()) {
         return false;
     }
 
-    if (*trimmedStr.data() == u'?') {
-        StringPiece16 package;
-        StringPiece16 type;
-        StringPiece16 entry;
+    if (*trimmedStr.data() == '?') {
+        StringPiece package;
+        StringPiece type;
+        StringPiece entry;
         if (!extractResourceName(trimmedStr.substr(1, trimmedStr.size() - 1),
                                  &package, &type, &entry)) {
             return false;
         }
 
-        if (!type.empty() && type != u"attr") {
+        if (!type.empty() && type != "attr") {
             return false;
         }
 
@@ -174,7 +207,7 @@
     return false;
 }
 
-bool isAttributeReference(const StringPiece16& str) {
+bool isAttributeReference(const StringPiece& str) {
     return tryParseAttributeReference(str, nullptr);
 }
 
@@ -186,23 +219,23 @@
  * <[*]package>:[style/]<entry>
  * [[*]package:style/]<entry>
  */
-Maybe<Reference> parseStyleParentReference(const StringPiece16& str, std::string* outError) {
+Maybe<Reference> parseStyleParentReference(const StringPiece& str, std::string* outError) {
     if (str.empty()) {
         return {};
     }
 
-    StringPiece16 name = str;
+    StringPiece name = str;
 
     bool hasLeadingIdentifiers = false;
     bool privateRef = false;
 
     // Skip over these identifiers. A style's parent is a normal reference.
-    if (name.data()[0] == u'@' || name.data()[0] == u'?') {
+    if (name.data()[0] == '@' || name.data()[0] == '?') {
         hasLeadingIdentifiers = true;
         name = name.substr(1, name.size() - 1);
     }
 
-    if (name.data()[0] == u'*') {
+    if (name.data()[0] == '*') {
         privateRef = true;
         name = name.substr(1, name.size() - 1);
     }
@@ -210,7 +243,7 @@
     ResourceNameRef ref;
     ref.type = ResourceType::kStyle;
 
-    StringPiece16 typeStr;
+    StringPiece typeStr;
     extractResourceName(name, &ref.package, &typeStr, &ref.entry);
     if (!typeStr.empty()) {
         // If we have a type, make sure it is a Style.
@@ -235,7 +268,7 @@
     return result;
 }
 
-std::unique_ptr<Reference> tryParseReference(const StringPiece16& str, bool* outCreate) {
+std::unique_ptr<Reference> tryParseReference(const StringPiece& str, bool* outCreate) {
     ResourceNameRef ref;
     bool privateRef = false;
     if (tryParseReference(str, &ref, outCreate, &privateRef)) {
@@ -253,14 +286,14 @@
     return {};
 }
 
-std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece16& str) {
-    StringPiece16 trimmedStr(util::trimWhitespace(str));
+std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece& str) {
+    StringPiece trimmedStr(util::trimWhitespace(str));
     android::Res_value value = { };
-    if (trimmedStr == u"@null") {
+    if (trimmedStr == "@null") {
         // TYPE_NULL with data set to 0 is interpreted by the runtime as an error.
         // Instead we set the data type to TYPE_REFERENCE with a value of 0.
         value.dataType = android::Res_value::TYPE_REFERENCE;
-    } else if (trimmedStr == u"@empty") {
+    } else if (trimmedStr == "@empty") {
         // TYPE_NULL with value of DATA_NULL_EMPTY is handled fine by the runtime.
         value.dataType = android::Res_value::TYPE_NULL;
         value.data = android::Res_value::DATA_NULL_EMPTY;
@@ -271,8 +304,8 @@
 }
 
 std::unique_ptr<BinaryPrimitive> tryParseEnumSymbol(const Attribute* enumAttr,
-                                                    const StringPiece16& str) {
-    StringPiece16 trimmedStr(util::trimWhitespace(str));
+                                                    const StringPiece& str) {
+    StringPiece trimmedStr(util::trimWhitespace(str));
     for (const Attribute::Symbol& symbol : enumAttr->symbols) {
         // Enum symbols are stored as @package:id/symbol resources,
         // so we need to match against the 'entry' part of the identifier.
@@ -288,7 +321,7 @@
 }
 
 std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute* flagAttr,
-                                                    const StringPiece16& str) {
+                                                    const StringPiece& str) {
     android::Res_value flags = { };
     flags.dataType = android::Res_value::TYPE_INT_HEX;
     flags.data = 0u;
@@ -298,8 +331,8 @@
         return util::make_unique<BinaryPrimitive>(flags);
     }
 
-    for (StringPiece16 part : util::tokenize(str, u'|')) {
-        StringPiece16 trimmedPart = util::trimWhitespace(part);
+    for (StringPiece part : util::tokenize(str, '|')) {
+        StringPiece trimmedPart = util::trimWhitespace(part);
 
         bool flagSet = false;
         for (const Attribute::Symbol& symbol : flagAttr->symbols) {
@@ -320,24 +353,24 @@
     return util::make_unique<BinaryPrimitive>(flags);
 }
 
-static uint32_t parseHex(char16_t c, bool* outError) {
-    if (c >= u'0' && c <= u'9') {
-        return c - u'0';
-    } else if (c >= u'a' && c <= u'f') {
-        return c - u'a' + 0xa;
-    } else if (c >= u'A' && c <= u'F') {
-        return c - u'A' + 0xa;
+static uint32_t parseHex(char c, bool* outError) {
+    if (c >= '0' && c <= '9') {
+        return c - '0';
+    } else if (c >= 'a' && c <= 'f') {
+        return c - 'a' + 0xa;
+    } else if (c >= 'A' && c <= 'F') {
+        return c - 'A' + 0xa;
     } else {
         *outError = true;
         return 0xffffffffu;
     }
 }
 
-std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece16& str) {
-    StringPiece16 colorStr(util::trimWhitespace(str));
-    const char16_t* start = colorStr.data();
+std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece& str) {
+    StringPiece colorStr(util::trimWhitespace(str));
+    const char* start = colorStr.data();
     const size_t len = colorStr.size();
-    if (len == 0 || start[0] != u'#') {
+    if (len == 0 || start[0] != '#') {
         return {};
     }
 
@@ -387,14 +420,14 @@
     return error ? std::unique_ptr<BinaryPrimitive>() : util::make_unique<BinaryPrimitive>(value);
 }
 
-bool tryParseBool(const StringPiece16& str, bool* outValue) {
-    StringPiece16 trimmedStr(util::trimWhitespace(str));
-    if (trimmedStr == u"true" || trimmedStr == u"TRUE" || trimmedStr == u"True") {
+bool tryParseBool(const StringPiece& str, bool* outValue) {
+    StringPiece trimmedStr(util::trimWhitespace(str));
+    if (trimmedStr == "true" || trimmedStr == "TRUE" || trimmedStr == "True") {
         if (outValue) {
             *outValue = true;
         }
         return true;
-    } else if (trimmedStr == u"false" || trimmedStr == u"FALSE" || trimmedStr == u"False") {
+    } else if (trimmedStr == "false" || trimmedStr == "FALSE" || trimmedStr == "False") {
         if (outValue) {
             *outValue = false;
         }
@@ -403,22 +436,24 @@
     return false;
 }
 
-Maybe<int> tryParseSdkVersion(const StringPiece16& str) {
-    StringPiece16 trimmedStr(util::trimWhitespace(str));
+Maybe<int> tryParseSdkVersion(const StringPiece& str) {
+    StringPiece trimmedStr(util::trimWhitespace(str));
+
+    std::u16string str16 = util::utf8ToUtf16(trimmedStr);
     android::Res_value value;
-    if (android::ResTable::stringToInt(trimmedStr.data(), trimmedStr.size(), &value)) {
+    if (android::ResTable::stringToInt(str16.data(), str16.size(), &value)) {
         return static_cast<int>(value.data);
     }
 
     // Try parsing the code name.
-    std::pair<StringPiece16, int> entry = getDevelopmentSdkCodeNameAndVersion();
+    std::pair<StringPiece, int> entry = getDevelopmentSdkCodeNameAndVersion();
     if (entry.first == trimmedStr) {
         return entry.second;
     }
     return {};
 }
 
-std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece16& str) {
+std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece& str) {
     bool result = false;
     if (tryParseBool(str, &result)) {
         android::Res_value value = {};
@@ -434,17 +469,19 @@
     return {};
 }
 
-std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece16& str) {
+std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece& str) {
+    std::u16string str16 = util::utf8ToUtf16(str);
     android::Res_value value;
-    if (!android::ResTable::stringToInt(str.data(), str.size(), &value)) {
+    if (!android::ResTable::stringToInt(str16.data(), str16.size(), &value)) {
         return {};
     }
     return util::make_unique<BinaryPrimitive>(value);
 }
 
-std::unique_ptr<BinaryPrimitive> tryParseFloat(const StringPiece16& str) {
+std::unique_ptr<BinaryPrimitive> tryParseFloat(const StringPiece& str) {
+    std::u16string str16 = util::utf8ToUtf16(str);
     android::Res_value value;
-    if (!android::ResTable::stringToFloat(str.data(), str.size(), &value)) {
+    if (!android::ResTable::stringToFloat(str16.data(), str16.size(), &value)) {
         return {};
     }
     return util::make_unique<BinaryPrimitive>(value);
@@ -490,7 +527,8 @@
 }
 
 std::unique_ptr<Item> parseItemForAttribute(
-        const StringPiece16& value, uint32_t typeMask,
+        const StringPiece& value,
+        uint32_t typeMask,
         std::function<void(const ResourceName&)> onCreateReference) {
     std::unique_ptr<BinaryPrimitive> nullOrEmpty = tryParseNullOrEmpty(value);
     if (nullOrEmpty) {
@@ -549,7 +587,7 @@
  * allows.
  */
 std::unique_ptr<Item> parseItemForAttribute(
-        const StringPiece16& str, const Attribute* attr,
+        const StringPiece& str, const Attribute* attr,
         std::function<void(const ResourceName&)> onCreateReference) {
     const uint32_t typeMask = attr->typeMask;
     std::unique_ptr<Item> value = parseItemForAttribute(str, typeMask, onCreateReference);
diff --git a/tools/aapt2/ResourceUtils.h b/tools/aapt2/ResourceUtils.h
index 3a03caf..871ed7c 100644
--- a/tools/aapt2/ResourceUtils.h
+++ b/tools/aapt2/ResourceUtils.h
@@ -28,6 +28,11 @@
 namespace aapt {
 namespace ResourceUtils {
 
+/**
+ * Convert an android::ResTable::resource_name to an aapt::ResourceName struct.
+ */
+Maybe<ResourceName> toResourceName(const android::ResTable::resource_name& name);
+
 /*
  * Extracts the package, type, and name from a string of the format:
  *
@@ -37,15 +42,15 @@
  * individual extracted piece to verify that the pieces are valid.
  * Returns false if there was no package but a ':' was present.
  */
-bool extractResourceName(const StringPiece16& str, StringPiece16* outPackage,
-                         StringPiece16* outType, StringPiece16* outEntry);
+bool extractResourceName(const StringPiece& str, StringPiece* outPackage,
+                         StringPiece* outType, StringPiece* outEntry);
 
 /**
  * Returns true if the string was parsed as a resource name ([*][package:]type/name), with
  * `outResource` set to the parsed resource name and `outPrivate` set to true if a '*' prefix
  * was present.
  */
-bool parseResourceName(const StringPiece16& str, ResourceNameRef* outResource,
+bool parseResourceName(const StringPiece& str, ResourceNameRef* outResource,
                        bool* outPrivate = nullptr);
 
 /*
@@ -55,34 +60,34 @@
  * If '+' was present in the reference, `outCreate` is set to true.
  * If '*' was present in the reference, `outPrivate` is set to true.
  */
-bool tryParseReference(const StringPiece16& str, ResourceNameRef* outReference,
+bool tryParseReference(const StringPiece& str, ResourceNameRef* outReference,
                        bool* outCreate = nullptr, bool* outPrivate = nullptr);
 
 /*
  * Returns true if the string is in the form of a resource reference (@[+][package:]type/name).
  */
-bool isReference(const StringPiece16& str);
+bool isReference(const StringPiece& str);
 
 /*
  * Returns true if the string was parsed as an attribute reference (?[package:][type/]name),
  * with `outReference` set to the parsed reference.
  */
-bool tryParseAttributeReference(const StringPiece16& str, ResourceNameRef* outReference);
+bool tryParseAttributeReference(const StringPiece& str, ResourceNameRef* outReference);
 
 /**
  * Returns true if the string is in the form of an attribute reference(?[package:][type/]name).
  */
-bool isAttributeReference(const StringPiece16& str);
+bool isAttributeReference(const StringPiece& str);
 
 /**
  * Returns true if the value is a boolean, putting the result in `outValue`.
  */
-bool tryParseBool(const StringPiece16& str, bool* outValue);
+bool tryParseBool(const StringPiece& str, bool* outValue);
 
 /**
  * Parses an SDK version, which can be an integer, or a letter from A-Z.
  */
-Maybe<int> tryParseSdkVersion(const StringPiece16& str);
+Maybe<int> tryParseSdkVersion(const StringPiece& str);
 
 /*
  * Returns a Reference, or None Maybe instance if the string `str` was parsed as a
@@ -93,58 +98,58 @@
  * ?[package:]style/<entry> or
  * <package>:[style/]<entry>
  */
-Maybe<Reference> parseStyleParentReference(const StringPiece16& str, std::string* outError);
+Maybe<Reference> parseStyleParentReference(const StringPiece& str, std::string* outError);
 
 /*
  * Returns a Reference object if the string was parsed as a resource or attribute reference,
  * ( @[+][package:]type/name | ?[package:]type/name ) setting outCreate to true if
  * the '+' was present in the string.
  */
-std::unique_ptr<Reference> tryParseReference(const StringPiece16& str, bool* outCreate = nullptr);
+std::unique_ptr<Reference> tryParseReference(const StringPiece& str, bool* outCreate = nullptr);
 
 /*
  * Returns a BinaryPrimitve object representing @null or @empty if the string was parsed
  * as one.
  */
-std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece16& str);
+std::unique_ptr<BinaryPrimitive> tryParseNullOrEmpty(const StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a color if the string was parsed
  * as one.
  */
-std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece16& str);
+std::unique_ptr<BinaryPrimitive> tryParseColor(const StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a boolean if the string was parsed
  * as one.
  */
-std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece16& str);
+std::unique_ptr<BinaryPrimitive> tryParseBool(const StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing an integer if the string was parsed
  * as one.
  */
-std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece16& str);
+std::unique_ptr<BinaryPrimitive> tryParseInt(const StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a floating point number
  * (float, dimension, etc) if the string was parsed as one.
  */
-std::unique_ptr<BinaryPrimitive> tryParseFloat(const StringPiece16& str);
+std::unique_ptr<BinaryPrimitive> tryParseFloat(const StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing an enum symbol if the string was parsed
  * as one.
  */
 std::unique_ptr<BinaryPrimitive> tryParseEnumSymbol(const Attribute* enumAttr,
-                                                    const StringPiece16& str);
+                                                    const StringPiece& str);
 
 /*
  * Returns a BinaryPrimitve object representing a flag symbol if the string was parsed
  * as one.
  */
 std::unique_ptr<BinaryPrimitive> tryParseFlagSymbol(const Attribute* enumAttr,
-                                                    const StringPiece16& str);
+                                                    const StringPiece& str);
 /*
  * Try to convert a string to an Item for the given attribute. The attribute will
  * restrict what values the string can be converted to.
@@ -152,11 +157,11 @@
  * reference to an ID that must be created (@+id/foo).
  */
 std::unique_ptr<Item> parseItemForAttribute(
-        const StringPiece16& value, const Attribute* attr,
+        const StringPiece& value, const Attribute* attr,
         std::function<void(const ResourceName&)> onCreateReference = {});
 
 std::unique_ptr<Item> parseItemForAttribute(
-        const StringPiece16& value, uint32_t typeMask,
+        const StringPiece& value, uint32_t typeMask,
         std::function<void(const ResourceName&)> onCreateReference = {});
 
 uint32_t androidTypeToAttributeTypeMask(uint16_t type);
diff --git a/tools/aapt2/ResourceUtils_test.cpp b/tools/aapt2/ResourceUtils_test.cpp
index 7425f97..fb76914 100644
--- a/tools/aapt2/ResourceUtils_test.cpp
+++ b/tools/aapt2/ResourceUtils_test.cpp
@@ -16,69 +16,66 @@
 
 #include "Resource.h"
 #include "ResourceUtils.h"
-#include "test/Builders.h"
-#include "test/Common.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
 
 namespace aapt {
 
 TEST(ResourceUtilsTest, ParseBool) {
     bool val = false;
-    EXPECT_TRUE(ResourceUtils::tryParseBool(u"true", &val));
+    EXPECT_TRUE(ResourceUtils::tryParseBool("true", &val));
     EXPECT_TRUE(val);
 
-    EXPECT_TRUE(ResourceUtils::tryParseBool(u"TRUE", &val));
+    EXPECT_TRUE(ResourceUtils::tryParseBool("TRUE", &val));
     EXPECT_TRUE(val);
 
-    EXPECT_TRUE(ResourceUtils::tryParseBool(u"True", &val));
+    EXPECT_TRUE(ResourceUtils::tryParseBool("True", &val));
     EXPECT_TRUE(val);
 
-    EXPECT_TRUE(ResourceUtils::tryParseBool(u"false", &val));
+    EXPECT_TRUE(ResourceUtils::tryParseBool("false", &val));
     EXPECT_FALSE(val);
 
-    EXPECT_TRUE(ResourceUtils::tryParseBool(u"FALSE", &val));
+    EXPECT_TRUE(ResourceUtils::tryParseBool("FALSE", &val));
     EXPECT_FALSE(val);
 
-    EXPECT_TRUE(ResourceUtils::tryParseBool(u"False", &val));
+    EXPECT_TRUE(ResourceUtils::tryParseBool("False", &val));
     EXPECT_FALSE(val);
 }
 
 TEST(ResourceUtilsTest, ParseResourceName) {
     ResourceNameRef actual;
     bool actualPriv = false;
-    EXPECT_TRUE(ResourceUtils::parseResourceName(u"android:color/foo", &actual, &actualPriv));
-    EXPECT_EQ(ResourceNameRef(u"android", ResourceType::kColor, u"foo"), actual);
+    EXPECT_TRUE(ResourceUtils::parseResourceName("android:color/foo", &actual, &actualPriv));
+    EXPECT_EQ(ResourceNameRef("android", ResourceType::kColor, "foo"), actual);
     EXPECT_FALSE(actualPriv);
 
-    EXPECT_TRUE(ResourceUtils::parseResourceName(u"color/foo", &actual, &actualPriv));
-    EXPECT_EQ(ResourceNameRef({}, ResourceType::kColor, u"foo"), actual);
+    EXPECT_TRUE(ResourceUtils::parseResourceName("color/foo", &actual, &actualPriv));
+    EXPECT_EQ(ResourceNameRef({}, ResourceType::kColor, "foo"), actual);
     EXPECT_FALSE(actualPriv);
 
-    EXPECT_TRUE(ResourceUtils::parseResourceName(u"*android:color/foo", &actual, &actualPriv));
-    EXPECT_EQ(ResourceNameRef(u"android", ResourceType::kColor, u"foo"), actual);
+    EXPECT_TRUE(ResourceUtils::parseResourceName("*android:color/foo", &actual, &actualPriv));
+    EXPECT_EQ(ResourceNameRef("android", ResourceType::kColor, "foo"), actual);
     EXPECT_TRUE(actualPriv);
 
-    EXPECT_FALSE(ResourceUtils::parseResourceName(StringPiece16(), &actual, &actualPriv));
+    EXPECT_FALSE(ResourceUtils::parseResourceName(StringPiece(), &actual, &actualPriv));
 }
 
 TEST(ResourceUtilsTest, ParseReferenceWithNoPackage) {
-    ResourceNameRef expected({}, ResourceType::kColor, u"foo");
+    ResourceNameRef expected({}, ResourceType::kColor, "foo");
     ResourceNameRef actual;
     bool create = false;
     bool privateRef = false;
-    EXPECT_TRUE(ResourceUtils::tryParseReference(u"@color/foo", &actual, &create, &privateRef));
+    EXPECT_TRUE(ResourceUtils::tryParseReference("@color/foo", &actual, &create, &privateRef));
     EXPECT_EQ(expected, actual);
     EXPECT_FALSE(create);
     EXPECT_FALSE(privateRef);
 }
 
 TEST(ResourceUtilsTest, ParseReferenceWithPackage) {
-    ResourceNameRef expected(u"android", ResourceType::kColor, u"foo");
+    ResourceNameRef expected("android", ResourceType::kColor, "foo");
     ResourceNameRef actual;
     bool create = false;
     bool privateRef = false;
-    EXPECT_TRUE(ResourceUtils::tryParseReference(u"@android:color/foo", &actual, &create,
+    EXPECT_TRUE(ResourceUtils::tryParseReference("@android:color/foo", &actual, &create,
                                                  &privateRef));
     EXPECT_EQ(expected, actual);
     EXPECT_FALSE(create);
@@ -86,11 +83,11 @@
 }
 
 TEST(ResourceUtilsTest, ParseReferenceWithSurroundingWhitespace) {
-    ResourceNameRef expected(u"android", ResourceType::kColor, u"foo");
+    ResourceNameRef expected("android", ResourceType::kColor, "foo");
     ResourceNameRef actual;
     bool create = false;
     bool privateRef = false;
-    EXPECT_TRUE(ResourceUtils::tryParseReference(u"\t @android:color/foo\n \n\t", &actual,
+    EXPECT_TRUE(ResourceUtils::tryParseReference("\t @android:color/foo\n \n\t", &actual,
                                                  &create, &privateRef));
     EXPECT_EQ(expected, actual);
     EXPECT_FALSE(create);
@@ -98,11 +95,11 @@
 }
 
 TEST(ResourceUtilsTest, ParseAutoCreateIdReference) {
-    ResourceNameRef expected(u"android", ResourceType::kId, u"foo");
+    ResourceNameRef expected("android", ResourceType::kId, "foo");
     ResourceNameRef actual;
     bool create = false;
     bool privateRef = false;
-    EXPECT_TRUE(ResourceUtils::tryParseReference(u"@+android:id/foo", &actual, &create,
+    EXPECT_TRUE(ResourceUtils::tryParseReference("@+android:id/foo", &actual, &create,
                                                  &privateRef));
     EXPECT_EQ(expected, actual);
     EXPECT_TRUE(create);
@@ -110,11 +107,11 @@
 }
 
 TEST(ResourceUtilsTest, ParsePrivateReference) {
-    ResourceNameRef expected(u"android", ResourceType::kId, u"foo");
+    ResourceNameRef expected("android", ResourceType::kId, "foo");
     ResourceNameRef actual;
     bool create = false;
     bool privateRef = false;
-    EXPECT_TRUE(ResourceUtils::tryParseReference(u"@*android:id/foo", &actual, &create,
+    EXPECT_TRUE(ResourceUtils::tryParseReference("@*android:id/foo", &actual, &create,
                                                  &privateRef));
     EXPECT_EQ(expected, actual);
     EXPECT_FALSE(create);
@@ -125,68 +122,68 @@
     bool create = false;
     bool privateRef = false;
     ResourceNameRef actual;
-    EXPECT_FALSE(ResourceUtils::tryParseReference(u"@+android:color/foo", &actual, &create,
+    EXPECT_FALSE(ResourceUtils::tryParseReference("@+android:color/foo", &actual, &create,
                                                   &privateRef));
 }
 
 TEST(ResourceUtilsTest, ParseAttributeReferences) {
-    EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android"));
-    EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android:foo"));
-    EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?attr/foo"));
-    EXPECT_TRUE(ResourceUtils::isAttributeReference(u"?android:attr/foo"));
+    EXPECT_TRUE(ResourceUtils::isAttributeReference("?android"));
+    EXPECT_TRUE(ResourceUtils::isAttributeReference("?android:foo"));
+    EXPECT_TRUE(ResourceUtils::isAttributeReference("?attr/foo"));
+    EXPECT_TRUE(ResourceUtils::isAttributeReference("?android:attr/foo"));
 }
 
 TEST(ResourceUtilsTest, FailParseIncompleteReference) {
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?style/foo"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:style/foo"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?android:attr/"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:attr/"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:attr/foo"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:/"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?:/foo"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?attr/"));
-    EXPECT_FALSE(ResourceUtils::isAttributeReference(u"?/foo"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?style/foo"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?android:style/foo"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?android:"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?android:attr/"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?:attr/"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?:attr/foo"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?:/"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?:/foo"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?attr/"));
+    EXPECT_FALSE(ResourceUtils::isAttributeReference("?/foo"));
 }
 
 TEST(ResourceUtilsTest, ParseStyleParentReference) {
-    const ResourceName kAndroidStyleFooName(u"android", ResourceType::kStyle, u"foo");
-    const ResourceName kStyleFooName({}, ResourceType::kStyle, u"foo");
+    const ResourceName kAndroidStyleFooName("android", ResourceType::kStyle, "foo");
+    const ResourceName kStyleFooName({}, ResourceType::kStyle, "foo");
 
     std::string errStr;
-    Maybe<Reference> ref = ResourceUtils::parseStyleParentReference(u"@android:style/foo", &errStr);
+    Maybe<Reference> ref = ResourceUtils::parseStyleParentReference("@android:style/foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kAndroidStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"@style/foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("@style/foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"?android:style/foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("?android:style/foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kAndroidStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"?style/foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("?style/foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"android:style/foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("android:style/foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kAndroidStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"android:foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("android:foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kAndroidStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"@android:foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("@android:foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kAndroidStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kStyleFooName);
 
-    ref = ResourceUtils::parseStyleParentReference(u"*android:style/foo", &errStr);
+    ref = ResourceUtils::parseStyleParentReference("*android:style/foo", &errStr);
     AAPT_ASSERT_TRUE(ref);
     EXPECT_EQ(ref.value().name.value(), kAndroidStyleFooName);
     EXPECT_TRUE(ref.value().privateReference);
@@ -195,11 +192,11 @@
 TEST(ResourceUtilsTest, ParseEmptyFlag) {
     std::unique_ptr<Attribute> attr = test::AttributeBuilder(false)
             .setTypeMask(android::ResTable_map::TYPE_FLAGS)
-            .addItem(u"one", 0x01)
-            .addItem(u"two", 0x02)
+            .addItem("one", 0x01)
+            .addItem("two", 0x02)
             .build();
 
-    std::unique_ptr<BinaryPrimitive> result = ResourceUtils::tryParseFlagSymbol(attr.get(), u"");
+    std::unique_ptr<BinaryPrimitive> result = ResourceUtils::tryParseFlagSymbol(attr.get(), "");
     ASSERT_NE(nullptr, result);
     EXPECT_EQ(0u, result->value.data);
 }
diff --git a/tools/aapt2/ResourceValues.h b/tools/aapt2/ResourceValues.h
index aa1b550..8ae71ad 100644
--- a/tools/aapt2/ResourceValues.h
+++ b/tools/aapt2/ResourceValues.h
@@ -84,15 +84,15 @@
     /**
      * Returns the comment that was associated with this resource.
      */
-    StringPiece16 getComment() const {
+    const std::string& getComment() const {
         return mComment;
     }
 
-    void setComment(const StringPiece16& str) {
+    void setComment(const StringPiece& str) {
         mComment = str.toString();
     }
 
-    void setComment(std::u16string&& str) {
+    void setComment(std::string&& str) {
         mComment = std::move(str);
     }
 
@@ -115,7 +115,7 @@
 
 protected:
     Source mSource;
-    std::u16string mComment;
+    std::string mComment;
     bool mWeak = false;
     bool mTranslateable = true;
 };
diff --git a/tools/aapt2/Resource_test.cpp b/tools/aapt2/Resource_test.cpp
index 48dc521..06cddc7 100644
--- a/tools/aapt2/Resource_test.cpp
+++ b/tools/aapt2/Resource_test.cpp
@@ -14,102 +14,101 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-
 #include "Resource.h"
+#include "test/Test.h"
 
 namespace aapt {
 
 TEST(ResourceTypeTest, ParseResourceTypes) {
-    const ResourceType* type = parseResourceType(u"anim");
+    const ResourceType* type = parseResourceType("anim");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kAnim);
 
-    type = parseResourceType(u"animator");
+    type = parseResourceType("animator");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kAnimator);
 
-    type = parseResourceType(u"array");
+    type = parseResourceType("array");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kArray);
 
-    type = parseResourceType(u"attr");
+    type = parseResourceType("attr");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kAttr);
 
-    type = parseResourceType(u"^attr-private");
+    type = parseResourceType("^attr-private");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kAttrPrivate);
 
-    type = parseResourceType(u"bool");
+    type = parseResourceType("bool");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kBool);
 
-    type = parseResourceType(u"color");
+    type = parseResourceType("color");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kColor);
 
-    type = parseResourceType(u"dimen");
+    type = parseResourceType("dimen");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kDimen);
 
-    type = parseResourceType(u"drawable");
+    type = parseResourceType("drawable");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kDrawable);
 
-    type = parseResourceType(u"fraction");
+    type = parseResourceType("fraction");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kFraction);
 
-    type = parseResourceType(u"id");
+    type = parseResourceType("id");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kId);
 
-    type = parseResourceType(u"integer");
+    type = parseResourceType("integer");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kInteger);
 
-    type = parseResourceType(u"interpolator");
+    type = parseResourceType("interpolator");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kInterpolator);
 
-    type = parseResourceType(u"layout");
+    type = parseResourceType("layout");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kLayout);
 
-    type = parseResourceType(u"menu");
+    type = parseResourceType("menu");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kMenu);
 
-    type = parseResourceType(u"mipmap");
+    type = parseResourceType("mipmap");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kMipmap);
 
-    type = parseResourceType(u"plurals");
+    type = parseResourceType("plurals");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kPlurals);
 
-    type = parseResourceType(u"raw");
+    type = parseResourceType("raw");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kRaw);
 
-    type = parseResourceType(u"string");
+    type = parseResourceType("string");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kString);
 
-    type = parseResourceType(u"style");
+    type = parseResourceType("style");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kStyle);
 
-    type = parseResourceType(u"transition");
+    type = parseResourceType("transition");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kTransition);
 
-    type = parseResourceType(u"xml");
+    type = parseResourceType("xml");
     ASSERT_NE(type, nullptr);
     EXPECT_EQ(*type, ResourceType::kXml);
 
-    type = parseResourceType(u"blahaha");
+    type = parseResourceType("blahaha");
     EXPECT_EQ(type, nullptr);
 }
 
diff --git a/tools/aapt2/SdkConstants.cpp b/tools/aapt2/SdkConstants.cpp
index 7312ee3..91e755d 100644
--- a/tools/aapt2/SdkConstants.cpp
+++ b/tools/aapt2/SdkConstants.cpp
@@ -23,7 +23,7 @@
 
 namespace aapt {
 
-static const char16_t* sDevelopmentSdkCodeName = u"O";
+static const char* sDevelopmentSdkCodeName = "O";
 static int sDevelopmentSdkLevel = 26;
 
 static const std::vector<std::pair<uint16_t, size_t>> sAttrIdMap = {
@@ -63,671 +63,671 @@
     return iter->second;
 }
 
-static const std::unordered_map<std::u16string, size_t> sAttrMap = {
-    { u"marqueeRepeatLimit", 2 },
-    { u"windowNoDisplay", 3 },
-    { u"backgroundDimEnabled", 3 },
-    { u"inputType", 3 },
-    { u"isDefault", 3 },
-    { u"windowDisablePreview", 3 },
-    { u"privateImeOptions", 3 },
-    { u"editorExtras", 3 },
-    { u"settingsActivity", 3 },
-    { u"fastScrollEnabled", 3 },
-    { u"reqTouchScreen", 3 },
-    { u"reqKeyboardType", 3 },
-    { u"reqHardKeyboard", 3 },
-    { u"reqNavigation", 3 },
-    { u"windowSoftInputMode", 3 },
-    { u"imeFullscreenBackground", 3 },
-    { u"noHistory", 3 },
-    { u"headerDividersEnabled", 3 },
-    { u"footerDividersEnabled", 3 },
-    { u"candidatesTextStyleSpans", 3 },
-    { u"smoothScrollbar", 3 },
-    { u"reqFiveWayNav", 3 },
-    { u"keyBackground", 3 },
-    { u"keyTextSize", 3 },
-    { u"labelTextSize", 3 },
-    { u"keyTextColor", 3 },
-    { u"keyPreviewLayout", 3 },
-    { u"keyPreviewOffset", 3 },
-    { u"keyPreviewHeight", 3 },
-    { u"verticalCorrection", 3 },
-    { u"popupLayout", 3 },
-    { u"state_long_pressable", 3 },
-    { u"keyWidth", 3 },
-    { u"keyHeight", 3 },
-    { u"horizontalGap", 3 },
-    { u"verticalGap", 3 },
-    { u"rowEdgeFlags", 3 },
-    { u"codes", 3 },
-    { u"popupKeyboard", 3 },
-    { u"popupCharacters", 3 },
-    { u"keyEdgeFlags", 3 },
-    { u"isModifier", 3 },
-    { u"isSticky", 3 },
-    { u"isRepeatable", 3 },
-    { u"iconPreview", 3 },
-    { u"keyOutputText", 3 },
-    { u"keyLabel", 3 },
-    { u"keyIcon", 3 },
-    { u"keyboardMode", 3 },
-    { u"isScrollContainer", 3 },
-    { u"fillEnabled", 3 },
-    { u"updatePeriodMillis", 3 },
-    { u"initialLayout", 3 },
-    { u"voiceSearchMode", 3 },
-    { u"voiceLanguageModel", 3 },
-    { u"voicePromptText", 3 },
-    { u"voiceLanguage", 3 },
-    { u"voiceMaxResults", 3 },
-    { u"bottomOffset", 3 },
-    { u"topOffset", 3 },
-    { u"allowSingleTap", 3 },
-    { u"handle", 3 },
-    { u"content", 3 },
-    { u"animateOnClick", 3 },
-    { u"configure", 3 },
-    { u"hapticFeedbackEnabled", 3 },
-    { u"innerRadius", 3 },
-    { u"thickness", 3 },
-    { u"sharedUserLabel", 3 },
-    { u"dropDownWidth", 3 },
-    { u"dropDownAnchor", 3 },
-    { u"imeOptions", 3 },
-    { u"imeActionLabel", 3 },
-    { u"imeActionId", 3 },
-    { u"imeExtractEnterAnimation", 3 },
-    { u"imeExtractExitAnimation", 3 },
-    { u"tension", 4 },
-    { u"extraTension", 4 },
-    { u"anyDensity", 4 },
-    { u"searchSuggestThreshold", 4 },
-    { u"includeInGlobalSearch", 4 },
-    { u"onClick", 4 },
-    { u"targetSdkVersion", 4 },
-    { u"maxSdkVersion", 4 },
-    { u"testOnly", 4 },
-    { u"contentDescription", 4 },
-    { u"gestureStrokeWidth", 4 },
-    { u"gestureColor", 4 },
-    { u"uncertainGestureColor", 4 },
-    { u"fadeOffset", 4 },
-    { u"fadeDuration", 4 },
-    { u"gestureStrokeType", 4 },
-    { u"gestureStrokeLengthThreshold", 4 },
-    { u"gestureStrokeSquarenessThreshold", 4 },
-    { u"gestureStrokeAngleThreshold", 4 },
-    { u"eventsInterceptionEnabled", 4 },
-    { u"fadeEnabled", 4 },
-    { u"backupAgent", 4 },
-    { u"allowBackup", 4 },
-    { u"glEsVersion", 4 },
-    { u"queryAfterZeroResults", 4 },
-    { u"dropDownHeight", 4 },
-    { u"smallScreens", 4 },
-    { u"normalScreens", 4 },
-    { u"largeScreens", 4 },
-    { u"progressBarStyleInverse", 4 },
-    { u"progressBarStyleSmallInverse", 4 },
-    { u"progressBarStyleLargeInverse", 4 },
-    { u"searchSettingsDescription", 4 },
-    { u"textColorPrimaryInverseDisableOnly", 4 },
-    { u"autoUrlDetect", 4 },
-    { u"resizeable", 4 },
-    { u"required", 5 },
-    { u"accountType", 5 },
-    { u"contentAuthority", 5 },
-    { u"userVisible", 5 },
-    { u"windowShowWallpaper", 5 },
-    { u"wallpaperOpenEnterAnimation", 5 },
-    { u"wallpaperOpenExitAnimation", 5 },
-    { u"wallpaperCloseEnterAnimation", 5 },
-    { u"wallpaperCloseExitAnimation", 5 },
-    { u"wallpaperIntraOpenEnterAnimation", 5 },
-    { u"wallpaperIntraOpenExitAnimation", 5 },
-    { u"wallpaperIntraCloseEnterAnimation", 5 },
-    { u"wallpaperIntraCloseExitAnimation", 5 },
-    { u"supportsUploading", 5 },
-    { u"killAfterRestore", 5 },
-    { u"restoreNeedsApplication", 5 },
-    { u"smallIcon", 5 },
-    { u"accountPreferences", 5 },
-    { u"textAppearanceSearchResultSubtitle", 5 },
-    { u"textAppearanceSearchResultTitle", 5 },
-    { u"summaryColumn", 5 },
-    { u"detailColumn", 5 },
-    { u"detailSocialSummary", 5 },
-    { u"thumbnail", 5 },
-    { u"detachWallpaper", 5 },
-    { u"finishOnCloseSystemDialogs", 5 },
-    { u"scrollbarFadeDuration", 5 },
-    { u"scrollbarDefaultDelayBeforeFade", 5 },
-    { u"fadeScrollbars", 5 },
-    { u"colorBackgroundCacheHint", 5 },
-    { u"dropDownHorizontalOffset", 5 },
-    { u"dropDownVerticalOffset", 5 },
-    { u"quickContactBadgeStyleWindowSmall", 6 },
-    { u"quickContactBadgeStyleWindowMedium", 6 },
-    { u"quickContactBadgeStyleWindowLarge", 6 },
-    { u"quickContactBadgeStyleSmallWindowSmall", 6 },
-    { u"quickContactBadgeStyleSmallWindowMedium", 6 },
-    { u"quickContactBadgeStyleSmallWindowLarge", 6 },
-    { u"author", 7 },
-    { u"autoStart", 7 },
-    { u"expandableListViewWhiteStyle", 8 },
-    { u"installLocation", 8 },
-    { u"vmSafeMode", 8 },
-    { u"webTextViewStyle", 8 },
-    { u"restoreAnyVersion", 8 },
-    { u"tabStripLeft", 8 },
-    { u"tabStripRight", 8 },
-    { u"tabStripEnabled", 8 },
-    { u"logo", 9 },
-    { u"xlargeScreens", 9 },
-    { u"immersive", 9 },
-    { u"overScrollMode", 9 },
-    { u"overScrollHeader", 9 },
-    { u"overScrollFooter", 9 },
-    { u"filterTouchesWhenObscured", 9 },
-    { u"textSelectHandleLeft", 9 },
-    { u"textSelectHandleRight", 9 },
-    { u"textSelectHandle", 9 },
-    { u"textSelectHandleWindowStyle", 9 },
-    { u"popupAnimationStyle", 9 },
-    { u"screenSize", 9 },
-    { u"screenDensity", 9 },
-    { u"allContactsName", 11 },
-    { u"windowActionBar", 11 },
-    { u"actionBarStyle", 11 },
-    { u"navigationMode", 11 },
-    { u"displayOptions", 11 },
-    { u"subtitle", 11 },
-    { u"customNavigationLayout", 11 },
-    { u"hardwareAccelerated", 11 },
-    { u"measureWithLargestChild", 11 },
-    { u"animateFirstView", 11 },
-    { u"dropDownSpinnerStyle", 11 },
-    { u"actionDropDownStyle", 11 },
-    { u"actionButtonStyle", 11 },
-    { u"showAsAction", 11 },
-    { u"previewImage", 11 },
-    { u"actionModeBackground", 11 },
-    { u"actionModeCloseDrawable", 11 },
-    { u"windowActionModeOverlay", 11 },
-    { u"valueFrom", 11 },
-    { u"valueTo", 11 },
-    { u"valueType", 11 },
-    { u"propertyName", 11 },
-    { u"ordering", 11 },
-    { u"fragment", 11 },
-    { u"windowActionBarOverlay", 11 },
-    { u"fragmentOpenEnterAnimation", 11 },
-    { u"fragmentOpenExitAnimation", 11 },
-    { u"fragmentCloseEnterAnimation", 11 },
-    { u"fragmentCloseExitAnimation", 11 },
-    { u"fragmentFadeEnterAnimation", 11 },
-    { u"fragmentFadeExitAnimation", 11 },
-    { u"actionBarSize", 11 },
-    { u"imeSubtypeLocale", 11 },
-    { u"imeSubtypeMode", 11 },
-    { u"imeSubtypeExtraValue", 11 },
-    { u"splitMotionEvents", 11 },
-    { u"listChoiceBackgroundIndicator", 11 },
-    { u"spinnerMode", 11 },
-    { u"animateLayoutChanges", 11 },
-    { u"actionBarTabStyle", 11 },
-    { u"actionBarTabBarStyle", 11 },
-    { u"actionBarTabTextStyle", 11 },
-    { u"actionOverflowButtonStyle", 11 },
-    { u"actionModeCloseButtonStyle", 11 },
-    { u"titleTextStyle", 11 },
-    { u"subtitleTextStyle", 11 },
-    { u"iconifiedByDefault", 11 },
-    { u"actionLayout", 11 },
-    { u"actionViewClass", 11 },
-    { u"activatedBackgroundIndicator", 11 },
-    { u"state_activated", 11 },
-    { u"listPopupWindowStyle", 11 },
-    { u"popupMenuStyle", 11 },
-    { u"textAppearanceLargePopupMenu", 11 },
-    { u"textAppearanceSmallPopupMenu", 11 },
-    { u"breadCrumbTitle", 11 },
-    { u"breadCrumbShortTitle", 11 },
-    { u"listDividerAlertDialog", 11 },
-    { u"textColorAlertDialogListItem", 11 },
-    { u"loopViews", 11 },
-    { u"dialogTheme", 11 },
-    { u"alertDialogTheme", 11 },
-    { u"dividerVertical", 11 },
-    { u"homeAsUpIndicator", 11 },
-    { u"enterFadeDuration", 11 },
-    { u"exitFadeDuration", 11 },
-    { u"selectableItemBackground", 11 },
-    { u"autoAdvanceViewId", 11 },
-    { u"useIntrinsicSizeAsMinimum", 11 },
-    { u"actionModeCutDrawable", 11 },
-    { u"actionModeCopyDrawable", 11 },
-    { u"actionModePasteDrawable", 11 },
-    { u"textEditPasteWindowLayout", 11 },
-    { u"textEditNoPasteWindowLayout", 11 },
-    { u"textIsSelectable", 11 },
-    { u"windowEnableSplitTouch", 11 },
-    { u"indeterminateProgressStyle", 11 },
-    { u"progressBarPadding", 11 },
-    { u"animationResolution", 11 },
-    { u"state_accelerated", 11 },
-    { u"baseline", 11 },
-    { u"homeLayout", 11 },
-    { u"opacity", 11 },
-    { u"alpha", 11 },
-    { u"transformPivotX", 11 },
-    { u"transformPivotY", 11 },
-    { u"translationX", 11 },
-    { u"translationY", 11 },
-    { u"scaleX", 11 },
-    { u"scaleY", 11 },
-    { u"rotation", 11 },
-    { u"rotationX", 11 },
-    { u"rotationY", 11 },
-    { u"showDividers", 11 },
-    { u"dividerPadding", 11 },
-    { u"borderlessButtonStyle", 11 },
-    { u"dividerHorizontal", 11 },
-    { u"itemPadding", 11 },
-    { u"buttonBarStyle", 11 },
-    { u"buttonBarButtonStyle", 11 },
-    { u"segmentedButtonStyle", 11 },
-    { u"staticWallpaperPreview", 11 },
-    { u"allowParallelSyncs", 11 },
-    { u"isAlwaysSyncable", 11 },
-    { u"verticalScrollbarPosition", 11 },
-    { u"fastScrollAlwaysVisible", 11 },
-    { u"fastScrollThumbDrawable", 11 },
-    { u"fastScrollPreviewBackgroundLeft", 11 },
-    { u"fastScrollPreviewBackgroundRight", 11 },
-    { u"fastScrollTrackDrawable", 11 },
-    { u"fastScrollOverlayPosition", 11 },
-    { u"customTokens", 11 },
-    { u"nextFocusForward", 11 },
-    { u"firstDayOfWeek", 11 },
-    { u"showWeekNumber", 11 },
-    { u"minDate", 11 },
-    { u"maxDate", 11 },
-    { u"shownWeekCount", 11 },
-    { u"selectedWeekBackgroundColor", 11 },
-    { u"focusedMonthDateColor", 11 },
-    { u"unfocusedMonthDateColor", 11 },
-    { u"weekNumberColor", 11 },
-    { u"weekSeparatorLineColor", 11 },
-    { u"selectedDateVerticalBar", 11 },
-    { u"weekDayTextAppearance", 11 },
-    { u"dateTextAppearance", 11 },
-    { u"solidColor", 11 },
-    { u"spinnersShown", 11 },
-    { u"calendarViewShown", 11 },
-    { u"state_multiline", 11 },
-    { u"detailsElementBackground", 11 },
-    { u"textColorHighlightInverse", 11 },
-    { u"textColorLinkInverse", 11 },
-    { u"editTextColor", 11 },
-    { u"editTextBackground", 11 },
-    { u"horizontalScrollViewStyle", 11 },
-    { u"layerType", 11 },
-    { u"alertDialogIcon", 11 },
-    { u"windowMinWidthMajor", 11 },
-    { u"windowMinWidthMinor", 11 },
-    { u"queryHint", 11 },
-    { u"fastScrollTextColor", 11 },
-    { u"largeHeap", 11 },
-    { u"windowCloseOnTouchOutside", 11 },
-    { u"datePickerStyle", 11 },
-    { u"calendarViewStyle", 11 },
-    { u"textEditSidePasteWindowLayout", 11 },
-    { u"textEditSideNoPasteWindowLayout", 11 },
-    { u"actionMenuTextAppearance", 11 },
-    { u"actionMenuTextColor", 11 },
-    { u"textCursorDrawable", 12 },
-    { u"resizeMode", 12 },
-    { u"requiresSmallestWidthDp", 12 },
-    { u"compatibleWidthLimitDp", 12 },
-    { u"largestWidthLimitDp", 12 },
-    { u"state_hovered", 13 },
-    { u"state_drag_can_accept", 13 },
-    { u"state_drag_hovered", 13 },
-    { u"stopWithTask", 13 },
-    { u"switchTextOn", 13 },
-    { u"switchTextOff", 13 },
-    { u"switchPreferenceStyle", 13 },
-    { u"switchTextAppearance", 13 },
-    { u"track", 13 },
-    { u"switchMinWidth", 13 },
-    { u"switchPadding", 13 },
-    { u"thumbTextPadding", 13 },
-    { u"textSuggestionsWindowStyle", 13 },
-    { u"textEditSuggestionItemLayout", 13 },
-    { u"rowCount", 13 },
-    { u"rowOrderPreserved", 13 },
-    { u"columnCount", 13 },
-    { u"columnOrderPreserved", 13 },
-    { u"useDefaultMargins", 13 },
-    { u"alignmentMode", 13 },
-    { u"layout_row", 13 },
-    { u"layout_rowSpan", 13 },
-    { u"layout_columnSpan", 13 },
-    { u"actionModeSelectAllDrawable", 13 },
-    { u"isAuxiliary", 13 },
-    { u"accessibilityEventTypes", 13 },
-    { u"packageNames", 13 },
-    { u"accessibilityFeedbackType", 13 },
-    { u"notificationTimeout", 13 },
-    { u"accessibilityFlags", 13 },
-    { u"canRetrieveWindowContent", 13 },
-    { u"listPreferredItemHeightLarge", 13 },
-    { u"listPreferredItemHeightSmall", 13 },
-    { u"actionBarSplitStyle", 13 },
-    { u"actionProviderClass", 13 },
-    { u"backgroundStacked", 13 },
-    { u"backgroundSplit", 13 },
-    { u"textAllCaps", 13 },
-    { u"colorPressedHighlight", 13 },
-    { u"colorLongPressedHighlight", 13 },
-    { u"colorFocusedHighlight", 13 },
-    { u"colorActivatedHighlight", 13 },
-    { u"colorMultiSelectHighlight", 13 },
-    { u"drawableStart", 13 },
-    { u"drawableEnd", 13 },
-    { u"actionModeStyle", 13 },
-    { u"minResizeWidth", 13 },
-    { u"minResizeHeight", 13 },
-    { u"actionBarWidgetTheme", 13 },
-    { u"uiOptions", 13 },
-    { u"subtypeLocale", 13 },
-    { u"subtypeExtraValue", 13 },
-    { u"actionBarDivider", 13 },
-    { u"actionBarItemBackground", 13 },
-    { u"actionModeSplitBackground", 13 },
-    { u"textAppearanceListItem", 13 },
-    { u"textAppearanceListItemSmall", 13 },
-    { u"targetDescriptions", 13 },
-    { u"directionDescriptions", 13 },
-    { u"overridesImplicitlyEnabledSubtype", 13 },
-    { u"listPreferredItemPaddingLeft", 13 },
-    { u"listPreferredItemPaddingRight", 13 },
-    { u"requiresFadingEdge", 13 },
-    { u"publicKey", 13 },
-    { u"parentActivityName", 16 },
-    { u"isolatedProcess", 16 },
-    { u"importantForAccessibility", 16 },
-    { u"keyboardLayout", 16 },
-    { u"fontFamily", 16 },
-    { u"mediaRouteButtonStyle", 16 },
-    { u"mediaRouteTypes", 16 },
-    { u"supportsRtl", 17 },
-    { u"textDirection", 17 },
-    { u"textAlignment", 17 },
-    { u"layoutDirection", 17 },
-    { u"paddingStart", 17 },
-    { u"paddingEnd", 17 },
-    { u"layout_marginStart", 17 },
-    { u"layout_marginEnd", 17 },
-    { u"layout_toStartOf", 17 },
-    { u"layout_toEndOf", 17 },
-    { u"layout_alignStart", 17 },
-    { u"layout_alignEnd", 17 },
-    { u"layout_alignParentStart", 17 },
-    { u"layout_alignParentEnd", 17 },
-    { u"listPreferredItemPaddingStart", 17 },
-    { u"listPreferredItemPaddingEnd", 17 },
-    { u"singleUser", 17 },
-    { u"presentationTheme", 17 },
-    { u"subtypeId", 17 },
-    { u"initialKeyguardLayout", 17 },
-    { u"widgetCategory", 17 },
-    { u"permissionGroupFlags", 17 },
-    { u"labelFor", 17 },
-    { u"permissionFlags", 17 },
-    { u"checkedTextViewStyle", 17 },
-    { u"showOnLockScreen", 17 },
-    { u"format12Hour", 17 },
-    { u"format24Hour", 17 },
-    { u"timeZone", 17 },
-    { u"mipMap", 18 },
-    { u"mirrorForRtl", 18 },
-    { u"windowOverscan", 18 },
-    { u"requiredForAllUsers", 18 },
-    { u"indicatorStart", 18 },
-    { u"indicatorEnd", 18 },
-    { u"childIndicatorStart", 18 },
-    { u"childIndicatorEnd", 18 },
-    { u"restrictedAccountType", 18 },
-    { u"requiredAccountType", 18 },
-    { u"canRequestTouchExplorationMode", 18 },
-    { u"canRequestEnhancedWebAccessibility", 18 },
-    { u"canRequestFilterKeyEvents", 18 },
-    { u"layoutMode", 18 },
-    { u"keySet", 19 },
-    { u"targetId", 19 },
-    { u"fromScene", 19 },
-    { u"toScene", 19 },
-    { u"transition", 19 },
-    { u"transitionOrdering", 19 },
-    { u"fadingMode", 19 },
-    { u"startDelay", 19 },
-    { u"ssp", 19 },
-    { u"sspPrefix", 19 },
-    { u"sspPattern", 19 },
-    { u"addPrintersActivity", 19 },
-    { u"vendor", 19 },
-    { u"category", 19 },
-    { u"isAsciiCapable", 19 },
-    { u"autoMirrored", 19 },
-    { u"supportsSwitchingToNextInputMethod", 19 },
-    { u"requireDeviceUnlock", 19 },
-    { u"apduServiceBanner", 19 },
-    { u"accessibilityLiveRegion", 19 },
-    { u"windowTranslucentStatus", 19 },
-    { u"windowTranslucentNavigation", 19 },
-    { u"advancedPrintOptionsActivity", 19 },
-    { u"banner", 20 },
-    { u"windowSwipeToDismiss", 20 },
-    { u"isGame", 20 },
-    { u"allowEmbedded", 20 },
-    { u"setupActivity", 20 },
-    { u"fastScrollStyle", 21 },
-    { u"windowContentTransitions", 21 },
-    { u"windowContentTransitionManager", 21 },
-    { u"translationZ", 21 },
-    { u"tintMode", 21 },
-    { u"controlX1", 21 },
-    { u"controlY1", 21 },
-    { u"controlX2", 21 },
-    { u"controlY2", 21 },
-    { u"transitionName", 21 },
-    { u"transitionGroup", 21 },
-    { u"viewportWidth", 21 },
-    { u"viewportHeight", 21 },
-    { u"fillColor", 21 },
-    { u"pathData", 21 },
-    { u"strokeColor", 21 },
-    { u"strokeWidth", 21 },
-    { u"trimPathStart", 21 },
-    { u"trimPathEnd", 21 },
-    { u"trimPathOffset", 21 },
-    { u"strokeLineCap", 21 },
-    { u"strokeLineJoin", 21 },
-    { u"strokeMiterLimit", 21 },
-    { u"colorControlNormal", 21 },
-    { u"colorControlActivated", 21 },
-    { u"colorButtonNormal", 21 },
-    { u"colorControlHighlight", 21 },
-    { u"persistableMode", 21 },
-    { u"titleTextAppearance", 21 },
-    { u"subtitleTextAppearance", 21 },
-    { u"slideEdge", 21 },
-    { u"actionBarTheme", 21 },
-    { u"textAppearanceListItemSecondary", 21 },
-    { u"colorPrimary", 21 },
-    { u"colorPrimaryDark", 21 },
-    { u"colorAccent", 21 },
-    { u"nestedScrollingEnabled", 21 },
-    { u"windowEnterTransition", 21 },
-    { u"windowExitTransition", 21 },
-    { u"windowSharedElementEnterTransition", 21 },
-    { u"windowSharedElementExitTransition", 21 },
-    { u"windowAllowReturnTransitionOverlap", 21 },
-    { u"windowAllowEnterTransitionOverlap", 21 },
-    { u"sessionService", 21 },
-    { u"stackViewStyle", 21 },
-    { u"switchStyle", 21 },
-    { u"elevation", 21 },
-    { u"excludeId", 21 },
-    { u"excludeClass", 21 },
-    { u"hideOnContentScroll", 21 },
-    { u"actionOverflowMenuStyle", 21 },
-    { u"documentLaunchMode", 21 },
-    { u"maxRecents", 21 },
-    { u"autoRemoveFromRecents", 21 },
-    { u"stateListAnimator", 21 },
-    { u"toId", 21 },
-    { u"fromId", 21 },
-    { u"reversible", 21 },
-    { u"splitTrack", 21 },
-    { u"targetName", 21 },
-    { u"excludeName", 21 },
-    { u"matchOrder", 21 },
-    { u"windowDrawsSystemBarBackgrounds", 21 },
-    { u"statusBarColor", 21 },
-    { u"navigationBarColor", 21 },
-    { u"contentInsetStart", 21 },
-    { u"contentInsetEnd", 21 },
-    { u"contentInsetLeft", 21 },
-    { u"contentInsetRight", 21 },
-    { u"paddingMode", 21 },
-    { u"layout_rowWeight", 21 },
-    { u"layout_columnWeight", 21 },
-    { u"translateX", 21 },
-    { u"translateY", 21 },
-    { u"selectableItemBackgroundBorderless", 21 },
-    { u"elegantTextHeight", 21 },
-    { u"searchKeyphraseId", 21 },
-    { u"searchKeyphrase", 21 },
-    { u"searchKeyphraseSupportedLocales", 21 },
-    { u"windowTransitionBackgroundFadeDuration", 21 },
-    { u"overlapAnchor", 21 },
-    { u"progressTint", 21 },
-    { u"progressTintMode", 21 },
-    { u"progressBackgroundTint", 21 },
-    { u"progressBackgroundTintMode", 21 },
-    { u"secondaryProgressTint", 21 },
-    { u"secondaryProgressTintMode", 21 },
-    { u"indeterminateTint", 21 },
-    { u"indeterminateTintMode", 21 },
-    { u"backgroundTint", 21 },
-    { u"backgroundTintMode", 21 },
-    { u"foregroundTint", 21 },
-    { u"foregroundTintMode", 21 },
-    { u"buttonTint", 21 },
-    { u"buttonTintMode", 21 },
-    { u"thumbTint", 21 },
-    { u"thumbTintMode", 21 },
-    { u"fullBackupOnly", 21 },
-    { u"propertyXName", 21 },
-    { u"propertyYName", 21 },
-    { u"relinquishTaskIdentity", 21 },
-    { u"tileModeX", 21 },
-    { u"tileModeY", 21 },
-    { u"actionModeShareDrawable", 21 },
-    { u"actionModeFindDrawable", 21 },
-    { u"actionModeWebSearchDrawable", 21 },
-    { u"transitionVisibilityMode", 21 },
-    { u"minimumHorizontalAngle", 21 },
-    { u"minimumVerticalAngle", 21 },
-    { u"maximumAngle", 21 },
-    { u"searchViewStyle", 21 },
-    { u"closeIcon", 21 },
-    { u"goIcon", 21 },
-    { u"searchIcon", 21 },
-    { u"voiceIcon", 21 },
-    { u"commitIcon", 21 },
-    { u"suggestionRowLayout", 21 },
-    { u"queryBackground", 21 },
-    { u"submitBackground", 21 },
-    { u"buttonBarPositiveButtonStyle", 21 },
-    { u"buttonBarNeutralButtonStyle", 21 },
-    { u"buttonBarNegativeButtonStyle", 21 },
-    { u"popupElevation", 21 },
-    { u"actionBarPopupTheme", 21 },
-    { u"multiArch", 21 },
-    { u"touchscreenBlocksFocus", 21 },
-    { u"windowElevation", 21 },
-    { u"launchTaskBehindTargetAnimation", 21 },
-    { u"launchTaskBehindSourceAnimation", 21 },
-    { u"restrictionType", 21 },
-    { u"dayOfWeekBackground", 21 },
-    { u"dayOfWeekTextAppearance", 21 },
-    { u"headerMonthTextAppearance", 21 },
-    { u"headerDayOfMonthTextAppearance", 21 },
-    { u"headerYearTextAppearance", 21 },
-    { u"yearListItemTextAppearance", 21 },
-    { u"yearListSelectorColor", 21 },
-    { u"calendarTextColor", 21 },
-    { u"recognitionService", 21 },
-    { u"timePickerStyle", 21 },
-    { u"timePickerDialogTheme", 21 },
-    { u"headerTimeTextAppearance", 21 },
-    { u"headerAmPmTextAppearance", 21 },
-    { u"numbersTextColor", 21 },
-    { u"numbersBackgroundColor", 21 },
-    { u"numbersSelectorColor", 21 },
-    { u"amPmTextColor", 21 },
-    { u"amPmBackgroundColor", 21 },
-    { u"searchKeyphraseRecognitionFlags", 21 },
-    { u"checkMarkTint", 21 },
-    { u"checkMarkTintMode", 21 },
-    { u"popupTheme", 21 },
-    { u"toolbarStyle", 21 },
-    { u"windowClipToOutline", 21 },
-    { u"datePickerDialogTheme", 21 },
-    { u"showText", 21 },
-    { u"windowReturnTransition", 21 },
-    { u"windowReenterTransition", 21 },
-    { u"windowSharedElementReturnTransition", 21 },
-    { u"windowSharedElementReenterTransition", 21 },
-    { u"resumeWhilePausing", 21 },
-    { u"datePickerMode", 21 },
-    { u"timePickerMode", 21 },
-    { u"inset", 21 },
-    { u"letterSpacing", 21 },
-    { u"fontFeatureSettings", 21 },
-    { u"outlineProvider", 21 },
-    { u"contentAgeHint", 21 },
-    { u"country", 21 },
-    { u"windowSharedElementsUseOverlay", 21 },
-    { u"reparent", 21 },
-    { u"reparentWithOverlay", 21 },
-    { u"ambientShadowAlpha", 21 },
-    { u"spotShadowAlpha", 21 },
-    { u"navigationIcon", 21 },
-    { u"navigationContentDescription", 21 },
-    { u"fragmentExitTransition", 21 },
-    { u"fragmentEnterTransition", 21 },
-    { u"fragmentSharedElementEnterTransition", 21 },
-    { u"fragmentReturnTransition", 21 },
-    { u"fragmentSharedElementReturnTransition", 21 },
-    { u"fragmentReenterTransition", 21 },
-    { u"fragmentAllowEnterTransitionOverlap", 21 },
-    { u"fragmentAllowReturnTransitionOverlap", 21 },
-    { u"patternPathData", 21 },
-    { u"strokeAlpha", 21 },
-    { u"fillAlpha", 21 },
-    { u"windowActivityTransitions", 21 },
-    { u"colorEdgeEffect", 21 }
+static const std::unordered_map<std::string, size_t> sAttrMap = {
+    { "marqueeRepeatLimit", 2 },
+    { "windowNoDisplay", 3 },
+    { "backgroundDimEnabled", 3 },
+    { "inputType", 3 },
+    { "isDefault", 3 },
+    { "windowDisablePreview", 3 },
+    { "privateImeOptions", 3 },
+    { "editorExtras", 3 },
+    { "settingsActivity", 3 },
+    { "fastScrollEnabled", 3 },
+    { "reqTouchScreen", 3 },
+    { "reqKeyboardType", 3 },
+    { "reqHardKeyboard", 3 },
+    { "reqNavigation", 3 },
+    { "windowSoftInputMode", 3 },
+    { "imeFullscreenBackground", 3 },
+    { "noHistory", 3 },
+    { "headerDividersEnabled", 3 },
+    { "footerDividersEnabled", 3 },
+    { "candidatesTextStyleSpans", 3 },
+    { "smoothScrollbar", 3 },
+    { "reqFiveWayNav", 3 },
+    { "keyBackground", 3 },
+    { "keyTextSize", 3 },
+    { "labelTextSize", 3 },
+    { "keyTextColor", 3 },
+    { "keyPreviewLayout", 3 },
+    { "keyPreviewOffset", 3 },
+    { "keyPreviewHeight", 3 },
+    { "verticalCorrection", 3 },
+    { "popupLayout", 3 },
+    { "state_long_pressable", 3 },
+    { "keyWidth", 3 },
+    { "keyHeight", 3 },
+    { "horizontalGap", 3 },
+    { "verticalGap", 3 },
+    { "rowEdgeFlags", 3 },
+    { "codes", 3 },
+    { "popupKeyboard", 3 },
+    { "popupCharacters", 3 },
+    { "keyEdgeFlags", 3 },
+    { "isModifier", 3 },
+    { "isSticky", 3 },
+    { "isRepeatable", 3 },
+    { "iconPreview", 3 },
+    { "keyOutputText", 3 },
+    { "keyLabel", 3 },
+    { "keyIcon", 3 },
+    { "keyboardMode", 3 },
+    { "isScrollContainer", 3 },
+    { "fillEnabled", 3 },
+    { "updatePeriodMillis", 3 },
+    { "initialLayout", 3 },
+    { "voiceSearchMode", 3 },
+    { "voiceLanguageModel", 3 },
+    { "voicePromptText", 3 },
+    { "voiceLanguage", 3 },
+    { "voiceMaxResults", 3 },
+    { "bottomOffset", 3 },
+    { "topOffset", 3 },
+    { "allowSingleTap", 3 },
+    { "handle", 3 },
+    { "content", 3 },
+    { "animateOnClick", 3 },
+    { "configure", 3 },
+    { "hapticFeedbackEnabled", 3 },
+    { "innerRadius", 3 },
+    { "thickness", 3 },
+    { "sharedUserLabel", 3 },
+    { "dropDownWidth", 3 },
+    { "dropDownAnchor", 3 },
+    { "imeOptions", 3 },
+    { "imeActionLabel", 3 },
+    { "imeActionId", 3 },
+    { "imeExtractEnterAnimation", 3 },
+    { "imeExtractExitAnimation", 3 },
+    { "tension", 4 },
+    { "extraTension", 4 },
+    { "anyDensity", 4 },
+    { "searchSuggestThreshold", 4 },
+    { "includeInGlobalSearch", 4 },
+    { "onClick", 4 },
+    { "targetSdkVersion", 4 },
+    { "maxSdkVersion", 4 },
+    { "testOnly", 4 },
+    { "contentDescription", 4 },
+    { "gestureStrokeWidth", 4 },
+    { "gestureColor", 4 },
+    { "uncertainGestureColor", 4 },
+    { "fadeOffset", 4 },
+    { "fadeDuration", 4 },
+    { "gestureStrokeType", 4 },
+    { "gestureStrokeLengthThreshold", 4 },
+    { "gestureStrokeSquarenessThreshold", 4 },
+    { "gestureStrokeAngleThreshold", 4 },
+    { "eventsInterceptionEnabled", 4 },
+    { "fadeEnabled", 4 },
+    { "backupAgent", 4 },
+    { "allowBackup", 4 },
+    { "glEsVersion", 4 },
+    { "queryAfterZeroResults", 4 },
+    { "dropDownHeight", 4 },
+    { "smallScreens", 4 },
+    { "normalScreens", 4 },
+    { "largeScreens", 4 },
+    { "progressBarStyleInverse", 4 },
+    { "progressBarStyleSmallInverse", 4 },
+    { "progressBarStyleLargeInverse", 4 },
+    { "searchSettingsDescription", 4 },
+    { "textColorPrimaryInverseDisableOnly", 4 },
+    { "autoUrlDetect", 4 },
+    { "resizeable", 4 },
+    { "required", 5 },
+    { "accountType", 5 },
+    { "contentAuthority", 5 },
+    { "userVisible", 5 },
+    { "windowShowWallpaper", 5 },
+    { "wallpaperOpenEnterAnimation", 5 },
+    { "wallpaperOpenExitAnimation", 5 },
+    { "wallpaperCloseEnterAnimation", 5 },
+    { "wallpaperCloseExitAnimation", 5 },
+    { "wallpaperIntraOpenEnterAnimation", 5 },
+    { "wallpaperIntraOpenExitAnimation", 5 },
+    { "wallpaperIntraCloseEnterAnimation", 5 },
+    { "wallpaperIntraCloseExitAnimation", 5 },
+    { "supportsUploading", 5 },
+    { "killAfterRestore", 5 },
+    { "restoreNeedsApplication", 5 },
+    { "smallIcon", 5 },
+    { "accountPreferences", 5 },
+    { "textAppearanceSearchResultSubtitle", 5 },
+    { "textAppearanceSearchResultTitle", 5 },
+    { "summaryColumn", 5 },
+    { "detailColumn", 5 },
+    { "detailSocialSummary", 5 },
+    { "thumbnail", 5 },
+    { "detachWallpaper", 5 },
+    { "finishOnCloseSystemDialogs", 5 },
+    { "scrollbarFadeDuration", 5 },
+    { "scrollbarDefaultDelayBeforeFade", 5 },
+    { "fadeScrollbars", 5 },
+    { "colorBackgroundCacheHint", 5 },
+    { "dropDownHorizontalOffset", 5 },
+    { "dropDownVerticalOffset", 5 },
+    { "quickContactBadgeStyleWindowSmall", 6 },
+    { "quickContactBadgeStyleWindowMedium", 6 },
+    { "quickContactBadgeStyleWindowLarge", 6 },
+    { "quickContactBadgeStyleSmallWindowSmall", 6 },
+    { "quickContactBadgeStyleSmallWindowMedium", 6 },
+    { "quickContactBadgeStyleSmallWindowLarge", 6 },
+    { "author", 7 },
+    { "autoStart", 7 },
+    { "expandableListViewWhiteStyle", 8 },
+    { "installLocation", 8 },
+    { "vmSafeMode", 8 },
+    { "webTextViewStyle", 8 },
+    { "restoreAnyVersion", 8 },
+    { "tabStripLeft", 8 },
+    { "tabStripRight", 8 },
+    { "tabStripEnabled", 8 },
+    { "logo", 9 },
+    { "xlargeScreens", 9 },
+    { "immersive", 9 },
+    { "overScrollMode", 9 },
+    { "overScrollHeader", 9 },
+    { "overScrollFooter", 9 },
+    { "filterTouchesWhenObscured", 9 },
+    { "textSelectHandleLeft", 9 },
+    { "textSelectHandleRight", 9 },
+    { "textSelectHandle", 9 },
+    { "textSelectHandleWindowStyle", 9 },
+    { "popupAnimationStyle", 9 },
+    { "screenSize", 9 },
+    { "screenDensity", 9 },
+    { "allContactsName", 11 },
+    { "windowActionBar", 11 },
+    { "actionBarStyle", 11 },
+    { "navigationMode", 11 },
+    { "displayOptions", 11 },
+    { "subtitle", 11 },
+    { "customNavigationLayout", 11 },
+    { "hardwareAccelerated", 11 },
+    { "measureWithLargestChild", 11 },
+    { "animateFirstView", 11 },
+    { "dropDownSpinnerStyle", 11 },
+    { "actionDropDownStyle", 11 },
+    { "actionButtonStyle", 11 },
+    { "showAsAction", 11 },
+    { "previewImage", 11 },
+    { "actionModeBackground", 11 },
+    { "actionModeCloseDrawable", 11 },
+    { "windowActionModeOverlay", 11 },
+    { "valueFrom", 11 },
+    { "valueTo", 11 },
+    { "valueType", 11 },
+    { "propertyName", 11 },
+    { "ordering", 11 },
+    { "fragment", 11 },
+    { "windowActionBarOverlay", 11 },
+    { "fragmentOpenEnterAnimation", 11 },
+    { "fragmentOpenExitAnimation", 11 },
+    { "fragmentCloseEnterAnimation", 11 },
+    { "fragmentCloseExitAnimation", 11 },
+    { "fragmentFadeEnterAnimation", 11 },
+    { "fragmentFadeExitAnimation", 11 },
+    { "actionBarSize", 11 },
+    { "imeSubtypeLocale", 11 },
+    { "imeSubtypeMode", 11 },
+    { "imeSubtypeExtraValue", 11 },
+    { "splitMotionEvents", 11 },
+    { "listChoiceBackgroundIndicator", 11 },
+    { "spinnerMode", 11 },
+    { "animateLayoutChanges", 11 },
+    { "actionBarTabStyle", 11 },
+    { "actionBarTabBarStyle", 11 },
+    { "actionBarTabTextStyle", 11 },
+    { "actionOverflowButtonStyle", 11 },
+    { "actionModeCloseButtonStyle", 11 },
+    { "titleTextStyle", 11 },
+    { "subtitleTextStyle", 11 },
+    { "iconifiedByDefault", 11 },
+    { "actionLayout", 11 },
+    { "actionViewClass", 11 },
+    { "activatedBackgroundIndicator", 11 },
+    { "state_activated", 11 },
+    { "listPopupWindowStyle", 11 },
+    { "popupMenuStyle", 11 },
+    { "textAppearanceLargePopupMen", 11 },
+    { "textAppearanceSmallPopupMen", 11 },
+    { "breadCrumbTitle", 11 },
+    { "breadCrumbShortTitle", 11 },
+    { "listDividerAlertDialog", 11 },
+    { "textColorAlertDialogListItem", 11 },
+    { "loopViews", 11 },
+    { "dialogTheme", 11 },
+    { "alertDialogTheme", 11 },
+    { "dividerVertical", 11 },
+    { "homeAsUpIndicator", 11 },
+    { "enterFadeDuration", 11 },
+    { "exitFadeDuration", 11 },
+    { "selectableItemBackground", 11 },
+    { "autoAdvanceViewId", 11 },
+    { "useIntrinsicSizeAsMinimum", 11 },
+    { "actionModeCutDrawable", 11 },
+    { "actionModeCopyDrawable", 11 },
+    { "actionModePasteDrawable", 11 },
+    { "textEditPasteWindowLayout", 11 },
+    { "textEditNoPasteWindowLayout", 11 },
+    { "textIsSelectable", 11 },
+    { "windowEnableSplitTouch", 11 },
+    { "indeterminateProgressStyle", 11 },
+    { "progressBarPadding", 11 },
+    { "animationResolution", 11 },
+    { "state_accelerated", 11 },
+    { "baseline", 11 },
+    { "homeLayout", 11 },
+    { "opacity", 11 },
+    { "alpha", 11 },
+    { "transformPivotX", 11 },
+    { "transformPivotY", 11 },
+    { "translationX", 11 },
+    { "translationY", 11 },
+    { "scaleX", 11 },
+    { "scaleY", 11 },
+    { "rotation", 11 },
+    { "rotationX", 11 },
+    { "rotationY", 11 },
+    { "showDividers", 11 },
+    { "dividerPadding", 11 },
+    { "borderlessButtonStyle", 11 },
+    { "dividerHorizontal", 11 },
+    { "itemPadding", 11 },
+    { "buttonBarStyle", 11 },
+    { "buttonBarButtonStyle", 11 },
+    { "segmentedButtonStyle", 11 },
+    { "staticWallpaperPreview", 11 },
+    { "allowParallelSyncs", 11 },
+    { "isAlwaysSyncable", 11 },
+    { "verticalScrollbarPosition", 11 },
+    { "fastScrollAlwaysVisible", 11 },
+    { "fastScrollThumbDrawable", 11 },
+    { "fastScrollPreviewBackgroundLeft", 11 },
+    { "fastScrollPreviewBackgroundRight", 11 },
+    { "fastScrollTrackDrawable", 11 },
+    { "fastScrollOverlayPosition", 11 },
+    { "customTokens", 11 },
+    { "nextFocusForward", 11 },
+    { "firstDayOfWeek", 11 },
+    { "showWeekNumber", 11 },
+    { "minDate", 11 },
+    { "maxDate", 11 },
+    { "shownWeekCount", 11 },
+    { "selectedWeekBackgroundColor", 11 },
+    { "focusedMonthDateColor", 11 },
+    { "unfocusedMonthDateColor", 11 },
+    { "weekNumberColor", 11 },
+    { "weekSeparatorLineColor", 11 },
+    { "selectedDateVerticalBar", 11 },
+    { "weekDayTextAppearance", 11 },
+    { "dateTextAppearance", 11 },
+    { "solidColor", 11 },
+    { "spinnersShown", 11 },
+    { "calendarViewShown", 11 },
+    { "state_multiline", 11 },
+    { "detailsElementBackground", 11 },
+    { "textColorHighlightInverse", 11 },
+    { "textColorLinkInverse", 11 },
+    { "editTextColor", 11 },
+    { "editTextBackground", 11 },
+    { "horizontalScrollViewStyle", 11 },
+    { "layerType", 11 },
+    { "alertDialogIcon", 11 },
+    { "windowMinWidthMajor", 11 },
+    { "windowMinWidthMinor", 11 },
+    { "queryHint", 11 },
+    { "fastScrollTextColor", 11 },
+    { "largeHeap", 11 },
+    { "windowCloseOnTouchOutside", 11 },
+    { "datePickerStyle", 11 },
+    { "calendarViewStyle", 11 },
+    { "textEditSidePasteWindowLayout", 11 },
+    { "textEditSideNoPasteWindowLayout", 11 },
+    { "actionMenuTextAppearance", 11 },
+    { "actionMenuTextColor", 11 },
+    { "textCursorDrawable", 12 },
+    { "resizeMode", 12 },
+    { "requiresSmallestWidthDp", 12 },
+    { "compatibleWidthLimitDp", 12 },
+    { "largestWidthLimitDp", 12 },
+    { "state_hovered", 13 },
+    { "state_drag_can_accept", 13 },
+    { "state_drag_hovered", 13 },
+    { "stopWithTask", 13 },
+    { "switchTextOn", 13 },
+    { "switchTextOff", 13 },
+    { "switchPreferenceStyle", 13 },
+    { "switchTextAppearance", 13 },
+    { "track", 13 },
+    { "switchMinWidth", 13 },
+    { "switchPadding", 13 },
+    { "thumbTextPadding", 13 },
+    { "textSuggestionsWindowStyle", 13 },
+    { "textEditSuggestionItemLayout", 13 },
+    { "rowCount", 13 },
+    { "rowOrderPreserved", 13 },
+    { "columnCount", 13 },
+    { "columnOrderPreserved", 13 },
+    { "useDefaultMargins", 13 },
+    { "alignmentMode", 13 },
+    { "layout_row", 13 },
+    { "layout_rowSpan", 13 },
+    { "layout_columnSpan", 13 },
+    { "actionModeSelectAllDrawable", 13 },
+    { "isAuxiliary", 13 },
+    { "accessibilityEventTypes", 13 },
+    { "packageNames", 13 },
+    { "accessibilityFeedbackType", 13 },
+    { "notificationTimeout", 13 },
+    { "accessibilityFlags", 13 },
+    { "canRetrieveWindowContent", 13 },
+    { "listPreferredItemHeightLarge", 13 },
+    { "listPreferredItemHeightSmall", 13 },
+    { "actionBarSplitStyle", 13 },
+    { "actionProviderClass", 13 },
+    { "backgroundStacked", 13 },
+    { "backgroundSplit", 13 },
+    { "textAllCaps", 13 },
+    { "colorPressedHighlight", 13 },
+    { "colorLongPressedHighlight", 13 },
+    { "colorFocusedHighlight", 13 },
+    { "colorActivatedHighlight", 13 },
+    { "colorMultiSelectHighlight", 13 },
+    { "drawableStart", 13 },
+    { "drawableEnd", 13 },
+    { "actionModeStyle", 13 },
+    { "minResizeWidth", 13 },
+    { "minResizeHeight", 13 },
+    { "actionBarWidgetTheme", 13 },
+    { "uiOptions", 13 },
+    { "subtypeLocale", 13 },
+    { "subtypeExtraValue", 13 },
+    { "actionBarDivider", 13 },
+    { "actionBarItemBackground", 13 },
+    { "actionModeSplitBackground", 13 },
+    { "textAppearanceListItem", 13 },
+    { "textAppearanceListItemSmall", 13 },
+    { "targetDescriptions", 13 },
+    { "directionDescriptions", 13 },
+    { "overridesImplicitlyEnabledSubtype", 13 },
+    { "listPreferredItemPaddingLeft", 13 },
+    { "listPreferredItemPaddingRight", 13 },
+    { "requiresFadingEdge", 13 },
+    { "publicKey", 13 },
+    { "parentActivityName", 16 },
+    { "isolatedProcess", 16 },
+    { "importantForAccessibility", 16 },
+    { "keyboardLayout", 16 },
+    { "fontFamily", 16 },
+    { "mediaRouteButtonStyle", 16 },
+    { "mediaRouteTypes", 16 },
+    { "supportsRtl", 17 },
+    { "textDirection", 17 },
+    { "textAlignment", 17 },
+    { "layoutDirection", 17 },
+    { "paddingStart", 17 },
+    { "paddingEnd", 17 },
+    { "layout_marginStart", 17 },
+    { "layout_marginEnd", 17 },
+    { "layout_toStartOf", 17 },
+    { "layout_toEndOf", 17 },
+    { "layout_alignStart", 17 },
+    { "layout_alignEnd", 17 },
+    { "layout_alignParentStart", 17 },
+    { "layout_alignParentEnd", 17 },
+    { "listPreferredItemPaddingStart", 17 },
+    { "listPreferredItemPaddingEnd", 17 },
+    { "singleUser", 17 },
+    { "presentationTheme", 17 },
+    { "subtypeId", 17 },
+    { "initialKeyguardLayout", 17 },
+    { "widgetCategory", 17 },
+    { "permissionGroupFlags", 17 },
+    { "labelFor", 17 },
+    { "permissionFlags", 17 },
+    { "checkedTextViewStyle", 17 },
+    { "showOnLockScreen", 17 },
+    { "format12Hour", 17 },
+    { "format24Hour", 17 },
+    { "timeZone", 17 },
+    { "mipMap", 18 },
+    { "mirrorForRtl", 18 },
+    { "windowOverscan", 18 },
+    { "requiredForAllUsers", 18 },
+    { "indicatorStart", 18 },
+    { "indicatorEnd", 18 },
+    { "childIndicatorStart", 18 },
+    { "childIndicatorEnd", 18 },
+    { "restrictedAccountType", 18 },
+    { "requiredAccountType", 18 },
+    { "canRequestTouchExplorationMode", 18 },
+    { "canRequestEnhancedWebAccessibility", 18 },
+    { "canRequestFilterKeyEvents", 18 },
+    { "layoutMode", 18 },
+    { "keySet", 19 },
+    { "targetId", 19 },
+    { "fromScene", 19 },
+    { "toScene", 19 },
+    { "transition", 19 },
+    { "transitionOrdering", 19 },
+    { "fadingMode", 19 },
+    { "startDelay", 19 },
+    { "ssp", 19 },
+    { "sspPrefix", 19 },
+    { "sspPattern", 19 },
+    { "addPrintersActivity", 19 },
+    { "vendor", 19 },
+    { "category", 19 },
+    { "isAsciiCapable", 19 },
+    { "autoMirrored", 19 },
+    { "supportsSwitchingToNextInputMethod", 19 },
+    { "requireDeviceUnlock", 19 },
+    { "apduServiceBanner", 19 },
+    { "accessibilityLiveRegion", 19 },
+    { "windowTranslucentStatus", 19 },
+    { "windowTranslucentNavigation", 19 },
+    { "advancedPrintOptionsActivity", 19 },
+    { "banner", 20 },
+    { "windowSwipeToDismiss", 20 },
+    { "isGame", 20 },
+    { "allowEmbedded", 20 },
+    { "setupActivity", 20 },
+    { "fastScrollStyle", 21 },
+    { "windowContentTransitions", 21 },
+    { "windowContentTransitionManager", 21 },
+    { "translationZ", 21 },
+    { "tintMode", 21 },
+    { "controlX1", 21 },
+    { "controlY1", 21 },
+    { "controlX2", 21 },
+    { "controlY2", 21 },
+    { "transitionName", 21 },
+    { "transitionGroup", 21 },
+    { "viewportWidth", 21 },
+    { "viewportHeight", 21 },
+    { "fillColor", 21 },
+    { "pathData", 21 },
+    { "strokeColor", 21 },
+    { "strokeWidth", 21 },
+    { "trimPathStart", 21 },
+    { "trimPathEnd", 21 },
+    { "trimPathOffset", 21 },
+    { "strokeLineCap", 21 },
+    { "strokeLineJoin", 21 },
+    { "strokeMiterLimit", 21 },
+    { "colorControlNormal", 21 },
+    { "colorControlActivated", 21 },
+    { "colorButtonNormal", 21 },
+    { "colorControlHighlight", 21 },
+    { "persistableMode", 21 },
+    { "titleTextAppearance", 21 },
+    { "subtitleTextAppearance", 21 },
+    { "slideEdge", 21 },
+    { "actionBarTheme", 21 },
+    { "textAppearanceListItemSecondary", 21 },
+    { "colorPrimary", 21 },
+    { "colorPrimaryDark", 21 },
+    { "colorAccent", 21 },
+    { "nestedScrollingEnabled", 21 },
+    { "windowEnterTransition", 21 },
+    { "windowExitTransition", 21 },
+    { "windowSharedElementEnterTransition", 21 },
+    { "windowSharedElementExitTransition", 21 },
+    { "windowAllowReturnTransitionOverlap", 21 },
+    { "windowAllowEnterTransitionOverlap", 21 },
+    { "sessionService", 21 },
+    { "stackViewStyle", 21 },
+    { "switchStyle", 21 },
+    { "elevation", 21 },
+    { "excludeId", 21 },
+    { "excludeClass", 21 },
+    { "hideOnContentScroll", 21 },
+    { "actionOverflowMenuStyle", 21 },
+    { "documentLaunchMode", 21 },
+    { "maxRecents", 21 },
+    { "autoRemoveFromRecents", 21 },
+    { "stateListAnimator", 21 },
+    { "toId", 21 },
+    { "fromId", 21 },
+    { "reversible", 21 },
+    { "splitTrack", 21 },
+    { "targetName", 21 },
+    { "excludeName", 21 },
+    { "matchOrder", 21 },
+    { "windowDrawsSystemBarBackgrounds", 21 },
+    { "statusBarColor", 21 },
+    { "navigationBarColor", 21 },
+    { "contentInsetStart", 21 },
+    { "contentInsetEnd", 21 },
+    { "contentInsetLeft", 21 },
+    { "contentInsetRight", 21 },
+    { "paddingMode", 21 },
+    { "layout_rowWeight", 21 },
+    { "layout_columnWeight", 21 },
+    { "translateX", 21 },
+    { "translateY", 21 },
+    { "selectableItemBackgroundBorderless", 21 },
+    { "elegantTextHeight", 21 },
+    { "searchKeyphraseId", 21 },
+    { "searchKeyphrase", 21 },
+    { "searchKeyphraseSupportedLocales", 21 },
+    { "windowTransitionBackgroundFadeDuration", 21 },
+    { "overlapAnchor", 21 },
+    { "progressTint", 21 },
+    { "progressTintMode", 21 },
+    { "progressBackgroundTint", 21 },
+    { "progressBackgroundTintMode", 21 },
+    { "secondaryProgressTint", 21 },
+    { "secondaryProgressTintMode", 21 },
+    { "indeterminateTint", 21 },
+    { "indeterminateTintMode", 21 },
+    { "backgroundTint", 21 },
+    { "backgroundTintMode", 21 },
+    { "foregroundTint", 21 },
+    { "foregroundTintMode", 21 },
+    { "buttonTint", 21 },
+    { "buttonTintMode", 21 },
+    { "thumbTint", 21 },
+    { "thumbTintMode", 21 },
+    { "fullBackupOnly", 21 },
+    { "propertyXName", 21 },
+    { "propertyYName", 21 },
+    { "relinquishTaskIdentity", 21 },
+    { "tileModeX", 21 },
+    { "tileModeY", 21 },
+    { "actionModeShareDrawable", 21 },
+    { "actionModeFindDrawable", 21 },
+    { "actionModeWebSearchDrawable", 21 },
+    { "transitionVisibilityMode", 21 },
+    { "minimumHorizontalAngle", 21 },
+    { "minimumVerticalAngle", 21 },
+    { "maximumAngle", 21 },
+    { "searchViewStyle", 21 },
+    { "closeIcon", 21 },
+    { "goIcon", 21 },
+    { "searchIcon", 21 },
+    { "voiceIcon", 21 },
+    { "commitIcon", 21 },
+    { "suggestionRowLayout", 21 },
+    { "queryBackground", 21 },
+    { "submitBackground", 21 },
+    { "buttonBarPositiveButtonStyle", 21 },
+    { "buttonBarNeutralButtonStyle", 21 },
+    { "buttonBarNegativeButtonStyle", 21 },
+    { "popupElevation", 21 },
+    { "actionBarPopupTheme", 21 },
+    { "multiArch", 21 },
+    { "touchscreenBlocksFocus", 21 },
+    { "windowElevation", 21 },
+    { "launchTaskBehindTargetAnimation", 21 },
+    { "launchTaskBehindSourceAnimation", 21 },
+    { "restrictionType", 21 },
+    { "dayOfWeekBackground", 21 },
+    { "dayOfWeekTextAppearance", 21 },
+    { "headerMonthTextAppearance", 21 },
+    { "headerDayOfMonthTextAppearance", 21 },
+    { "headerYearTextAppearance", 21 },
+    { "yearListItemTextAppearance", 21 },
+    { "yearListSelectorColor", 21 },
+    { "calendarTextColor", 21 },
+    { "recognitionService", 21 },
+    { "timePickerStyle", 21 },
+    { "timePickerDialogTheme", 21 },
+    { "headerTimeTextAppearance", 21 },
+    { "headerAmPmTextAppearance", 21 },
+    { "numbersTextColor", 21 },
+    { "numbersBackgroundColor", 21 },
+    { "numbersSelectorColor", 21 },
+    { "amPmTextColor", 21 },
+    { "amPmBackgroundColor", 21 },
+    { "searchKeyphraseRecognitionFlags", 21 },
+    { "checkMarkTint", 21 },
+    { "checkMarkTintMode", 21 },
+    { "popupTheme", 21 },
+    { "toolbarStyle", 21 },
+    { "windowClipToOutline", 21 },
+    { "datePickerDialogTheme", 21 },
+    { "showText", 21 },
+    { "windowReturnTransition", 21 },
+    { "windowReenterTransition", 21 },
+    { "windowSharedElementReturnTransition", 21 },
+    { "windowSharedElementReenterTransition", 21 },
+    { "resumeWhilePausing", 21 },
+    { "datePickerMode", 21 },
+    { "timePickerMode", 21 },
+    { "inset", 21 },
+    { "letterSpacing", 21 },
+    { "fontFeatureSettings", 21 },
+    { "outlineProvider", 21 },
+    { "contentAgeHint", 21 },
+    { "country", 21 },
+    { "windowSharedElementsUseOverlay", 21 },
+    { "reparent", 21 },
+    { "reparentWithOverlay", 21 },
+    { "ambientShadowAlpha", 21 },
+    { "spotShadowAlpha", 21 },
+    { "navigationIcon", 21 },
+    { "navigationContentDescription", 21 },
+    { "fragmentExitTransition", 21 },
+    { "fragmentEnterTransition", 21 },
+    { "fragmentSharedElementEnterTransition", 21 },
+    { "fragmentReturnTransition", 21 },
+    { "fragmentSharedElementReturnTransition", 21 },
+    { "fragmentReenterTransition", 21 },
+    { "fragmentAllowEnterTransitionOverlap", 21 },
+    { "fragmentAllowReturnTransitionOverlap", 21 },
+    { "patternPathData", 21 },
+    { "strokeAlpha", 21 },
+    { "fillAlpha", 21 },
+    { "windowActivityTransitions", 21 },
+    { "colorEdgeEffect", 21 }
 };
 
 size_t findAttributeSdkLevel(const ResourceName& name) {
-    if (name.package != u"android" && name.type != ResourceType::kAttr) {
+    if (name.package != "android" && name.type != ResourceType::kAttr) {
         return 0;
     }
 
@@ -738,8 +738,8 @@
     return SDK_LOLLIPOP_MR1;
 }
 
-std::pair<StringPiece16, int> getDevelopmentSdkCodeNameAndVersion() {
-    return std::make_pair(StringPiece16(sDevelopmentSdkCodeName), sDevelopmentSdkLevel);
+std::pair<StringPiece, int> getDevelopmentSdkCodeNameAndVersion() {
+    return std::make_pair(StringPiece(sDevelopmentSdkCodeName), sDevelopmentSdkLevel);
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/SdkConstants.h b/tools/aapt2/SdkConstants.h
index a6dba8b..f28679f 100644
--- a/tools/aapt2/SdkConstants.h
+++ b/tools/aapt2/SdkConstants.h
@@ -49,7 +49,7 @@
 
 size_t findAttributeSdkLevel(ResourceId id);
 size_t findAttributeSdkLevel(const ResourceName& name);
-std::pair<StringPiece16, int> getDevelopmentSdkCodeNameAndVersion();
+std::pair<StringPiece, int> getDevelopmentSdkCodeNameAndVersion();
 
 } // namespace aapt
 
diff --git a/tools/aapt2/StringPool.cpp b/tools/aapt2/StringPool.cpp
index aadb00b..fe4b967 100644
--- a/tools/aapt2/StringPool.cpp
+++ b/tools/aapt2/StringPool.cpp
@@ -59,11 +59,11 @@
     return *this;
 }
 
-const std::u16string* StringPool::Ref::operator->() const {
+const std::string* StringPool::Ref::operator->() const {
     return &mEntry->value;
 }
 
-const std::u16string& StringPool::Ref::operator*() const {
+const std::string& StringPool::Ref::operator*() const {
     return mEntry->value;
 }
 
@@ -124,15 +124,15 @@
     return mEntry->str.getContext();
 }
 
-StringPool::Ref StringPool::makeRef(const StringPiece16& str) {
+StringPool::Ref StringPool::makeRef(const StringPiece& str) {
     return makeRefImpl(str, Context{}, true);
 }
 
-StringPool::Ref StringPool::makeRef(const StringPiece16& str, const Context& context) {
+StringPool::Ref StringPool::makeRef(const StringPiece& str, const Context& context) {
     return makeRefImpl(str, context, true);
 }
 
-StringPool::Ref StringPool::makeRefImpl(const StringPiece16& str, const Context& context,
+StringPool::Ref StringPool::makeRefImpl(const StringPiece& str, const Context& context,
         bool unique) {
     if (unique) {
         auto iter = mIndexedStrings.find(str);
@@ -147,7 +147,7 @@
     entry->index = mStrings.size();
     entry->ref = 0;
     mStrings.emplace_back(entry);
-    mIndexedStrings.insert(std::make_pair(StringPiece16(entry->value), entry));
+    mIndexedStrings.insert(std::make_pair(StringPiece(entry->value), entry));
     return Ref(entry);
 }
 
@@ -162,13 +162,12 @@
     entry->index = mStrings.size();
     entry->ref = 0;
     mStrings.emplace_back(entry);
-    mIndexedStrings.insert(std::make_pair(StringPiece16(entry->value), entry));
+    mIndexedStrings.insert(std::make_pair(StringPiece(entry->value), entry));
 
     StyleEntry* styleEntry = new StyleEntry();
     styleEntry->str = Ref(entry);
     for (const aapt::Span& span : str.spans) {
-        styleEntry->spans.emplace_back(Span{makeRef(span.name),
-                span.firstChar, span.lastChar});
+        styleEntry->spans.emplace_back(Span{ makeRef(span.name), span.firstChar, span.lastChar });
     }
     styleEntry->ref = 0;
     mStyles.emplace_back(styleEntry);
@@ -182,7 +181,7 @@
     entry->index = mStrings.size();
     entry->ref = 0;
     mStrings.emplace_back(entry);
-    mIndexedStrings.insert(std::make_pair(StringPiece16(entry->value), entry));
+    mIndexedStrings.insert(std::make_pair(StringPiece(entry->value), entry));
 
     StyleEntry* styleEntry = new StyleEntry();
     styleEntry->str = Ref(entry);
@@ -320,33 +319,40 @@
         indices++;
 
         if (utf8) {
-            std::string encoded = util::utf16ToUtf8(entry->value);
+            const std::string& encoded = entry->value;
+            const ssize_t utf16Length = utf8_to_utf16_length(
+                    reinterpret_cast<const uint8_t*>(entry->value.data()), entry->value.size());
+            assert(utf16Length >= 0);
 
-            const size_t totalSize = encodedLengthUnits<char>(entry->value.size())
+            const size_t totalSize = encodedLengthUnits<char>(utf16Length)
                     + encodedLengthUnits<char>(encoded.length())
                     + encoded.size() + 1;
 
             char* data = out->nextBlock<char>(totalSize);
 
-            // First encode the actual UTF16 string length.
-            data = encodeLength(data, entry->value.size());
+            // First encode the UTF16 string length.
+            data = encodeLength(data, utf16Length);
 
-            // Now encode the size of the converted UTF8 string.
+            // Now encode the size of the real UTF8 string.
             data = encodeLength(data, encoded.length());
             strncpy(data, encoded.data(), encoded.size());
+
         } else {
-            const size_t totalSize = encodedLengthUnits<char16_t>(entry->value.size())
-                    + entry->value.size() + 1;
+            const std::u16string encoded = util::utf8ToUtf16(entry->value);
+            const ssize_t utf16Length = encoded.size();
+
+            // Total number of 16-bit words to write.
+            const size_t totalSize = encodedLengthUnits<char16_t>(utf16Length) + encoded.size() + 1;
 
             char16_t* data = out->nextBlock<char16_t>(totalSize);
 
             // Encode the actual UTF16 string length.
-            data = encodeLength(data, entry->value.size());
-            const size_t byteLength = entry->value.size() * sizeof(char16_t);
+            data = encodeLength(data, utf16Length);
+            const size_t byteLength = encoded.size() * sizeof(char16_t);
 
             // NOTE: For some reason, strncpy16(data, entry->value.data(), entry->value.size())
             // truncates the string.
-            memcpy(data, entry->value.data(), byteLength);
+            memcpy(data, encoded.data(), byteLength);
 
             // The null-terminating character is already here due to the block of data being set
             // to 0s on allocation.
diff --git a/tools/aapt2/StringPool.h b/tools/aapt2/StringPool.h
index 5f88543..72ae9d1 100644
--- a/tools/aapt2/StringPool.h
+++ b/tools/aapt2/StringPool.h
@@ -30,13 +30,13 @@
 namespace aapt {
 
 struct Span {
-    std::u16string name;
+    std::string name;
     uint32_t firstChar;
     uint32_t lastChar;
 };
 
 struct StyleString {
-    std::u16string str;
+    std::string str;
     std::vector<Span> spans;
 };
 
@@ -56,8 +56,8 @@
         ~Ref();
 
         Ref& operator=(const Ref& rhs);
-        const std::u16string* operator->() const;
-        const std::u16string& operator*() const;
+        const std::string* operator->() const;
+        const std::string& operator*() const;
 
         size_t getIndex() const;
         const Context& getContext() const;
@@ -95,7 +95,7 @@
 
     class Entry {
     public:
-        std::u16string value;
+        std::string value;
         Context context;
         size_t index;
 
@@ -136,14 +136,14 @@
      * Adds a string to the pool, unless it already exists. Returns
      * a reference to the string in the pool.
      */
-    Ref makeRef(const StringPiece16& str);
+    Ref makeRef(const StringPiece& str);
 
     /**
      * Adds a string to the pool, unless it already exists, with a context
      * object that can be used when sorting the string pool. Returns
      * a reference to the string in the pool.
      */
-    Ref makeRef(const StringPiece16& str, const Context& context);
+    Ref makeRef(const StringPiece& str, const Context& context);
 
     /**
      * Adds a style to the string pool and returns a reference to it.
@@ -195,11 +195,11 @@
 
     static bool flatten(BigBuffer* out, const StringPool& pool, bool utf8);
 
-    Ref makeRefImpl(const StringPiece16& str, const Context& context, bool unique);
+    Ref makeRefImpl(const StringPiece& str, const Context& context, bool unique);
 
     std::vector<std::unique_ptr<Entry>> mStrings;
     std::vector<std::unique_ptr<StyleEntry>> mStyles;
-    std::unordered_multimap<StringPiece16, Entry*> mIndexedStrings;
+    std::unordered_multimap<StringPiece, Entry*> mIndexedStrings;
 };
 
 //
diff --git a/tools/aapt2/StringPool_test.cpp b/tools/aapt2/StringPool_test.cpp
index 562d80e..1367af7 100644
--- a/tools/aapt2/StringPool_test.cpp
+++ b/tools/aapt2/StringPool_test.cpp
@@ -15,9 +15,9 @@
  */
 
 #include "StringPool.h"
+#include "test/Test.h"
 #include "util/Util.h"
 
-#include <gtest/gtest.h>
 #include <string>
 
 namespace aapt {
@@ -25,37 +25,37 @@
 TEST(StringPoolTest, InsertOneString) {
     StringPool pool;
 
-    StringPool::Ref ref = pool.makeRef(u"wut");
-    EXPECT_EQ(*ref, u"wut");
+    StringPool::Ref ref = pool.makeRef("wut");
+    EXPECT_EQ(*ref, "wut");
 }
 
 TEST(StringPoolTest, InsertTwoUniqueStrings) {
     StringPool pool;
 
-    StringPool::Ref ref = pool.makeRef(u"wut");
-    StringPool::Ref ref2 = pool.makeRef(u"hey");
+    StringPool::Ref ref = pool.makeRef("wut");
+    StringPool::Ref ref2 = pool.makeRef("hey");
 
-    EXPECT_EQ(*ref, u"wut");
-    EXPECT_EQ(*ref2, u"hey");
+    EXPECT_EQ(*ref, "wut");
+    EXPECT_EQ(*ref2, "hey");
 }
 
 TEST(StringPoolTest, DoNotInsertNewDuplicateString) {
     StringPool pool;
 
-    StringPool::Ref ref = pool.makeRef(u"wut");
-    StringPool::Ref ref2 = pool.makeRef(u"wut");
+    StringPool::Ref ref = pool.makeRef("wut");
+    StringPool::Ref ref2 = pool.makeRef("wut");
 
-    EXPECT_EQ(*ref, u"wut");
-    EXPECT_EQ(*ref2, u"wut");
+    EXPECT_EQ(*ref, "wut");
+    EXPECT_EQ(*ref2, "wut");
     EXPECT_EQ(1u, pool.size());
 }
 
 TEST(StringPoolTest, MaintainInsertionOrderIndex) {
     StringPool pool;
 
-    StringPool::Ref ref = pool.makeRef(u"z");
-    StringPool::Ref ref2 = pool.makeRef(u"a");
-    StringPool::Ref ref3 = pool.makeRef(u"m");
+    StringPool::Ref ref = pool.makeRef("z");
+    StringPool::Ref ref2 = pool.makeRef("a");
+    StringPool::Ref ref3 = pool.makeRef("m");
 
     EXPECT_EQ(0u, ref.getIndex());
     EXPECT_EQ(1u, ref2.getIndex());
@@ -65,39 +65,39 @@
 TEST(StringPoolTest, PruneStringsWithNoReferences) {
     StringPool pool;
 
-    StringPool::Ref refA = pool.makeRef(u"foo");
+    StringPool::Ref refA = pool.makeRef("foo");
     {
-        StringPool::Ref ref = pool.makeRef(u"wut");
-        EXPECT_EQ(*ref, u"wut");
+        StringPool::Ref ref = pool.makeRef("wut");
+        EXPECT_EQ(*ref, "wut");
         EXPECT_EQ(2u, pool.size());
     }
-    StringPool::Ref refB = pool.makeRef(u"bar");
+    StringPool::Ref refB = pool.makeRef("bar");
 
     EXPECT_EQ(3u, pool.size());
     pool.prune();
     EXPECT_EQ(2u, pool.size());
     StringPool::const_iterator iter = begin(pool);
-    EXPECT_EQ((*iter)->value, u"foo");
+    EXPECT_EQ((*iter)->value, "foo");
     EXPECT_LT((*iter)->index, 2u);
     ++iter;
-    EXPECT_EQ((*iter)->value, u"bar");
+    EXPECT_EQ((*iter)->value, "bar");
     EXPECT_LT((*iter)->index, 2u);
 }
 
 TEST(StringPoolTest, SortAndMaintainIndexesInReferences) {
     StringPool pool;
 
-    StringPool::Ref ref = pool.makeRef(u"z");
-    StringPool::StyleRef ref2 = pool.makeRef(StyleString{ {u"a"} });
-    StringPool::Ref ref3 = pool.makeRef(u"m");
+    StringPool::Ref ref = pool.makeRef("z");
+    StringPool::StyleRef ref2 = pool.makeRef(StyleString{ {"a"} });
+    StringPool::Ref ref3 = pool.makeRef("m");
 
-    EXPECT_EQ(*ref, u"z");
+    EXPECT_EQ(*ref, "z");
     EXPECT_EQ(0u, ref.getIndex());
 
-    EXPECT_EQ(*(ref2->str), u"a");
+    EXPECT_EQ(*(ref2->str), "a");
     EXPECT_EQ(1u, ref2.getIndex());
 
-    EXPECT_EQ(*ref3, u"m");
+    EXPECT_EQ(*ref3, "m");
     EXPECT_EQ(2u, ref3.getIndex());
 
     pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
@@ -105,30 +105,30 @@
     });
 
 
-    EXPECT_EQ(*ref, u"z");
+    EXPECT_EQ(*ref, "z");
     EXPECT_EQ(2u, ref.getIndex());
 
-    EXPECT_EQ(*(ref2->str), u"a");
+    EXPECT_EQ(*(ref2->str), "a");
     EXPECT_EQ(0u, ref2.getIndex());
 
-    EXPECT_EQ(*ref3, u"m");
+    EXPECT_EQ(*ref3, "m");
     EXPECT_EQ(1u, ref3.getIndex());
 }
 
 TEST(StringPoolTest, SortAndStillDedupe) {
     StringPool pool;
 
-    StringPool::Ref ref = pool.makeRef(u"z");
-    StringPool::Ref ref2 = pool.makeRef(u"a");
-    StringPool::Ref ref3 = pool.makeRef(u"m");
+    StringPool::Ref ref = pool.makeRef("z");
+    StringPool::Ref ref2 = pool.makeRef("a");
+    StringPool::Ref ref3 = pool.makeRef("m");
 
     pool.sort([](const StringPool::Entry& a, const StringPool::Entry& b) -> bool {
         return a.value < b.value;
     });
 
-    StringPool::Ref ref4 = pool.makeRef(u"z");
-    StringPool::Ref ref5 = pool.makeRef(u"a");
-    StringPool::Ref ref6 = pool.makeRef(u"m");
+    StringPool::Ref ref4 = pool.makeRef("z");
+    StringPool::Ref ref5 = pool.makeRef("a");
+    StringPool::Ref ref6 = pool.makeRef("m");
 
     EXPECT_EQ(ref4.getIndex(), ref.getIndex());
     EXPECT_EQ(ref5.getIndex(), ref2.getIndex());
@@ -139,20 +139,20 @@
     StringPool pool;
 
     StyleString str {
-        { u"android" },
+        { "android" },
         {
-            Span{ { u"b" }, 2, 6 }
+            Span{ { "b" }, 2, 6 }
         }
     };
 
     StringPool::StyleRef ref = pool.makeRef(str);
 
     EXPECT_EQ(0u, ref.getIndex());
-    EXPECT_EQ(std::u16string(u"android"), *(ref->str));
+    EXPECT_EQ(std::string("android"), *(ref->str));
     ASSERT_EQ(1u, ref->spans.size());
 
     const StringPool::Span& span = ref->spans.front();
-    EXPECT_EQ(*(span.name), u"b");
+    EXPECT_EQ(*(span.name), "b");
     EXPECT_EQ(2u, span.firstChar);
     EXPECT_EQ(6u, span.lastChar);
 }
@@ -160,9 +160,9 @@
 TEST(StringPoolTest, DoNotDedupeStyleWithSameStringAsNonStyle) {
     StringPool pool;
 
-    StringPool::Ref ref = pool.makeRef(u"android");
+    StringPool::Ref ref = pool.makeRef("android");
 
-    StyleString str { { u"android" } };
+    StyleString str { { "android" } };
     StringPool::StyleRef styleRef = pool.makeRef(str);
 
     EXPECT_NE(ref.getIndex(), styleRef.getIndex());
@@ -184,7 +184,7 @@
     using namespace android; // For NO_ERROR on Windows.
 
     StringPool pool;
-    pool.makeRef(u"\u093f");
+    pool.makeRef("\u093f");
     BigBuffer buffer(1024);
     StringPool::flattenUtf16(&buffer, pool);
 
@@ -198,20 +198,20 @@
     EXPECT_EQ(0u, str[1]);
 }
 
-constexpr const char16_t* sLongString = u"バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使 用するその他のアプリは、起動しても更新されないことがあります。バッテリーセーバーは端末の充電中は自動的にOFFになります。";
+constexpr const char* sLongString = "バッテリーを長持ちさせるため、バッテリーセーバーは端末のパフォーマンスを抑え、バイブレーション、位置情報サービス、大半のバックグラウンドデータを制限します。メール、SMSや、同期を使 用するその他のアプリは、起動しても更新されないことがあります。バッテリーセーバーは端末の充電中は自動的にOFFになります。";
 
-TEST(StringPoolTest, FlattenUtf8) {
+TEST(StringPoolTest, Flatten) {
     using namespace android; // For NO_ERROR on Windows.
 
     StringPool pool;
 
-    StringPool::Ref ref1 = pool.makeRef(u"hello");
-    StringPool::Ref ref2 = pool.makeRef(u"goodbye");
+    StringPool::Ref ref1 = pool.makeRef("hello");
+    StringPool::Ref ref2 = pool.makeRef("goodbye");
     StringPool::Ref ref3 = pool.makeRef(sLongString);
-    StringPool::Ref ref4 = pool.makeRef(u"");
+    StringPool::Ref ref4 = pool.makeRef("");
     StringPool::StyleRef ref5 = pool.makeRef(StyleString{
-            { u"style" },
-            { Span{ { u"b" }, 0, 1 }, Span{ { u"i" }, 2, 3 } }
+            { "style" },
+            { Span{ { "b" }, 0, 1 }, Span{ { "i" }, 2, 3 } }
     });
 
     EXPECT_EQ(0u, ref1.getIndex());
@@ -220,30 +220,43 @@
     EXPECT_EQ(3u, ref4.getIndex());
     EXPECT_EQ(4u, ref5.getIndex());
 
-    BigBuffer buffer(1024);
-    StringPool::flattenUtf8(&buffer, pool);
+    BigBuffer buffers[2] = { BigBuffer(1024), BigBuffer(1024) };
+    StringPool::flattenUtf8(&buffers[0], pool);
+    StringPool::flattenUtf16(&buffers[1], pool);
 
-    std::unique_ptr<uint8_t[]> data = util::copy(buffer);
-    {
+    // Test both UTF-8 and UTF-16 buffers.
+    for (const BigBuffer& buffer : buffers) {
+        std::unique_ptr<uint8_t[]> data = util::copy(buffer);
+
         ResStringPool test;
         ASSERT_EQ(test.setTo(data.get(), buffer.size()), NO_ERROR);
 
-        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(std::string("hello"), util::getString(test, 0));
+        EXPECT_EQ(StringPiece16(u"hello"), util::getString16(test, 0));
+
+        EXPECT_EQ(std::string("goodbye"), util::getString(test, 1));
+        EXPECT_EQ(StringPiece16(u"goodbye"), util::getString16(test, 1));
+
+        EXPECT_EQ(StringPiece(sLongString), util::getString(test, 2));
+        EXPECT_EQ(util::utf8ToUtf16(sLongString), util::getString16(test, 2).toString());
+
         size_t len;
-        EXPECT_NE(nullptr, test.stringAt(3, &len));
-        EXPECT_EQ(util::getString(test, 4), u"style");
+        EXPECT_TRUE(test.stringAt(3, &len) != nullptr || test.string8At(3, &len) != nullptr);
+
+        EXPECT_EQ(std::string("style"), util::getString(test, 4));
+        EXPECT_EQ(StringPiece16(u"style"), util::getString16(test, 4));
 
         const ResStringPool_span* span = test.styleAt(4);
         ASSERT_NE(nullptr, span);
-        EXPECT_EQ(util::getString(test, span->name.index), u"b");
+        EXPECT_EQ(std::string("b"), util::getString(test, span->name.index));
+        EXPECT_EQ(StringPiece16(u"b"), util::getString16(test, span->name.index));
         EXPECT_EQ(0u, span->firstChar);
         EXPECT_EQ(1u, span->lastChar);
         span++;
 
         ASSERT_NE(ResStringPool_span::END, span->name.index);
-        EXPECT_EQ(util::getString(test, span->name.index), u"i");
+        EXPECT_EQ(std::string("i"), util::getString(test, span->name.index));
+        EXPECT_EQ(StringPiece16(u"i"), util::getString16(test, span->name.index));
         EXPECT_EQ(2u, span->firstChar);
         EXPECT_EQ(3u, span->lastChar);
         span++;
diff --git a/tools/aapt2/ValueVisitor_test.cpp b/tools/aapt2/ValueVisitor_test.cpp
index 1624079..11eab33 100644
--- a/tools/aapt2/ValueVisitor_test.cpp
+++ b/tools/aapt2/ValueVisitor_test.cpp
@@ -14,13 +14,12 @@
  * limitations under the License.
  */
 
-#include <gtest/gtest.h>
-#include <string>
-
 #include "ResourceValues.h"
-#include "util/Util.h"
 #include "ValueVisitor.h"
-#include "test/Builders.h"
+#include "test/Test.h"
+#include "util/Util.h"
+
+#include <string>
 
 namespace aapt {
 
@@ -51,7 +50,7 @@
 };
 
 TEST(ValueVisitorTest, VisitsReference) {
-    Reference ref(ResourceName{u"android", ResourceType::kAttr, u"foo"});
+    Reference ref(ResourceName{"android", ResourceType::kAttr, "foo"});
     SingleReferenceVisitor visitor;
     ref.accept(&visitor);
 
@@ -60,8 +59,8 @@
 
 TEST(ValueVisitorTest, VisitsReferencesInStyle) {
     std::unique_ptr<Style> style = test::StyleBuilder()
-            .setParent(u"@android:style/foo")
-            .addItem(u"@android:attr/one", test::buildReference(u"@android:id/foo"))
+            .setParent("@android:style/foo")
+            .addItem("@android:attr/one", test::buildReference("@android:id/foo"))
             .build();
 
     StyleVisitor visitor;
@@ -74,11 +73,11 @@
 }
 
 TEST(ValueVisitorTest, ValueCast) {
-    std::unique_ptr<Reference> ref = test::buildReference(u"@android:color/white");
+    std::unique_ptr<Reference> ref = test::buildReference("@android:color/white");
     EXPECT_NE(valueCast<Reference>(ref.get()), nullptr);
 
     std::unique_ptr<Style> style = test::StyleBuilder()
-            .addItem(u"@android:attr/foo", test::buildReference(u"@android:color/black"))
+            .addItem("@android:attr/foo", test::buildReference("@android:color/black"))
             .build();
     EXPECT_NE(valueCast<Style>(style.get()), nullptr);
     EXPECT_EQ(valueCast<Reference>(style.get()), nullptr);
diff --git a/tools/aapt2/compile/Compile.cpp b/tools/aapt2/compile/Compile.cpp
index 5d11c40..39e4489 100644
--- a/tools/aapt2/compile/Compile.cpp
+++ b/tools/aapt2/compile/Compile.cpp
@@ -43,8 +43,8 @@
 
 struct ResourcePathData {
     Source source;
-    std::u16string resourceDir;
-    std::u16string name;
+    std::string resourceDir;
+    std::string name;
     std::string extension;
 
     // Original config str. We keep this because when we parse the config, we may add on
@@ -96,8 +96,8 @@
 
     return ResourcePathData{
             Source(path),
-            util::utf8ToUtf16(dirStr),
-            util::utf8ToUtf16(name),
+            dirStr.toString(),
+            name.toString(),
             extension.toString(),
             configStr.toString(),
             config
@@ -127,7 +127,7 @@
 }
 
 static bool isHidden(const StringPiece& filename) {
-    return util::stringStartsWith<char>(filename, ".");
+    return util::stringStartsWith(filename, ".");
 }
 
 /**
@@ -200,7 +200,7 @@
         parserOptions.errorOnPositionalArguments = !options.legacyMode;
 
         // If the filename includes donottranslate, then the default translatable is false.
-        parserOptions.translatable = pathData.name.find(u"donottranslate") == std::string::npos;
+        parserOptions.translatable = pathData.name.find("donottranslate") == std::string::npos;
 
         ResourceParser resParser(context->getDiagnostics(), &table, pathData.source,
                                  pathData.config, parserOptions);
@@ -440,8 +440,8 @@
        return nullptr;
     }
 
-    const std::u16string& getCompilationPackage() override {
-        static std::u16string empty;
+    const std::string& getCompilationPackage() override {
+        static std::string empty;
         return empty;
     }
 
@@ -530,7 +530,7 @@
             context.getDiagnostics()->note(DiagMessage(pathData.source) << "processing");
         }
 
-        if (pathData.resourceDir == u"values") {
+        if (pathData.resourceDir == "values") {
             // Overwrite the extension.
             pathData.extension = "arsc";
 
diff --git a/tools/aapt2/compile/IdAssigner.cpp b/tools/aapt2/compile/IdAssigner.cpp
index aa4a580..341c9b3 100644
--- a/tools/aapt2/compile/IdAssigner.cpp
+++ b/tools/aapt2/compile/IdAssigner.cpp
@@ -15,7 +15,6 @@
  */
 
 #include "ResourceTable.h"
-
 #include "compile/IdAssigner.h"
 #include "process/IResourceTableConsumer.h"
 #include "util/Util.h"
diff --git a/tools/aapt2/compile/IdAssigner_test.cpp b/tools/aapt2/compile/IdAssigner_test.cpp
index e25a17a..802e99a 100644
--- a/tools/aapt2/compile/IdAssigner_test.cpp
+++ b/tools/aapt2/compile/IdAssigner_test.cpp
@@ -27,10 +27,10 @@
 
 TEST(IdAssignerTest, AssignIds) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addSimple(u"@android:attr/foo")
-            .addSimple(u"@android:attr/bar")
-            .addSimple(u"@android:id/foo")
-            .setPackageId(u"android", 0x01)
+            .addSimple("@android:attr/foo")
+            .addSimple("@android:attr/bar")
+            .addSimple("@android:id/foo")
+            .setPackageId("android", 0x01)
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
@@ -42,12 +42,12 @@
 
 TEST(IdAssignerTest, AssignIdsWithReservedIds) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addSimple(u"@android:attr/foo", ResourceId(0x01040006))
-            .addSimple(u"@android:attr/bar")
-            .addSimple(u"@android:id/foo")
-            .addSimple(u"@app:id/biz")
-            .setPackageId(u"android", 0x01)
-            .setPackageId(u"app", 0x7f)
+            .addSimple("@android:attr/foo", ResourceId(0x01040006))
+            .addSimple("@android:attr/bar")
+            .addSimple("@android:id/foo")
+            .addSimple("@app:id/biz")
+            .setPackageId("android", 0x01)
+            .setPackageId("app", 0x7f)
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
@@ -59,10 +59,10 @@
 
 TEST(IdAssignerTest, FailWhenNonUniqueIdsAssigned) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addSimple(u"@android:attr/foo", ResourceId(0x01040006))
-            .addSimple(u"@android:attr/bar", ResourceId(0x01040006))
-            .setPackageId(u"android", 0x01)
-            .setPackageId(u"app", 0x7f)
+            .addSimple("@android:attr/foo", ResourceId(0x01040006))
+            .addSimple("@android:attr/bar", ResourceId(0x01040006))
+            .setPackageId("android", 0x01)
+            .setPackageId("app", 0x7f)
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
diff --git a/tools/aapt2/compile/Png.cpp b/tools/aapt2/compile/Png.cpp
index bbf7f41..055d8b5 100644
--- a/tools/aapt2/compile/Png.cpp
+++ b/tools/aapt2/compile/Png.cpp
@@ -1234,7 +1234,7 @@
         goto bail;
     }
 
-    if (util::stringEndsWith<char>(source.path, ".9.png")) {
+    if (util::stringEndsWith(source.path, ".9.png")) {
         std::string errorMsg;
         if (!do9Patch(&pngInfo, &errorMsg)) {
             mDiag->error(DiagMessage() << errorMsg);
diff --git a/tools/aapt2/compile/PseudolocaleGenerator.cpp b/tools/aapt2/compile/PseudolocaleGenerator.cpp
index d080e16..732101f 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator.cpp
@@ -29,7 +29,7 @@
                                                          StringPool* pool) {
     Pseudolocalizer localizer(method);
 
-    const StringPiece16 originalText = *string->value->str;
+    const StringPiece originalText = *string->value->str;
 
     StyleString localized;
 
@@ -147,7 +147,7 @@
     }
 
     void visit(String* string) override {
-        std::u16string result = mLocalizer.start() + mLocalizer.text(*string->value) +
+        std::string result = mLocalizer.start() + mLocalizer.text(*string->value) +
                 mLocalizer.end();
         std::unique_ptr<String> localized = util::make_unique<String>(mPool->makeRef(result));
         localized->setSource(string->getSource());
diff --git a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
index 4cb6ea2..1816abc 100644
--- a/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
+++ b/tools/aapt2/compile/PseudolocaleGenerator_test.cpp
@@ -15,21 +15,18 @@
  */
 
 #include "compile/PseudolocaleGenerator.h"
-#include "test/Builders.h"
-#include "test/Common.h"
-#include "test/Context.h"
+#include "test/Test.h"
 #include "util/Util.h"
 
 #include <androidfw/ResourceTypes.h>
-#include <gtest/gtest.h>
 
 namespace aapt {
 
 TEST(PseudolocaleGeneratorTest, PseudolocalizeStyledString) {
     StringPool pool;
     StyleString originalStyle;
-    originalStyle.str = u"Hello world!";
-    originalStyle.spans = { Span{ u"b", 2, 3 }, Span{ u"b", 6, 7 }, Span{ u"i", 1, 10 } };
+    originalStyle.str = "Hello world!";
+    originalStyle.spans = { Span{ "b", 2, 3 }, Span{ "b", 6, 7 }, Span{ "i", 1, 10 } };
 
     std::unique_ptr<StyledString> newString = pseudolocalizeStyledString(
             util::make_unique<StyledString>(pool.makeRef(originalStyle)).get(),
@@ -38,51 +35,51 @@
     EXPECT_EQ(originalStyle.str, *newString->value->str);
     ASSERT_EQ(originalStyle.spans.size(), newString->value->spans.size());
 
-    EXPECT_EQ(2u, newString->value->spans[0].firstChar);
-    EXPECT_EQ(3u, newString->value->spans[0].lastChar);
-    EXPECT_EQ(std::u16string(u"b"), *newString->value->spans[0].name);
+    EXPECT_EQ(std::string("He").size(), newString->value->spans[0].firstChar);
+    EXPECT_EQ(std::string("Hel").size(), newString->value->spans[0].lastChar);
+    EXPECT_EQ(std::string("b"), *newString->value->spans[0].name);
 
-    EXPECT_EQ(6u, newString->value->spans[1].firstChar);
-    EXPECT_EQ(7u, newString->value->spans[1].lastChar);
-    EXPECT_EQ(std::u16string(u"b"), *newString->value->spans[1].name);
+    EXPECT_EQ(std::string("Hello ").size(), newString->value->spans[1].firstChar);
+    EXPECT_EQ(std::string("Hello w").size(), newString->value->spans[1].lastChar);
+    EXPECT_EQ(std::string("b"), *newString->value->spans[1].name);
 
-    EXPECT_EQ(1u, newString->value->spans[2].firstChar);
-    EXPECT_EQ(10u, newString->value->spans[2].lastChar);
-    EXPECT_EQ(std::u16string(u"i"), *newString->value->spans[2].name);
+    EXPECT_EQ(std::string("H").size(), newString->value->spans[2].firstChar);
+    EXPECT_EQ(std::string("Hello worl").size(), newString->value->spans[2].lastChar);
+    EXPECT_EQ(std::string("i"), *newString->value->spans[2].name);
 
-    originalStyle.spans.push_back(Span{ u"em", 0, 11u });
+    originalStyle.spans.push_back(Span{ "em", 0, 11u });
 
     newString = pseudolocalizeStyledString(
             util::make_unique<StyledString>(pool.makeRef(originalStyle)).get(),
             Pseudolocalizer::Method::kAccent, &pool);
 
-    EXPECT_EQ(std::u16string(u"[Ĥéļļö ŵöŕļð¡ one two]"), *newString->value->str);
+    EXPECT_EQ(std::string("[Ĥéļļö ŵöŕļð¡ one two]"), *newString->value->str);
     ASSERT_EQ(originalStyle.spans.size(), newString->value->spans.size());
 
-    EXPECT_EQ(3u, newString->value->spans[0].firstChar);
-    EXPECT_EQ(4u, newString->value->spans[0].lastChar);
+    EXPECT_EQ(std::string("[Ĥé").size(), newString->value->spans[0].firstChar);
+    EXPECT_EQ(std::string("[Ĥéļ").size(), newString->value->spans[0].lastChar);
 
-    EXPECT_EQ(7u, newString->value->spans[1].firstChar);
-    EXPECT_EQ(8u, newString->value->spans[1].lastChar);
+    EXPECT_EQ(std::string("[Ĥéļļö ").size(), newString->value->spans[1].firstChar);
+    EXPECT_EQ(std::string("[Ĥéļļö ŵ").size(), newString->value->spans[1].lastChar);
 
-    EXPECT_EQ(2u, newString->value->spans[2].firstChar);
-    EXPECT_EQ(11u, newString->value->spans[2].lastChar);
+    EXPECT_EQ(std::string("[Ĥ").size(), newString->value->spans[2].firstChar);
+    EXPECT_EQ(std::string("[Ĥéļļö ŵöŕļ").size(), newString->value->spans[2].lastChar);
 
-    EXPECT_EQ(1u, newString->value->spans[3].firstChar);
-    EXPECT_EQ(12u, newString->value->spans[3].lastChar);
+    EXPECT_EQ(std::string("[").size(), newString->value->spans[3].firstChar);
+    EXPECT_EQ(std::string("[Ĥéļļö ŵöŕļð").size(), newString->value->spans[3].lastChar);
 }
 
 TEST(PseudolocaleGeneratorTest, PseudolocalizeOnlyDefaultConfigs) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addString(u"@android:string/one", u"one")
-            .addString(u"@android:string/two", ResourceId{}, test::parseConfigOrDie("en"), u"two")
-            .addString(u"@android:string/three", u"three")
-            .addString(u"@android:string/three", ResourceId{}, test::parseConfigOrDie("en-rXA"),
-                       u"three")
-            .addString(u"@android:string/four", u"four")
+            .addString("@android:string/one", "one")
+            .addString("@android:string/two", ResourceId{}, test::parseConfigOrDie("en"), "two")
+            .addString("@android:string/three", "three")
+            .addString("@android:string/three", ResourceId{}, test::parseConfigOrDie("en-rXA"),
+                       "three")
+            .addString("@android:string/four", "four")
             .build();
 
-    String* val = test::getValue<String>(table.get(), u"@android:string/four");
+    String* val = test::getValue<String>(table.get(), "@android:string/four");
     val->setTranslateable(false);
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
@@ -90,31 +87,31 @@
     ASSERT_TRUE(generator.consume(context.get(), table.get()));
 
     // Normal pseudolocalization should take place.
-    ASSERT_NE(nullptr, test::getValueForConfig<String>(table.get(), u"@android:string/one",
+    ASSERT_NE(nullptr, test::getValueForConfig<String>(table.get(), "@android:string/one",
                                                        test::parseConfigOrDie("en-rXA")));
-    ASSERT_NE(nullptr, test::getValueForConfig<String>(table.get(), u"@android:string/one",
+    ASSERT_NE(nullptr, test::getValueForConfig<String>(table.get(), "@android:string/one",
                                                        test::parseConfigOrDie("ar-rXB")));
 
     // No default config for android:string/two, so no pseudlocales should exist.
-    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), u"@android:string/two",
+    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), "@android:string/two",
                                                        test::parseConfigOrDie("en-rXA")));
-    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), u"@android:string/two",
+    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), "@android:string/two",
                                                        test::parseConfigOrDie("ar-rXB")));
 
 
     // Check that we didn't override manual pseudolocalization.
-    val = test::getValueForConfig<String>(table.get(), u"@android:string/three",
+    val = test::getValueForConfig<String>(table.get(), "@android:string/three",
                                           test::parseConfigOrDie("en-rXA"));
     ASSERT_NE(nullptr, val);
-    EXPECT_EQ(std::u16string(u"three"), *val->value);
+    EXPECT_EQ(std::string("three"), *val->value);
 
-    ASSERT_NE(nullptr, test::getValueForConfig<String>(table.get(), u"@android:string/three",
+    ASSERT_NE(nullptr, test::getValueForConfig<String>(table.get(), "@android:string/three",
                                                        test::parseConfigOrDie("ar-rXB")));
 
     // Check that four's translateable marker was honored.
-    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), u"@android:string/four",
+    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), "@android:string/four",
                                                        test::parseConfigOrDie("en-rXA")));
-    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), u"@android:string/four",
+    ASSERT_EQ(nullptr, test::getValueForConfig<String>(table.get(), "@android:string/four",
                                                        test::parseConfigOrDie("ar-rXB")));
 
 }
diff --git a/tools/aapt2/compile/Pseudolocalizer.cpp b/tools/aapt2/compile/Pseudolocalizer.cpp
index 767d746..90d0d85 100644
--- a/tools/aapt2/compile/Pseudolocalizer.cpp
+++ b/tools/aapt2/compile/Pseudolocalizer.cpp
@@ -20,41 +20,41 @@
 namespace aapt {
 
 // String basis to generate expansion
-static const std::u16string k_expansion_string = u"one two three "
+static const std::string k_expansion_string = "one two three "
         "four five six seven eight nine ten eleven twelve thirteen "
         "fourteen fiveteen sixteen seventeen nineteen twenty";
 
 // Special unicode characters to override directionality of the words
-static const std::u16string k_rlm = u"\u200f";
-static const std::u16string k_rlo = u"\u202e";
-static const std::u16string k_pdf = u"\u202c";
+static const std::string k_rlm = "\u200f";
+static const std::string k_rlo = "\u202e";
+static const std::string k_pdf = "\u202c";
 
 // Placeholder marks
-static const std::u16string k_placeholder_open = u"\u00bb";
-static const std::u16string k_placeholder_close = u"\u00ab";
+static const std::string k_placeholder_open = "\u00bb";
+static const std::string k_placeholder_close = "\u00ab";
 
-static const char16_t k_arg_start = u'{';
-static const char16_t k_arg_end = u'}';
+static const char k_arg_start = '{';
+static const char k_arg_end = '}';
 
 class PseudoMethodNone : public PseudoMethodImpl {
 public:
-    std::u16string text(const StringPiece16& text) override { return text.toString(); }
-    std::u16string placeholder(const StringPiece16& text) override { return text.toString(); }
+    std::string text(const StringPiece& text) override { return text.toString(); }
+    std::string placeholder(const StringPiece& text) override { return text.toString(); }
 };
 
 class PseudoMethodBidi : public PseudoMethodImpl {
 public:
-    std::u16string text(const StringPiece16& text) override;
-    std::u16string placeholder(const StringPiece16& text) override;
+    std::string text(const StringPiece& text) override;
+    std::string placeholder(const StringPiece& text) override;
 };
 
 class PseudoMethodAccent : public PseudoMethodImpl {
 public:
     PseudoMethodAccent() : mDepth(0), mWordCount(0), mLength(0) {}
-    std::u16string start() override;
-    std::u16string end() override;
-    std::u16string text(const StringPiece16& text) override;
-    std::u16string placeholder(const StringPiece16& text) override;
+    std::string start() override;
+    std::string end() override;
+    std::string text(const StringPiece& text) override;
+    std::string placeholder(const StringPiece& text) override;
 private:
     size_t mDepth;
     size_t mWordCount;
@@ -79,12 +79,12 @@
     }
 }
 
-std::u16string Pseudolocalizer::text(const StringPiece16& text) {
-    std::u16string out;
+std::string Pseudolocalizer::text(const StringPiece& text) {
+    std::string out;
     size_t depth = mLastDepth;
     size_t lastpos, pos;
     const size_t length = text.size();
-    const char16_t* str = text.data();
+    const char* str = text.data();
     bool escaped = false;
     for (lastpos = pos = 0; pos < length; pos++) {
         char16_t c = str[pos];
@@ -111,7 +111,7 @@
             }
             size_t size = nextpos - lastpos;
             if (size) {
-                std::u16string chunk = text.substr(lastpos, size).toString();
+                std::string chunk = text.substr(lastpos, size).toString();
                 if (pseudo) {
                     chunk = mImpl->text(chunk);
                 } else if (str[lastpos] == k_arg_start && str[nextpos - 1] == k_arg_end) {
@@ -131,67 +131,67 @@
     return out;
 }
 
-static const char16_t* pseudolocalizeChar(const char16_t c) {
+static const char* pseudolocalizeChar(const char c) {
     switch (c) {
-        case 'a':   return u"\u00e5";
-        case 'b':   return u"\u0253";
-        case 'c':   return u"\u00e7";
-        case 'd':   return u"\u00f0";
-        case 'e':   return u"\u00e9";
-        case 'f':   return u"\u0192";
-        case 'g':   return u"\u011d";
-        case 'h':   return u"\u0125";
-        case 'i':   return u"\u00ee";
-        case 'j':   return u"\u0135";
-        case 'k':   return u"\u0137";
-        case 'l':   return u"\u013c";
-        case 'm':   return u"\u1e3f";
-        case 'n':   return u"\u00f1";
-        case 'o':   return u"\u00f6";
-        case 'p':   return u"\u00fe";
-        case 'q':   return u"\u0051";
-        case 'r':   return u"\u0155";
-        case 's':   return u"\u0161";
-        case 't':   return u"\u0163";
-        case 'u':   return u"\u00fb";
-        case 'v':   return u"\u0056";
-        case 'w':   return u"\u0175";
-        case 'x':   return u"\u0445";
-        case 'y':   return u"\u00fd";
-        case 'z':   return u"\u017e";
-        case 'A':   return u"\u00c5";
-        case 'B':   return u"\u03b2";
-        case 'C':   return u"\u00c7";
-        case 'D':   return u"\u00d0";
-        case 'E':   return u"\u00c9";
-        case 'G':   return u"\u011c";
-        case 'H':   return u"\u0124";
-        case 'I':   return u"\u00ce";
-        case 'J':   return u"\u0134";
-        case 'K':   return u"\u0136";
-        case 'L':   return u"\u013b";
-        case 'M':   return u"\u1e3e";
-        case 'N':   return u"\u00d1";
-        case 'O':   return u"\u00d6";
-        case 'P':   return u"\u00de";
-        case 'Q':   return u"\u0071";
-        case 'R':   return u"\u0154";
-        case 'S':   return u"\u0160";
-        case 'T':   return u"\u0162";
-        case 'U':   return u"\u00db";
-        case 'V':   return u"\u03bd";
-        case 'W':   return u"\u0174";
-        case 'X':   return u"\u00d7";
-        case 'Y':   return u"\u00dd";
-        case 'Z':   return u"\u017d";
-        case '!':   return u"\u00a1";
-        case '?':   return u"\u00bf";
-        case '$':   return u"\u20ac";
-        default:    return NULL;
+        case 'a':   return "\u00e5";
+        case 'b':   return "\u0253";
+        case 'c':   return "\u00e7";
+        case 'd':   return "\u00f0";
+        case 'e':   return "\u00e9";
+        case 'f':   return "\u0192";
+        case 'g':   return "\u011d";
+        case 'h':   return "\u0125";
+        case 'i':   return "\u00ee";
+        case 'j':   return "\u0135";
+        case 'k':   return "\u0137";
+        case 'l':   return "\u013c";
+        case 'm':   return "\u1e3f";
+        case 'n':   return "\u00f1";
+        case 'o':   return "\u00f6";
+        case 'p':   return "\u00fe";
+        case 'q':   return "\u0051";
+        case 'r':   return "\u0155";
+        case 's':   return "\u0161";
+        case 't':   return "\u0163";
+        case 'u':   return "\u00fb";
+        case 'v':   return "\u0056";
+        case 'w':   return "\u0175";
+        case 'x':   return "\u0445";
+        case 'y':   return "\u00fd";
+        case 'z':   return "\u017e";
+        case 'A':   return "\u00c5";
+        case 'B':   return "\u03b2";
+        case 'C':   return "\u00c7";
+        case 'D':   return "\u00d0";
+        case 'E':   return "\u00c9";
+        case 'G':   return "\u011c";
+        case 'H':   return "\u0124";
+        case 'I':   return "\u00ce";
+        case 'J':   return "\u0134";
+        case 'K':   return "\u0136";
+        case 'L':   return "\u013b";
+        case 'M':   return "\u1e3e";
+        case 'N':   return "\u00d1";
+        case 'O':   return "\u00d6";
+        case 'P':   return "\u00de";
+        case 'Q':   return "\u0071";
+        case 'R':   return "\u0154";
+        case 'S':   return "\u0160";
+        case 'T':   return "\u0162";
+        case 'U':   return "\u00db";
+        case 'V':   return "\u03bd";
+        case 'W':   return "\u0174";
+        case 'X':   return "\u00d7";
+        case 'Y':   return "\u00dd";
+        case 'Z':   return "\u017d";
+        case '!':   return "\u00a1";
+        case '?':   return "\u00bf";
+        case '$':   return "\u20ac";
+        default:    return nullptr;
     }
 }
 
-static bool isPossibleNormalPlaceholderEnd(const char16_t c) {
+static bool isPossibleNormalPlaceholderEnd(const char c) {
     switch (c) {
         case 's': return true;
         case 'S': return true;
@@ -218,11 +218,11 @@
     }
 }
 
-static std::u16string pseudoGenerateExpansion(const unsigned int length) {
-    std::u16string result = k_expansion_string;
-    const char16_t* s = result.data();
+static std::string pseudoGenerateExpansion(const unsigned int length) {
+    std::string result = k_expansion_string;
+    const char* s = result.data();
     if (result.size() < length) {
-        result += u" ";
+        result += " ";
         result += pseudoGenerateExpansion(length - result.size());
     } else {
         int ext = 0;
@@ -238,26 +238,26 @@
     return result;
 }
 
-std::u16string PseudoMethodAccent::start() {
-    std::u16string result;
+std::string PseudoMethodAccent::start() {
+    std::string result;
     if (mDepth == 0) {
-        result = u"[";
+        result = "[";
     }
     mWordCount = mLength = 0;
     mDepth++;
     return result;
 }
 
-std::u16string PseudoMethodAccent::end() {
-    std::u16string result;
+std::string PseudoMethodAccent::end() {
+    std::string result;
     if (mLength) {
-        result += u" ";
+        result += " ";
         result += pseudoGenerateExpansion(mWordCount > 3 ? mLength : mLength / 2);
     }
     mWordCount = mLength = 0;
     mDepth--;
     if (mDepth == 0) {
-        result += u"]";
+        result += "]";
     }
     return result;
 }
@@ -267,17 +267,17 @@
  *
  * Note: This leaves placeholder syntax untouched.
  */
-std::u16string PseudoMethodAccent::text(const StringPiece16& source)
+std::string PseudoMethodAccent::text(const StringPiece& source)
 {
-    const char16_t* s = source.data();
-    std::u16string result;
+    const char* s = source.data();
+    std::string result;
     const size_t I = source.size();
     bool lastspace = true;
     for (size_t i = 0; i < I; i++) {
-        char16_t c = s[i];
+        char c = s[i];
         if (c == '%') {
             // Placeholder syntax, no need to pseudolocalize
-            std::u16string chunk;
+            std::string chunk;
             bool end = false;
             chunk.append(&c, 1);
             while (!end && i + 1 < I) {
@@ -300,7 +300,7 @@
             bool tag_closed = false;
             while (!tag_closed && i < I) {
                 if (c == '&') {
-                    std::u16string escapeText;
+                    std::string escapeText;
                     escapeText.append(&c, 1);
                     bool end = false;
                     size_t htmlCodePos = i;
@@ -322,7 +322,7 @@
                         }
                     }
                     result += escapeText;
-                    if (escapeText != u"&lt;") {
+                    if (escapeText != "&lt;") {
                         tag_closed = true;
                     }
                     continue;
@@ -338,11 +338,11 @@
             }
         } else {
             // This is a pure text that should be pseudolocalized
-            const char16_t* p = pseudolocalizeChar(c);
+            const char* p = pseudolocalizeChar(c);
             if (p != nullptr) {
                 result += p;
             } else {
-                bool space = util::isspace16(c);
+                bool space = isspace(c);
                 if (lastspace && !space) {
                     mWordCount++;
                 }
@@ -356,19 +356,19 @@
     return result;
 }
 
-std::u16string PseudoMethodAccent::placeholder(const StringPiece16& source) {
+std::string PseudoMethodAccent::placeholder(const StringPiece& source) {
     // Surround a placeholder with brackets
     return k_placeholder_open + source.toString() + k_placeholder_close;
 }
 
-std::u16string PseudoMethodBidi::text(const StringPiece16& source) {
-    const char16_t* s = source.data();
-    std::u16string result;
+std::string PseudoMethodBidi::text(const StringPiece& source) {
+    const char* s = source.data();
+    std::string result;
     bool lastspace = true;
     bool space = true;
     for (size_t i = 0; i < source.size(); i++) {
-        char16_t c = s[i];
-        space = util::isspace16(c);
+        char c = s[i];
+        space = isspace(c);
         if (lastspace && !space) {
             // Word start
             result += k_rlm + k_rlo;
@@ -386,7 +386,7 @@
     return result;
 }
 
-std::u16string PseudoMethodBidi::placeholder(const StringPiece16& source) {
+std::string PseudoMethodBidi::placeholder(const StringPiece& source) {
     // Surround a placeholder with directionality change sequence
     return k_rlm + k_rlo + source.toString() + k_pdf + k_rlm;
 }
diff --git a/tools/aapt2/compile/Pseudolocalizer.h b/tools/aapt2/compile/Pseudolocalizer.h
index 8818c17..7db88de 100644
--- a/tools/aapt2/compile/Pseudolocalizer.h
+++ b/tools/aapt2/compile/Pseudolocalizer.h
@@ -29,10 +29,10 @@
 class PseudoMethodImpl {
 public:
     virtual ~PseudoMethodImpl() {}
-    virtual std::u16string start() { return {}; }
-    virtual std::u16string end() { return {}; }
-    virtual std::u16string text(const StringPiece16& text) = 0;
-    virtual std::u16string placeholder(const StringPiece16& text) = 0;
+    virtual std::string start() { return {}; }
+    virtual std::string end() { return {}; }
+    virtual std::string text(const StringPiece& text) = 0;
+    virtual std::string placeholder(const StringPiece& text) = 0;
 };
 
 class Pseudolocalizer {
@@ -45,9 +45,9 @@
 
     Pseudolocalizer(Method method);
     void setMethod(Method method);
-    std::u16string start() { return mImpl->start(); }
-    std::u16string end() { return mImpl->end(); }
-    std::u16string text(const StringPiece16& text);
+    std::string start() { return mImpl->start(); }
+    std::string end() { return mImpl->end(); }
+    std::string text(const StringPiece& text);
 private:
     std::unique_ptr<PseudoMethodImpl> mImpl;
     size_t mLastDepth;
diff --git a/tools/aapt2/compile/Pseudolocalizer_test.cpp b/tools/aapt2/compile/Pseudolocalizer_test.cpp
index 36c8896..c33e152 100644
--- a/tools/aapt2/compile/Pseudolocalizer_test.cpp
+++ b/tools/aapt2/compile/Pseudolocalizer_test.cpp
@@ -28,9 +28,8 @@
 static ::testing::AssertionResult simpleHelper(const char* input, const char* expected,
                                                Pseudolocalizer::Method method) {
     Pseudolocalizer pseudo(method);
-    std::string result = util::utf16ToUtf8(
-            pseudo.start() + pseudo.text(util::utf8ToUtf16(input)) + pseudo.end());
-    if (StringPiece(expected) != result) {
+    std::string result = pseudo.start() + pseudo.text(input) + pseudo.end();
+    if (result != expected) {
         return ::testing::AssertionFailure() << expected << " != " << result;
     }
     return ::testing::AssertionSuccess();
@@ -40,12 +39,9 @@
                                                  const char* expected,
                                                  Pseudolocalizer::Method method) {
     Pseudolocalizer pseudo(method);
-    std::string result = util::utf16ToUtf8(pseudo.start() +
-                                           pseudo.text(util::utf8ToUtf16(in1)) +
-                                           pseudo.text(util::utf8ToUtf16(in2)) +
-                                           pseudo.text(util::utf8ToUtf16(in3)) +
-                                           pseudo.end());
-    if (StringPiece(expected) != result) {
+    std::string result = pseudo.start() + pseudo.text(in1) + pseudo.text(in2) + pseudo.text(in3) +
+            pseudo.end();
+    if (result != expected) {
         return ::testing::AssertionFailure() << expected << " != " << result;
     }
     return ::testing::AssertionSuccess();
@@ -218,10 +214,10 @@
 
 TEST(PseudolocalizerTest, RedefineMethod) {
     Pseudolocalizer pseudo(Pseudolocalizer::Method::kAccent);
-    std::u16string result = pseudo.text(u"Hello, ");
+    std::string result = pseudo.text("Hello, ");
     pseudo.setMethod(Pseudolocalizer::Method::kNone);
-    result += pseudo.text(u"world!");
-    ASSERT_EQ(StringPiece("Ĥéļļö, world!"), util::utf16ToUtf8(result));
+    result += pseudo.text("world!");
+    ASSERT_EQ(StringPiece("Ĥéļļö, world!"), result);
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/compile/XmlIdCollector_test.cpp b/tools/aapt2/compile/XmlIdCollector_test.cpp
index a37ea86..ea1ced3 100644
--- a/tools/aapt2/compile/XmlIdCollector_test.cpp
+++ b/tools/aapt2/compile/XmlIdCollector_test.cpp
@@ -38,13 +38,13 @@
     ASSERT_TRUE(collector.consume(context.get(), doc.get()));
 
     EXPECT_EQ(1, std::count(doc->file.exportedSymbols.begin(), doc->file.exportedSymbols.end(),
-                             SourcedResourceName{ test::parseNameOrDie(u"@id/foo"), 3u }));
+                             SourcedResourceName{ test::parseNameOrDie("@id/foo"), 3u }));
 
     EXPECT_EQ(1, std::count(doc->file.exportedSymbols.begin(), doc->file.exportedSymbols.end(),
-                             SourcedResourceName{ test::parseNameOrDie(u"@id/bar"), 3u }));
+                             SourcedResourceName{ test::parseNameOrDie("@id/bar"), 3u }));
 
     EXPECT_EQ(1, std::count(doc->file.exportedSymbols.begin(), doc->file.exportedSymbols.end(),
-                             SourcedResourceName{ test::parseNameOrDie(u"@id/car"), 6u }));
+                             SourcedResourceName{ test::parseNameOrDie("@id/car"), 6u }));
 }
 
 TEST(XmlIdCollectorTest, DontCollectNonIds) {
diff --git a/tools/aapt2/diff/Diff.cpp b/tools/aapt2/diff/Diff.cpp
index 1ff6ef6..9b1f057 100644
--- a/tools/aapt2/diff/Diff.cpp
+++ b/tools/aapt2/diff/Diff.cpp
@@ -28,7 +28,7 @@
 
 class DiffContext : public IAaptContext {
 public:
-    const std::u16string& getCompilationPackage() override {
+    const std::string& getCompilationPackage() override {
         return mEmpty;
     }
 
@@ -57,7 +57,7 @@
     }
 
 private:
-    std::u16string mEmpty;
+    std::string mEmpty;
     StdErrDiagnostics mDiagnostics;
     NameMangler mNameMangler = NameMangler(NameManglerPolicy{});
     SymbolTable mSymbolTable;
diff --git a/tools/aapt2/dump/Dump.cpp b/tools/aapt2/dump/Dump.cpp
index 8f0dd3a..88c6f64 100644
--- a/tools/aapt2/dump/Dump.cpp
+++ b/tools/aapt2/dump/Dump.cpp
@@ -137,8 +137,8 @@
         return nullptr;
     }
 
-    const std::u16string& getCompilationPackage() override {
-        static std::u16string empty;
+    const std::string& getCompilationPackage() override {
+        static std::string empty;
         return empty;
     }
 
diff --git a/tools/aapt2/flatten/TableFlattener.cpp b/tools/aapt2/flatten/TableFlattener.cpp
index 28a7928..5fbb0fe 100644
--- a/tools/aapt2/flatten/TableFlattener.cpp
+++ b/tools/aapt2/flatten/TableFlattener.cpp
@@ -25,6 +25,7 @@
 
 #include <android-base/macros.h>
 #include <algorithm>
+#include <sstream>
 #include <type_traits>
 #include <numeric>
 
@@ -231,7 +232,8 @@
         }
 
         // Copy the package name in device endianness.
-        strcpy16_htod(pkgHeader->name, arraysize(pkgHeader->name), mPackage->name);
+        strcpy16_htod(pkgHeader->name, arraysize(pkgHeader->name),
+                      util::utf8ToUtf16(mPackage->name));
 
         // Serialize the types. We do this now so that our type and key strings
         // are populated. We write those first.
@@ -423,9 +425,9 @@
             // If there is a gap in the type IDs, fill in the StringPool
             // with empty values until we reach the ID we expect.
             while (type->id.value() > expectedTypeId) {
-                std::u16string typeName(u"?");
-                typeName += expectedTypeId;
-                mTypePool.makeRef(typeName);
+                std::stringstream typeName;
+                typeName << "?" << expectedTypeId;
+                mTypePool.makeRef(typeName.str());
                 expectedTypeId++;
             }
             expectedTypeId++;
diff --git a/tools/aapt2/flatten/TableFlattener_test.cpp b/tools/aapt2/flatten/TableFlattener_test.cpp
index d0f831e..e720e7e 100644
--- a/tools/aapt2/flatten/TableFlattener_test.cpp
+++ b/tools/aapt2/flatten/TableFlattener_test.cpp
@@ -14,6 +14,7 @@
  * limitations under the License.
  */
 
+#include "ResourceUtils.h"
 #include "flatten/TableFlattener.h"
 #include "test/Test.h"
 #include "unflatten/BinaryResourceParser.h"
@@ -27,7 +28,7 @@
 public:
     void SetUp() override {
         mContext = test::ContextBuilder()
-                .setCompilationPackage(u"com.app.test")
+                .setCompilationPackage("com.app.test")
                 .setPackageId(0x7f)
                 .build();
     }
@@ -62,7 +63,7 @@
     }
 
     ::testing::AssertionResult exists(ResTable* table,
-                                      const StringPiece16& expectedName,
+                                      const StringPiece& expectedName,
                                       const ResourceId expectedId,
                                       const ConfigDescription& expectedConfig,
                                       const uint8_t expectedDataType, const uint32_t expectedData,
@@ -104,25 +105,16 @@
             return ::testing::AssertionFailure() << "failed to find resource name";
         }
 
-        StringPiece16 package16(actualName.package, actualName.packageLen);
-        if (package16 != expectedResName.package) {
+        Maybe<ResourceName> resName = ResourceUtils::toResourceName(actualName);
+        if (!resName) {
             return ::testing::AssertionFailure()
-                    << "expected package '" << expectedResName.package << "' but got '"
-                    << package16 << "'";
-        }
-
-        StringPiece16 type16(actualName.type, actualName.typeLen);
-        if (type16 != toString(expectedResName.type)) {
-            return ::testing::AssertionFailure()
-                    << "expected type '" << expectedResName.type
-                    << "' but got '" << type16 << "'";
-        }
-
-        StringPiece16 name16(actualName.name, actualName.nameLen);
-        if (name16 != expectedResName.entry) {
-            return ::testing::AssertionFailure()
-                    << "expected name '" << expectedResName.entry
-                    << "' but got '" << name16 << "'";
+                    << "expected name '" << expectedResName << "' but got '"
+                    << StringPiece16(actualName.package, actualName.packageLen)
+                    << ":"
+                    << StringPiece16(actualName.type, actualName.typeLen)
+                    << "/"
+                    << StringPiece16(actualName.name, actualName.nameLen)
+                    << "'";
         }
 
         if (expectedConfig != config) {
@@ -139,67 +131,67 @@
 
 TEST_F(TableFlattenerTest, FlattenFullyLinkedTable) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addSimple(u"@com.app.test:id/one", ResourceId(0x7f020000))
-            .addSimple(u"@com.app.test:id/two", ResourceId(0x7f020001))
-            .addValue(u"@com.app.test:id/three", ResourceId(0x7f020002),
-                      test::buildReference(u"@com.app.test:id/one", ResourceId(0x7f020000)))
-            .addValue(u"@com.app.test:integer/one", ResourceId(0x7f030000),
+            .setPackageId("com.app.test", 0x7f)
+            .addSimple("@com.app.test:id/one", ResourceId(0x7f020000))
+            .addSimple("@com.app.test:id/two", ResourceId(0x7f020001))
+            .addValue("@com.app.test:id/three", ResourceId(0x7f020002),
+                      test::buildReference("@com.app.test:id/one", ResourceId(0x7f020000)))
+            .addValue("@com.app.test:integer/one", ResourceId(0x7f030000),
                       util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 1u))
-            .addValue(u"@com.app.test:integer/one", test::parseConfigOrDie("v1"),
+            .addValue("@com.app.test:integer/one", test::parseConfigOrDie("v1"),
                       ResourceId(0x7f030000),
                       util::make_unique<BinaryPrimitive>(uint8_t(Res_value::TYPE_INT_DEC), 2u))
-            .addString(u"@com.app.test:string/test", ResourceId(0x7f040000), u"foo")
-            .addString(u"@com.app.test:layout/bar", ResourceId(0x7f050000), u"res/layout/bar.xml")
+            .addString("@com.app.test:string/test", ResourceId(0x7f040000), "foo")
+            .addString("@com.app.test:layout/bar", ResourceId(0x7f050000), "res/layout/bar.xml")
             .build();
 
     ResTable resTable;
     ASSERT_TRUE(flatten(table.get(), &resTable));
 
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:id/one", ResourceId(0x7f020000), {},
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:id/one", ResourceId(0x7f020000), {},
                        Res_value::TYPE_INT_BOOLEAN, 0u, 0u));
 
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:id/two", ResourceId(0x7f020001), {},
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:id/two", ResourceId(0x7f020001), {},
                        Res_value::TYPE_INT_BOOLEAN, 0u, 0u));
 
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:id/three", ResourceId(0x7f020002), {},
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:id/three", ResourceId(0x7f020002), {},
                        Res_value::TYPE_REFERENCE, 0x7f020000u, 0u));
 
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:integer/one", ResourceId(0x7f030000),
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:integer/one", ResourceId(0x7f030000),
                        {}, Res_value::TYPE_INT_DEC, 1u,
                        ResTable_config::CONFIG_VERSION));
 
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:integer/one", ResourceId(0x7f030000),
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:integer/one", ResourceId(0x7f030000),
                        test::parseConfigOrDie("v1"), Res_value::TYPE_INT_DEC, 2u,
                        ResTable_config::CONFIG_VERSION));
 
-    StringPiece16 fooStr = u"foo";
+    std::u16string fooStr = u"foo";
     ssize_t idx = resTable.getTableStringBlock(0)->indexOfString(fooStr.data(), fooStr.size());
     ASSERT_GE(idx, 0);
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:string/test", ResourceId(0x7f040000),
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:string/test", ResourceId(0x7f040000),
                        {}, Res_value::TYPE_STRING, (uint32_t) idx, 0u));
 
-    StringPiece16 barPath = u"res/layout/bar.xml";
+    std::u16string barPath = u"res/layout/bar.xml";
     idx = resTable.getTableStringBlock(0)->indexOfString(barPath.data(), barPath.size());
     ASSERT_GE(idx, 0);
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:layout/bar", ResourceId(0x7f050000), {},
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:layout/bar", ResourceId(0x7f050000), {},
                        Res_value::TYPE_STRING, (uint32_t) idx, 0u));
 }
 
 TEST_F(TableFlattenerTest, FlattenEntriesWithGapsInIds) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addSimple(u"@com.app.test:id/one", ResourceId(0x7f020001))
-            .addSimple(u"@com.app.test:id/three", ResourceId(0x7f020003))
+            .setPackageId("com.app.test", 0x7f)
+            .addSimple("@com.app.test:id/one", ResourceId(0x7f020001))
+            .addSimple("@com.app.test:id/three", ResourceId(0x7f020003))
             .build();
 
     ResTable resTable;
     ASSERT_TRUE(flatten(table.get(), &resTable));
 
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:id/one", ResourceId(0x7f020001), {},
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:id/one", ResourceId(0x7f020001), {},
                        Res_value::TYPE_INT_BOOLEAN, 0u, 0u));
-    EXPECT_TRUE(exists(&resTable, u"@com.app.test:id/three", ResourceId(0x7f020003), {},
-                           Res_value::TYPE_INT_BOOLEAN, 0u, 0u));
+    EXPECT_TRUE(exists(&resTable, "@com.app.test:id/three", ResourceId(0x7f020003), {},
+                       Res_value::TYPE_INT_BOOLEAN, 0u, 0u));
 }
 
 TEST_F(TableFlattenerTest, FlattenMinMaxAttributes) {
@@ -208,15 +200,15 @@
     attr.minInt = 10;
     attr.maxInt = 23;
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addValue(u"@android:attr/foo", ResourceId(0x01010000),
+            .setPackageId("android", 0x01)
+            .addValue("@android:attr/foo", ResourceId(0x01010000),
                       util::make_unique<Attribute>(attr))
             .build();
 
     ResourceTable result;
     ASSERT_TRUE(flatten(table.get(), &result));
 
-    Attribute* actualAttr = test::getValue<Attribute>(&result, u"@android:attr/foo");
+    Attribute* actualAttr = test::getValue<Attribute>(&result, "@android:attr/foo");
     ASSERT_NE(nullptr, actualAttr);
     EXPECT_EQ(attr.isWeak(), actualAttr->isWeak());
     EXPECT_EQ(attr.typeMask, actualAttr->typeMask);
diff --git a/tools/aapt2/flatten/XmlFlattener.cpp b/tools/aapt2/flatten/XmlFlattener.cpp
index 2cf7dda..a743177 100644
--- a/tools/aapt2/flatten/XmlFlattener.cpp
+++ b/tools/aapt2/flatten/XmlFlattener.cpp
@@ -57,7 +57,7 @@
             mBuffer(buffer), mOptions(options) {
     }
 
-    void addString(const StringPiece16& str, uint32_t priority, android::ResStringPool_ref* dest,
+    void addString(const StringPiece& 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.
@@ -205,9 +205,9 @@
                     xmlAttr->compiledAttribute.value().id.value() == kIdAttr) {
                 flatElem->idIndex = util::hostToDevice16(attributeIndex);
             } else if (xmlAttr->namespaceUri.empty()) {
-                if (xmlAttr->name == u"class") {
+                if (xmlAttr->name == "class") {
                     flatElem->classIndex = util::hostToDevice16(attributeIndex);
-                } else if (xmlAttr->name == u"style") {
+                } else if (xmlAttr->name == "style") {
                     flatElem->styleIndex = util::hostToDevice16(attributeIndex);
                 }
             }
diff --git a/tools/aapt2/flatten/XmlFlattener_test.cpp b/tools/aapt2/flatten/XmlFlattener_test.cpp
index ef06528..9efee1e 100644
--- a/tools/aapt2/flatten/XmlFlattener_test.cpp
+++ b/tools/aapt2/flatten/XmlFlattener_test.cpp
@@ -16,13 +16,11 @@
 
 #include "flatten/XmlFlattener.h"
 #include "link/Linkers.h"
-#include "test/Builders.h"
-#include "test/Context.h"
+#include "test/Test.h"
 #include "util/BigBuffer.h"
 #include "util/Util.h"
 
 #include <androidfw/ResourceTypes.h>
-#include <gtest/gtest.h>
 
 namespace aapt {
 
@@ -30,15 +28,15 @@
 public:
     void SetUp() override {
         mContext = test::ContextBuilder()
-                .setCompilationPackage(u"com.app.test")
-                .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
+                .setCompilationPackage("com.app.test")
+                .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
                 .addSymbolSource(test::StaticSymbolSourceBuilder()
-                        .addSymbol(u"@android:attr/id", ResourceId(0x010100d0),
+                        .addSymbol("@android:attr/id", ResourceId(0x010100d0),
                                    test::AttributeBuilder().build())
-                        .addSymbol(u"@com.app.test:id/id", ResourceId(0x7f020000))
-                        .addSymbol(u"@android:attr/paddingStart", ResourceId(0x010103b3),
+                        .addSymbol("@com.app.test:id/id", ResourceId(0x7f020000))
+                        .addSymbol("@android:attr/paddingStart", ResourceId(0x010103b3),
                                    test::AttributeBuilder().build())
-                        .addSymbol(u"@android:attr/colorAccent", ResourceId(0x01010435),
+                        .addSymbol("@android:attr/colorAccent", ResourceId(0x01010435),
                                    test::AttributeBuilder().build())
                         .build())
                 .build();
diff --git a/tools/aapt2/java/AnnotationProcessor.cpp b/tools/aapt2/java/AnnotationProcessor.cpp
index b7e7f90..23ff8ab 100644
--- a/tools/aapt2/java/AnnotationProcessor.cpp
+++ b/tools/aapt2/java/AnnotationProcessor.cpp
@@ -47,23 +47,13 @@
     mComment << "\n * " << std::move(comment);
 }
 
-void AnnotationProcessor::appendComment(const StringPiece16& comment) {
-    // We need to process line by line to clean-up whitespace and append prefixes.
-    for (StringPiece16 line : util::tokenize(comment, u'\n')) {
-        line = util::trimWhitespace(line);
-        if (!line.empty()) {
-            std::string utf8Line = util::utf16ToUtf8(line);
-            appendCommentLine(utf8Line);
-        }
-    }
-}
-
 void AnnotationProcessor::appendComment(const StringPiece& comment) {
+    // We need to process line by line to clean-up whitespace and append prefixes.
     for (StringPiece line : util::tokenize(comment, '\n')) {
         line = util::trimWhitespace(line);
         if (!line.empty()) {
-            std::string utf8Line = line.toString();
-            appendCommentLine(utf8Line);
+            std::string lineCopy = line.toString();
+            appendCommentLine(lineCopy);
         }
     }
 }
@@ -75,7 +65,7 @@
 void AnnotationProcessor::writeToStream(std::ostream* out, const StringPiece& prefix) const {
     if (mHasComments) {
         std::string result = mComment.str();
-        for (StringPiece line : util::tokenize<char>(result, '\n')) {
+        for (StringPiece line : util::tokenize(result, '\n')) {
            *out << prefix << line << "\n";
         }
         *out << prefix << " */" << "\n";
diff --git a/tools/aapt2/java/AnnotationProcessor.h b/tools/aapt2/java/AnnotationProcessor.h
index 8309dd9..cfc32f3 100644
--- a/tools/aapt2/java/AnnotationProcessor.h
+++ b/tools/aapt2/java/AnnotationProcessor.h
@@ -57,7 +57,6 @@
      * Adds more comments. Since resources can have various values with different configurations,
      * we need to collect all the comments.
      */
-    void appendComment(const StringPiece16& comment);
     void appendComment(const StringPiece& comment);
 
     void appendNewLine();
diff --git a/tools/aapt2/java/JavaClassGenerator.cpp b/tools/aapt2/java/JavaClassGenerator.cpp
index 84df0b4..fbaefb1 100644
--- a/tools/aapt2/java/JavaClassGenerator.cpp
+++ b/tools/aapt2/java/JavaClassGenerator.cpp
@@ -19,7 +19,6 @@
 #include "ResourceTable.h"
 #include "ResourceValues.h"
 #include "ValueVisitor.h"
-
 #include "java/AnnotationProcessor.h"
 #include "java/ClassDefinition.h"
 #include "java/JavaClassGenerator.h"
@@ -39,20 +38,20 @@
         mContext(context), mTable(table), mOptions(options) {
 }
 
-static const std::set<StringPiece16> sJavaIdentifiers = {
-    u"abstract", u"assert", u"boolean", u"break", u"byte",
-    u"case", u"catch", u"char", u"class", u"const", u"continue",
-    u"default", u"do", u"double", u"else", u"enum", u"extends",
-    u"final", u"finally", u"float", u"for", u"goto", u"if",
-    u"implements", u"import", u"instanceof", u"int", u"interface",
-    u"long", u"native", u"new", u"package", u"private", u"protected",
-    u"public", u"return", u"short", u"static", u"strictfp", u"super",
-    u"switch", u"synchronized", u"this", u"throw", u"throws",
-    u"transient", u"try", u"void", u"volatile", u"while", u"true",
-    u"false", u"null"
+static const std::set<StringPiece> sJavaIdentifiers = {
+    "abstract", "assert", "boolean", "break", "byte",
+    "case", "catch", "char", "class", "const", "continue",
+    "default", "do", "double", "else", "enum", "extends",
+    "final", "finally", "float", "for", "goto", "if",
+    "implements", "import", "instanceof", "int", "interface",
+    "long", "native", "new", "package", "private", "protected",
+    "public", "return", "short", "static", "strictfp", "super",
+    "switch", "synchronized", "this", "throw", "throws",
+    "transient", "try", "void", "volatile", "while", "true",
+    "false", "null"
 };
 
-static bool isValidSymbol(const StringPiece16& symbol) {
+static bool isValidSymbol(const StringPiece& symbol) {
     return sJavaIdentifiers.find(symbol) == sJavaIdentifiers.end();
 }
 
@@ -60,8 +59,8 @@
  * Java symbols can not contain . or -, but those are valid in a resource name.
  * Replace those with '_'.
  */
-static std::string transform(const StringPiece16& symbol) {
-    std::string output = util::utf16ToUtf8(symbol);
+static std::string transform(const StringPiece& symbol) {
+    std::string output = symbol.toString();
     for (char& c : output) {
         if (c == '.' || c == '-') {
             c = '_';
@@ -83,7 +82,7 @@
  */
 static std::string transformNestedAttr(const ResourceNameRef& attrName,
                                        const std::string& styleableClassName,
-                                       const StringPiece16& packageNameToGenerate) {
+                                       const StringPiece& packageNameToGenerate) {
     std::string output = styleableClassName;
 
     // We may reference IDs from other packages, so prefix the entry name with
@@ -204,8 +203,8 @@
     }
 }
 
-void JavaClassGenerator::addMembersToStyleableClass(const StringPiece16& packageNameToGenerate,
-                                                    const std::u16string& entryName,
+void JavaClassGenerator::addMembersToStyleableClass(const StringPiece& packageNameToGenerate,
+                                                    const std::string& entryName,
                                                     const Styleable* styleable,
                                                     ClassDefinition* outStyleableClassDef) {
     const std::string className = transform(entryName);
@@ -284,8 +283,8 @@
                 continue;
             }
 
-            StringPiece16 attrCommentLine = entry.symbol->attribute->getComment();
-            if (attrCommentLine.contains(StringPiece16(u"@removed"))) {
+            StringPiece attrCommentLine = entry.symbol->attribute->getComment();
+            if (attrCommentLine.contains("@removed")) {
                 // Removed attributes are public but hidden from the documentation, so don't emit
                 // them as part of the class documentation.
                 continue;
@@ -354,12 +353,12 @@
             continue;
         }
 
-        StringPiece16 comment = styleableAttr.attrRef->getComment();
+        StringPiece comment = styleableAttr.attrRef->getComment();
         if (styleableAttr.symbol->attribute && comment.empty()) {
             comment = styleableAttr.symbol->attribute->getComment();
         }
 
-        if (comment.contains(StringPiece16(u"@removed"))) {
+        if (comment.contains("@removed")) {
             // Removed attributes are public but hidden from the documentation, so don't emit them
             // as part of the class documentation.
             continue;
@@ -367,7 +366,7 @@
 
         const ResourceName& attrName = styleableAttr.attrRef->name.value();
 
-        StringPiece16 packageName = attrName.package;
+        StringPiece packageName = attrName.package;
         if (packageName.empty()) {
             packageName = mContext->getCompilationPackage();
         }
@@ -403,7 +402,7 @@
     }
 }
 
-bool JavaClassGenerator::addMembersToTypeClass(const StringPiece16& packageNameToGenerate,
+bool JavaClassGenerator::addMembersToTypeClass(const StringPiece& packageNameToGenerate,
                                                const ResourceTablePackage* package,
                                                const ResourceTableType* type,
                                                ClassDefinition* outTypeClassDef) {
@@ -418,8 +417,8 @@
             id = ResourceId(package->id.value(), type->id.value(), entry->id.value());
         }
 
-        std::u16string unmangledPackage;
-        std::u16string unmangledName = entry->name;
+        std::string unmangledPackage;
+        std::string unmangledName = entry->name;
         if (NameMangler::unmangle(&unmangledName, &unmangledPackage)) {
             // The entry name was mangled, and we successfully unmangled it.
             // Check that we want to emit this symbol.
@@ -481,7 +480,7 @@
     return true;
 }
 
-bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate, std::ostream* out) {
+bool JavaClassGenerator::generate(const StringPiece& packageNameToGenerate, std::ostream* out) {
     return generate(packageNameToGenerate, packageNameToGenerate, out);
 }
 
@@ -494,8 +493,8 @@
     }
 }
 
-bool JavaClassGenerator::generate(const StringPiece16& packageNameToGenerate,
-                                  const StringPiece16& outPackageName, std::ostream* out) {
+bool JavaClassGenerator::generate(const StringPiece& packageNameToGenerate,
+                                  const StringPiece& outPackageName, std::ostream* out) {
 
     ClassDefinition rClass("R", ClassQualifier::None, true);
 
@@ -509,8 +508,7 @@
                     (mOptions.types == JavaClassGeneratorOptions::SymbolTypes::kPublic);
 
             std::unique_ptr<ClassDefinition> classDef = util::make_unique<ClassDefinition>(
-                    util::utf16ToUtf8(toString(type->type)), ClassQualifier::Static,
-                    forceCreationIfEmpty);
+                    toString(type->type), ClassQualifier::Static, forceCreationIfEmpty);
 
             bool result = addMembersToTypeClass(packageNameToGenerate, package.get(), type.get(),
                                                 classDef.get());
@@ -545,8 +543,7 @@
 
     appendJavaDocAnnotations(mOptions.javadocAnnotations, rClass.getCommentBuilder());
 
-    if (!ClassDefinition::writeJavaFile(&rClass, util::utf16ToUtf8(outPackageName),
-                                        mOptions.useFinal, out)) {
+    if (!ClassDefinition::writeJavaFile(&rClass, outPackageName, mOptions.useFinal, out)) {
         return false;
     }
 
diff --git a/tools/aapt2/java/JavaClassGenerator.h b/tools/aapt2/java/JavaClassGenerator.h
index 77e0ed7..901a86e 100644
--- a/tools/aapt2/java/JavaClassGenerator.h
+++ b/tools/aapt2/java/JavaClassGenerator.h
@@ -66,22 +66,22 @@
      * We need to generate these symbols in a separate file.
      * Returns true on success.
      */
-    bool generate(const StringPiece16& packageNameToGenerate, std::ostream* out);
+    bool generate(const StringPiece& packageNameToGenerate, std::ostream* out);
 
-    bool generate(const StringPiece16& packageNameToGenerate,
-                  const StringPiece16& outputPackageName,
+    bool generate(const StringPiece& packageNameToGenerate,
+                  const StringPiece& outputPackageName,
                   std::ostream* out);
 
     const std::string& getError() const;
 
 private:
-    bool addMembersToTypeClass(const StringPiece16& packageNameToGenerate,
+    bool addMembersToTypeClass(const StringPiece& packageNameToGenerate,
                                const ResourceTablePackage* package,
                                const ResourceTableType* type,
                                ClassDefinition* outTypeClassDef);
 
-    void addMembersToStyleableClass(const StringPiece16& packageNameToGenerate,
-                                    const std::u16string& entryName,
+    void addMembersToStyleableClass(const StringPiece& packageNameToGenerate,
+                                    const std::string& entryName,
                                     const Styleable* styleable,
                                     ClassDefinition* outStyleableClassDef);
 
diff --git a/tools/aapt2/java/JavaClassGenerator_test.cpp b/tools/aapt2/java/JavaClassGenerator_test.cpp
index 46266b3..57a8047 100644
--- a/tools/aapt2/java/JavaClassGenerator_test.cpp
+++ b/tools/aapt2/java/JavaClassGenerator_test.cpp
@@ -25,40 +25,40 @@
 
 TEST(JavaClassGeneratorTest, FailWhenEntryIsJavaKeyword) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addSimple(u"@android:id/class", ResourceId(0x01020000))
+            .setPackageId("android", 0x01)
+            .addSimple("@android:id/class", ResourceId(0x01020000))
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
-    EXPECT_FALSE(generator.generate(u"android", &out));
+    EXPECT_FALSE(generator.generate("android", &out));
 }
 
 TEST(JavaClassGeneratorTest, TransformInvalidJavaIdentifierCharacter) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addSimple(u"@android:id/hey-man", ResourceId(0x01020000))
-            .addValue(u"@android:attr/cool.attr", ResourceId(0x01010000),
+            .setPackageId("android", 0x01)
+            .addSimple("@android:id/hey-man", ResourceId(0x01020000))
+            .addValue("@android:attr/cool.attr", ResourceId(0x01010000),
                       test::AttributeBuilder(false).build())
-            .addValue(u"@android:styleable/hey.dude", ResourceId(0x01030000),
+            .addValue("@android:styleable/hey.dude", ResourceId(0x01030000),
                       test::StyleableBuilder()
-                              .addItem(u"@android:attr/cool.attr", ResourceId(0x01010000))
+                              .addItem("@android:attr/cool.attr", ResourceId(0x01010000))
                               .build())
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
-    EXPECT_TRUE(generator.generate(u"android", &out));
+    EXPECT_TRUE(generator.generate("android", &out));
 
     std::string output = out.str();
 
@@ -74,18 +74,18 @@
 
 TEST(JavaClassGeneratorTest, CorrectPackageNameIsUsed) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addSimple(u"@android:id/one", ResourceId(0x01020000))
-            .addSimple(u"@android:id/com.foo$two", ResourceId(0x01020001))
+            .setPackageId("android", 0x01)
+            .addSimple("@android:id/one", ResourceId(0x01020000))
+            .addSimple("@android:id/com.foo$two", ResourceId(0x01020001))
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
-    ASSERT_TRUE(generator.generate(u"android", u"com.android.internal", &out));
+    ASSERT_TRUE(generator.generate("android", "com.android.internal", &out));
 
     std::string output = out.str();
     EXPECT_NE(std::string::npos, output.find("package com.android.internal;"));
@@ -96,18 +96,18 @@
 
 TEST(JavaClassGeneratorTest, AttrPrivateIsWrittenAsAttr) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addSimple(u"@android:attr/two", ResourceId(0x01010001))
-            .addSimple(u"@android:^attr-private/one", ResourceId(0x01010000))
+            .setPackageId("android", 0x01)
+            .addSimple("@android:attr/two", ResourceId(0x01010001))
+            .addSimple("@android:^attr-private/one", ResourceId(0x01010000))
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
-    ASSERT_TRUE(generator.generate(u"android", &out));
+    ASSERT_TRUE(generator.generate("android", &out));
 
     std::string output = out.str();
     EXPECT_NE(std::string::npos, output.find("public static final class attr"));
@@ -117,17 +117,17 @@
 TEST(JavaClassGeneratorTest, OnlyWritePublicResources) {
     StdErrDiagnostics diag;
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addSimple(u"@android:id/one", ResourceId(0x01020000))
-            .addSimple(u"@android:id/two", ResourceId(0x01020001))
-            .addSimple(u"@android:id/three", ResourceId(0x01020002))
-            .setSymbolState(u"@android:id/one", ResourceId(0x01020000), SymbolState::kPublic)
-            .setSymbolState(u"@android:id/two", ResourceId(0x01020001), SymbolState::kPrivate)
+            .setPackageId("android", 0x01)
+            .addSimple("@android:id/one", ResourceId(0x01020000))
+            .addSimple("@android:id/two", ResourceId(0x01020001))
+            .addSimple("@android:id/three", ResourceId(0x01020002))
+            .setSymbolState("@android:id/one", ResourceId(0x01020000), SymbolState::kPublic)
+            .setSymbolState("@android:id/two", ResourceId(0x01020001), SymbolState::kPrivate)
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
 
     JavaClassGeneratorOptions options;
@@ -135,7 +135,7 @@
     {
         JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
-        ASSERT_TRUE(generator.generate(u"android", &out));
+        ASSERT_TRUE(generator.generate("android", &out));
         std::string output = out.str();
         EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
         EXPECT_EQ(std::string::npos, output.find("two"));
@@ -146,7 +146,7 @@
     {
         JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
-        ASSERT_TRUE(generator.generate(u"android", &out));
+        ASSERT_TRUE(generator.generate("android", &out));
         std::string output = out.str();
         EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
         EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
@@ -157,7 +157,7 @@
     {
         JavaClassGenerator generator(context.get(), table.get(), options);
         std::stringstream out;
-        ASSERT_TRUE(generator.generate(u"android", &out));
+        ASSERT_TRUE(generator.generate("android", &out));
         std::string output = out.str();
         EXPECT_NE(std::string::npos, output.find("public static final int one=0x01020000;"));
         EXPECT_NE(std::string::npos, output.find("public static final int two=0x01020001;"));
@@ -198,27 +198,27 @@
 
 TEST(JavaClassGeneratorTest, EmitOtherPackagesAttributesInStyleable) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-                .setPackageId(u"android", 0x01)
-                .setPackageId(u"com.lib", 0x02)
-                .addValue(u"@android:attr/bar", ResourceId(0x01010000),
+                .setPackageId("android", 0x01)
+                .setPackageId("com.lib", 0x02)
+                .addValue("@android:attr/bar", ResourceId(0x01010000),
                           test::AttributeBuilder(false).build())
-                .addValue(u"@com.lib:attr/bar", ResourceId(0x02010000),
+                .addValue("@com.lib:attr/bar", ResourceId(0x02010000),
                            test::AttributeBuilder(false).build())
-                .addValue(u"@android:styleable/foo", ResourceId(0x01030000),
+                .addValue("@android:styleable/foo", ResourceId(0x01030000),
                           test::StyleableBuilder()
-                                  .addItem(u"@android:attr/bar", ResourceId(0x01010000))
-                                  .addItem(u"@com.lib:attr/bar", ResourceId(0x02010000))
+                                  .addItem("@android:attr/bar", ResourceId(0x01010000))
+                                  .addItem("@com.lib:attr/bar", ResourceId(0x02010000))
                                   .build())
                 .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGenerator generator(context.get(), table.get(), {});
 
     std::stringstream out;
-    EXPECT_TRUE(generator.generate(u"android", &out));
+    EXPECT_TRUE(generator.generate("android", &out));
 
     std::string output = out.str();
     EXPECT_NE(std::string::npos, output.find("int foo_bar="));
@@ -227,19 +227,19 @@
 
 TEST(JavaClassGeneratorTest, CommentsForSimpleResourcesArePresent) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addSimple(u"@android:id/foo", ResourceId(0x01010000))
+            .setPackageId("android", 0x01)
+            .addSimple("@android:id/foo", ResourceId(0x01010000))
             .build();
-    test::getValue<Id>(table.get(), u"@android:id/foo")
-            ->setComment(std::u16string(u"This is a comment\n@deprecated"));
+    test::getValue<Id>(table.get(), "@android:id/foo")
+            ->setComment(std::string("This is a comment\n@deprecated"));
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGenerator generator(context.get(), table.get(), {});
     std::stringstream out;
-    ASSERT_TRUE(generator.generate(u"android", &out));
+    ASSERT_TRUE(generator.generate("android", &out));
     std::string actual = out.str();
 
     const char* expectedText =
@@ -259,59 +259,56 @@
 
 TEST(JavaClassGeneratorTest, CommentsForStyleablesAndNestedAttributesArePresent) {
     Attribute attr(false);
-    attr.setComment(StringPiece16(u"This is an attribute"));
+    attr.setComment(StringPiece("This is an attribute"));
 
     Styleable styleable;
-    styleable.entries.push_back(Reference(test::parseNameOrDie(u"@android:attr/one")));
-    styleable.setComment(StringPiece16(u"This is a styleable"));
+    styleable.entries.push_back(Reference(test::parseNameOrDie("@android:attr/one")));
+    styleable.setComment(StringPiece("This is a styleable"));
 
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addValue(u"@android:attr/one", util::make_unique<Attribute>(attr))
-            .addValue(u"@android:styleable/Container",
+            .setPackageId("android", 0x01)
+            .addValue("@android:attr/one", util::make_unique<Attribute>(attr))
+            .addValue("@android:styleable/Container",
                       std::unique_ptr<Styleable>(styleable.clone(nullptr)))
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGeneratorOptions options;
     options.useFinal = false;
     JavaClassGenerator generator(context.get(), table.get(), options);
     std::stringstream out;
-    ASSERT_TRUE(generator.generate(u"android", &out));
+    ASSERT_TRUE(generator.generate("android", &out));
     std::string actual = out.str();
 
     EXPECT_NE(std::string::npos, actual.find("@attr name android:one"));
     EXPECT_NE(std::string::npos, actual.find("@attr description"));
-    EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(attr.getComment())));
-    EXPECT_NE(std::string::npos, actual.find(util::utf16ToUtf8(styleable.getComment())));
+    EXPECT_NE(std::string::npos, actual.find(attr.getComment().data()));
+    EXPECT_NE(std::string::npos, actual.find(styleable.getComment().data()));
 }
 
 TEST(JavaClassGeneratorTest, CommentsForRemovedAttributesAreNotPresentInClass) {
     Attribute attr(false);
-    attr.setComment(StringPiece16(u"@removed"));
-
+    attr.setComment(StringPiece("@removed"));
 
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"android", 0x01)
-            .addValue(u"@android:attr/one", util::make_unique<Attribute>(attr))
+            .setPackageId("android", 0x01)
+            .addValue("@android:attr/one", util::make_unique<Attribute>(attr))
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+            .setNameManglerPolicy(NameManglerPolicy{ "android" })
             .build();
     JavaClassGeneratorOptions options;
     options.useFinal = false;
     JavaClassGenerator generator(context.get(), table.get(), options);
     std::stringstream out;
-    ASSERT_TRUE(generator.generate(u"android", &out));
+    ASSERT_TRUE(generator.generate("android", &out));
     std::string actual = out.str();
 
-    std::cout << actual << std::endl;
-
     EXPECT_EQ(std::string::npos, actual.find("@attr name android:one"));
     EXPECT_EQ(std::string::npos, actual.find("@attr description"));
 
diff --git a/tools/aapt2/java/ManifestClassGenerator.cpp b/tools/aapt2/java/ManifestClassGenerator.cpp
index be8955e..5ff11b1 100644
--- a/tools/aapt2/java/ManifestClassGenerator.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator.cpp
@@ -25,12 +25,12 @@
 
 namespace aapt {
 
-static Maybe<StringPiece16> extractJavaIdentifier(IDiagnostics* diag, const Source& source,
-                                                  const StringPiece16& value) {
-    const StringPiece16 sep = u".";
+static Maybe<StringPiece> extractJavaIdentifier(IDiagnostics* diag, const Source& source,
+                                                const StringPiece& value) {
+    const StringPiece sep = ".";
     auto iter = std::find_end(value.begin(), value.end(), sep.begin(), sep.end());
 
-    StringPiece16 result;
+    StringPiece result;
     if (iter != value.end()) {
         result.assign(iter + sep.size(), value.end() - (iter + sep.size()));
     } else {
@@ -42,15 +42,15 @@
         return {};
     }
 
-    iter = util::findNonAlphaNumericAndNotInSet(result, u"_");
+    iter = util::findNonAlphaNumericAndNotInSet(result, "_");
     if (iter != result.end()) {
         diag->error(DiagMessage(source)
-                    << "invalid character '" << StringPiece16(iter, 1)
+                    << "invalid character '" << StringPiece(iter, 1)
                     << "' in '" << result << "'");
         return {};
     }
 
-    if (*result.begin() >= u'0' && *result.begin() <= u'9') {
+    if (*result.begin() >= '0' && *result.begin() <= '9') {
         diag->error(DiagMessage(source) << "symbol can not start with a digit");
         return {};
     }
@@ -60,20 +60,20 @@
 
 static bool writeSymbol(const Source& source, IDiagnostics* diag, xml::Element* el,
                         ClassDefinition* classDef) {
-    xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name");
+    xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, "name");
     if (!attr) {
         diag->error(DiagMessage(source) << "<" << el->name << "> must define 'android:name'");
         return false;
     }
 
-    Maybe<StringPiece16> result = extractJavaIdentifier(diag, source.withLine(el->lineNumber),
-                                                        attr->value);
+    Maybe<StringPiece> result = extractJavaIdentifier(diag, source.withLine(el->lineNumber),
+                                                      attr->value);
     if (!result) {
         return false;
     }
 
     std::unique_ptr<StringMember> stringMember = util::make_unique<StringMember>(
-            util::utf16ToUtf8(result.value()), util::utf16ToUtf8(attr->value));
+            result.value(), attr->value);
     stringMember->getCommentBuilder()->appendComment(el->comment);
 
     classDef->addMember(std::move(stringMember));
@@ -87,7 +87,7 @@
         return {};
     }
 
-    if (el->name != u"manifest" && !el->namespaceUri.empty()) {
+    if (el->name != "manifest" && !el->namespaceUri.empty()) {
         diag->error(DiagMessage(res->file.source) << "no <manifest> root tag defined");
         return {};
     }
@@ -102,9 +102,9 @@
     std::vector<xml::Element*> children = el->getChildElements();
     for (xml::Element* childEl : children) {
         if (childEl->namespaceUri.empty()) {
-            if (childEl->name == u"permission") {
+            if (childEl->name == "permission") {
                 error |= !writeSymbol(res->file.source, diag, childEl, permissionClass.get());
-            } else if (childEl->name == u"permission-group") {
+            } else if (childEl->name == "permission-group") {
                 error |= !writeSymbol(res->file.source, diag, childEl, permissionGroupClass.get());
             }
         }
diff --git a/tools/aapt2/java/ManifestClassGenerator_test.cpp b/tools/aapt2/java/ManifestClassGenerator_test.cpp
index d3bca70..eecb544 100644
--- a/tools/aapt2/java/ManifestClassGenerator_test.cpp
+++ b/tools/aapt2/java/ManifestClassGenerator_test.cpp
@@ -15,10 +15,7 @@
  */
 
 #include "java/ManifestClassGenerator.h"
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
 
 namespace aapt {
 
diff --git a/tools/aapt2/java/ProguardRules.cpp b/tools/aapt2/java/ProguardRules.cpp
index 53ff961..9061660 100644
--- a/tools/aapt2/java/ProguardRules.cpp
+++ b/tools/aapt2/java/ProguardRules.cpp
@@ -43,7 +43,7 @@
                     node->namespaceUri);
             if (maybePackage) {
                 // This is a custom view, let's figure out the class name from this.
-                std::u16string package = maybePackage.value().package + u"." + node->name;
+                std::string package = maybePackage.value().package + "." + node->name;
                 if (util::isJavaClassName(package)) {
                     addClass(node->lineNumber, package);
                 }
@@ -58,11 +58,11 @@
     }
 
 protected:
-    void addClass(size_t lineNumber, const std::u16string& className) {
+    void addClass(size_t lineNumber, const std::string& className) {
         mKeepSet->addClass(Source(mSource.path, lineNumber), className);
     }
 
-    void addMethod(size_t lineNumber, const std::u16string& methodName) {
+    void addMethod(size_t lineNumber, const std::string& methodName) {
         mKeepSet->addMethod(Source(mSource.path, lineNumber), methodName);
     }
 
@@ -79,19 +79,19 @@
         bool checkClass = false;
         bool checkName = false;
         if (node->namespaceUri.empty()) {
-            checkClass = node->name == u"view" || node->name == u"fragment";
+            checkClass = node->name == "view" || node->name == "fragment";
         } else if (node->namespaceUri == xml::kSchemaAndroid) {
-            checkName = node->name == u"fragment";
+            checkName = node->name == "fragment";
         }
 
         for (const auto& attr : node->attributes) {
-            if (checkClass && attr.namespaceUri.empty() && attr.name == u"class" &&
+            if (checkClass && attr.namespaceUri.empty() && attr.name == "class" &&
                     util::isJavaClassName(attr.value)) {
                 addClass(node->lineNumber, attr.value);
             } else if (checkName && attr.namespaceUri == xml::kSchemaAndroid &&
-                    attr.name == u"name" && util::isJavaClassName(attr.value)) {
+                    attr.name == "name" && util::isJavaClassName(attr.value)) {
                 addClass(node->lineNumber, attr.value);
-            } else if (attr.namespaceUri == xml::kSchemaAndroid && attr.name == u"onClick") {
+            } else if (attr.namespaceUri == xml::kSchemaAndroid && attr.name == "onClick") {
                 addMethod(node->lineNumber, attr.value);
             }
         }
@@ -107,11 +107,11 @@
     virtual void visit(xml::Element* node) override {
         bool checkFragment = false;
         if (node->namespaceUri.empty()) {
-            checkFragment = node->name == u"PreferenceScreen" || node->name == u"header";
+            checkFragment = node->name == "PreferenceScreen" || node->name == "header";
         }
 
         if (checkFragment) {
-            xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"fragment");
+            xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, "fragment");
             if (attr && util::isJavaClassName(attr->value)) {
                 addClass(node->lineNumber, attr->value);
             }
@@ -127,9 +127,9 @@
 
     virtual void visit(xml::Element* node) override {
         bool checkClass = node->namespaceUri.empty() &&
-                (node->name == u"transition" || node->name == u"pathMotion");
+                (node->name == "transition" || node->name == "pathMotion");
         if (checkClass) {
-            xml::Attribute* attr = node->findAttribute({}, u"class");
+            xml::Attribute* attr = node->findAttribute({}, "class");
             if (attr && util::isJavaClassName(attr->value)) {
                 addClass(node->lineNumber, attr->value);
             }
@@ -147,50 +147,50 @@
     virtual void visit(xml::Element* node) override {
         if (node->namespaceUri.empty()) {
             bool getName = false;
-            if (node->name == u"manifest") {
-                xml::Attribute* attr = node->findAttribute({}, u"package");
+            if (node->name == "manifest") {
+                xml::Attribute* attr = node->findAttribute({}, "package");
                 if (attr) {
                     mPackage = attr->value;
                 }
-            } else if (node->name == u"application") {
+            } else if (node->name == "application") {
                 getName = true;
-                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"backupAgent");
+                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, "backupAgent");
                 if (attr) {
-                    Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
-                                                                                    attr->value);
+                    Maybe<std::string> result = util::getFullyQualifiedClassName(mPackage,
+                                                                                 attr->value);
                     if (result) {
                         addClass(node->lineNumber, result.value());
                     }
                 }
                 if (mMainDexOnly) {
                     xml::Attribute* defaultProcess = node->findAttribute(xml::kSchemaAndroid,
-                                                                         u"process");
+                                                                         "process");
                     if (defaultProcess) {
                         mDefaultProcess = defaultProcess->value;
                     }
                 }
-            } else if (node->name == u"activity" || node->name == u"service" ||
-                    node->name == u"receiver" || node->name == u"provider" ||
-                    node->name == u"instrumentation") {
+            } else if (node->name == "activity" || node->name == "service" ||
+                    node->name == "receiver" || node->name == "provider" ||
+                    node->name == "instrumentation") {
                 getName = true;
             }
 
             if (getName) {
-                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, u"name");
+                xml::Attribute* attr = node->findAttribute(xml::kSchemaAndroid, "name");
                 getName = attr != nullptr;
 
                 if (getName && mMainDexOnly) {
                     xml::Attribute* componentProcess = node->findAttribute(xml::kSchemaAndroid,
-                                                                           u"process");
+                                                                           "process");
 
-                    const std::u16string& process = componentProcess ? componentProcess->value
-                                                                     : mDefaultProcess;
-                    getName = !process.empty() && process[0] != u':';
+                    const std::string& process = componentProcess ? componentProcess->value
+                            : mDefaultProcess;
+                    getName = !process.empty() && process[0] != ':';
                 }
 
                 if (getName) {
-                    Maybe<std::u16string> result = util::getFullyQualifiedClassName(mPackage,
-                                                                                    attr->value);
+                    Maybe<std::string> result = util::getFullyQualifiedClassName(mPackage,
+                                                                                 attr->value);
                     if (result) {
                         addClass(node->lineNumber, result.value());
                     }
@@ -201,9 +201,9 @@
     }
 
 private:
-    std::u16string mPackage;
+    std::string mPackage;
     const bool mMainDexOnly;
-    std::u16string mDefaultProcess;
+    std::string mDefaultProcess;
 };
 
 bool collectProguardRulesForManifest(const Source& source, xml::XmlResource* res,
diff --git a/tools/aapt2/java/ProguardRules.h b/tools/aapt2/java/ProguardRules.h
index 744ae5b..c2d2bd9 100644
--- a/tools/aapt2/java/ProguardRules.h
+++ b/tools/aapt2/java/ProguardRules.h
@@ -31,19 +31,19 @@
 
 class KeepSet {
 public:
-    inline void addClass(const Source& source, const std::u16string& className) {
+    inline void addClass(const Source& source, const std::string& className) {
         mKeepSet[className].insert(source);
     }
 
-    inline void addMethod(const Source& source, const std::u16string& methodName) {
+    inline void addMethod(const Source& source, const std::string& methodName) {
         mKeepMethodSet[methodName].insert(source);
     }
 
 private:
     friend bool writeKeepSet(std::ostream* out, const KeepSet& keepSet);
 
-    std::map<std::u16string, std::set<Source>> mKeepSet;
-    std::map<std::u16string, std::set<Source>> mKeepMethodSet;
+    std::map<std::string, std::set<Source>> mKeepSet;
+    std::map<std::string, std::set<Source>> mKeepMethodSet;
 };
 
 bool collectProguardRulesForManifest(const Source& source, xml::XmlResource* res, KeepSet* keepSet,
diff --git a/tools/aapt2/link/AutoVersioner_test.cpp b/tools/aapt2/link/AutoVersioner_test.cpp
index 99a7c02..7764176 100644
--- a/tools/aapt2/link/AutoVersioner_test.cpp
+++ b/tools/aapt2/link/AutoVersioner_test.cpp
@@ -25,7 +25,7 @@
     const ConfigDescription landConfig = test::parseConfigOrDie("land");
     const ConfigDescription sw600dpLandConfig = test::parseConfigOrDie("sw600dp-land");
 
-    ResourceEntry entry(u"foo");
+    ResourceEntry entry("foo");
     entry.values.push_back(util::make_unique<ResourceConfigValue>(defaultConfig, ""));
     entry.values.push_back(util::make_unique<ResourceConfigValue>(landConfig, ""));
     entry.values.push_back(util::make_unique<ResourceConfigValue>(sw600dpLandConfig, ""));
@@ -39,7 +39,7 @@
     const ConfigDescription sw600dpV13Config = test::parseConfigOrDie("sw600dp-v13");
     const ConfigDescription v21Config = test::parseConfigOrDie("v21");
 
-    ResourceEntry entry(u"foo");
+    ResourceEntry entry("foo");
     entry.values.push_back(util::make_unique<ResourceConfigValue>(defaultConfig, ""));
     entry.values.push_back(util::make_unique<ResourceConfigValue>(sw600dpV13Config, ""));
     entry.values.push_back(util::make_unique<ResourceConfigValue>(v21Config, ""));
@@ -50,73 +50,73 @@
 
 TEST(AutoVersionerTest, VersionStylesForTable) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"app", 0x7f)
-            .addValue(u"@app:style/Foo", test::parseConfigOrDie("v4"), ResourceId(0x7f020000),
+            .setPackageId("app", 0x7f)
+            .addValue("@app:style/Foo", test::parseConfigOrDie("v4"), ResourceId(0x7f020000),
                       test::StyleBuilder()
-                            .addItem(u"@android:attr/onClick", ResourceId(0x0101026f),
+                            .addItem("@android:attr/onClick", ResourceId(0x0101026f),
                                      util::make_unique<Id>())
-                            .addItem(u"@android:attr/paddingStart", ResourceId(0x010103b3),
+                            .addItem("@android:attr/paddingStart", ResourceId(0x010103b3),
                                      util::make_unique<Id>())
-                            .addItem(u"@android:attr/requiresSmallestWidthDp",
+                            .addItem("@android:attr/requiresSmallestWidthDp",
                                      ResourceId(0x01010364), util::make_unique<Id>())
-                            .addItem(u"@android:attr/colorAccent", ResourceId(0x01010435),
+                            .addItem("@android:attr/colorAccent", ResourceId(0x01010435),
                                      util::make_unique<Id>())
                             .build())
-            .addValue(u"@app:style/Foo", test::parseConfigOrDie("v21"), ResourceId(0x7f020000),
+            .addValue("@app:style/Foo", test::parseConfigOrDie("v21"), ResourceId(0x7f020000),
                       test::StyleBuilder()
-                            .addItem(u"@android:attr/paddingEnd", ResourceId(0x010103b4),
+                            .addItem("@android:attr/paddingEnd", ResourceId(0x010103b4),
                                      util::make_unique<Id>())
                             .build())
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage(u"app")
+            .setCompilationPackage("app")
             .setPackageId(0x7f)
             .build();
 
     AutoVersioner versioner;
     ASSERT_TRUE(versioner.consume(context.get(), table.get()));
 
-    Style* style = test::getValueForConfig<Style>(table.get(), u"@app:style/Foo",
+    Style* style = test::getValueForConfig<Style>(table.get(), "@app:style/Foo",
                                                   test::parseConfigOrDie("v4"));
     ASSERT_NE(style, nullptr);
     ASSERT_EQ(style->entries.size(), 1u);
     AAPT_ASSERT_TRUE(style->entries.front().key.name);
     EXPECT_EQ(style->entries.front().key.name.value(),
-              test::parseNameOrDie(u"@android:attr/onClick"));
+              test::parseNameOrDie("@android:attr/onClick"));
 
-    style = test::getValueForConfig<Style>(table.get(), u"@app:style/Foo",
+    style = test::getValueForConfig<Style>(table.get(), "@app:style/Foo",
                                            test::parseConfigOrDie("v13"));
     ASSERT_NE(style, nullptr);
     ASSERT_EQ(style->entries.size(), 2u);
     AAPT_ASSERT_TRUE(style->entries[0].key.name);
     EXPECT_EQ(style->entries[0].key.name.value(),
-              test::parseNameOrDie(u"@android:attr/onClick"));
+              test::parseNameOrDie("@android:attr/onClick"));
     AAPT_ASSERT_TRUE(style->entries[1].key.name);
     EXPECT_EQ(style->entries[1].key.name.value(),
-                  test::parseNameOrDie(u"@android:attr/requiresSmallestWidthDp"));
+                  test::parseNameOrDie("@android:attr/requiresSmallestWidthDp"));
 
-    style = test::getValueForConfig<Style>(table.get(), u"@app:style/Foo",
+    style = test::getValueForConfig<Style>(table.get(), "@app:style/Foo",
                                            test::parseConfigOrDie("v17"));
     ASSERT_NE(style, nullptr);
     ASSERT_EQ(style->entries.size(), 3u);
     AAPT_ASSERT_TRUE(style->entries[0].key.name);
     EXPECT_EQ(style->entries[0].key.name.value(),
-                  test::parseNameOrDie(u"@android:attr/onClick"));
+                  test::parseNameOrDie("@android:attr/onClick"));
     AAPT_ASSERT_TRUE(style->entries[1].key.name);
     EXPECT_EQ(style->entries[1].key.name.value(),
-                  test::parseNameOrDie(u"@android:attr/requiresSmallestWidthDp"));
+                  test::parseNameOrDie("@android:attr/requiresSmallestWidthDp"));
     AAPT_ASSERT_TRUE(style->entries[2].key.name);
     EXPECT_EQ(style->entries[2].key.name.value(),
-                  test::parseNameOrDie(u"@android:attr/paddingStart"));
+                  test::parseNameOrDie("@android:attr/paddingStart"));
 
-    style = test::getValueForConfig<Style>(table.get(), u"@app:style/Foo",
+    style = test::getValueForConfig<Style>(table.get(), "@app:style/Foo",
                                            test::parseConfigOrDie("v21"));
     ASSERT_NE(style, nullptr);
     ASSERT_EQ(style->entries.size(), 1u);
     AAPT_ASSERT_TRUE(style->entries.front().key.name);
     EXPECT_EQ(style->entries.front().key.name.value(),
-              test::parseNameOrDie(u"@android:attr/paddingEnd"));
+              test::parseNameOrDie("@android:attr/paddingEnd"));
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index 9411053..8093e6a 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -58,8 +58,8 @@
     std::vector<std::string> includePaths;
     std::vector<std::string> overlayFiles;
     Maybe<std::string> generateJavaClassPath;
-    Maybe<std::u16string> customJavaPackage;
-    std::set<std::u16string> extraJavaPackages;
+    Maybe<std::string> customJavaPackage;
+    std::set<std::string> extraJavaPackages;
     Maybe<std::string> generateProguardRulesPath;
     Maybe<std::string> generateMainDexProguardRulesPath;
     bool noAutoVersion = false;
@@ -72,7 +72,7 @@
     bool autoAddOverlay = false;
     bool doNotCompressAnything = false;
     std::vector<std::string> extensionsToNotCompress;
-    Maybe<std::u16string> privateSymbols;
+    Maybe<std::string> privateSymbols;
     ManifestFixerOptions manifestFixerOptions;
     std::unordered_set<std::string> products;
     TableSplitterOptions tableSplitterOptions;
@@ -95,11 +95,11 @@
         mNameMangler = NameMangler(policy);
     }
 
-    const std::u16string& getCompilationPackage() override {
+    const std::string& getCompilationPackage() override {
         return mCompilationPackage;
     }
 
-    void setCompilationPackage(const StringPiece16& packageName) {
+    void setCompilationPackage(const StringPiece& packageName) {
         mCompilationPackage = packageName.toString();
     }
 
@@ -134,7 +134,7 @@
 private:
     StdErrDiagnostics mDiagnostics;
     NameMangler mNameMangler;
-    std::u16string mCompilationPackage;
+    std::string mCompilationPackage;
     uint8_t mPackageId = 0x0;
     SymbolTable mSymbols;
     bool mVerbose = false;
@@ -155,7 +155,7 @@
     size_t bufferSize = data->size();
 
     // If the file ends with .flat, we must strip off the CompiledFileHeader from it.
-    if (util::stringEndsWith<char>(file->getSource().path, ".flat")) {
+    if (util::stringEndsWith(file->getSource().path, ".flat")) {
         CompiledFileInputStream inputStream(data->data(), data->size());
         if (!inputStream.CompiledFile()) {
             context->getDiagnostics()->error(DiagMessage(file->getSource())
@@ -213,16 +213,6 @@
     return false;
 }
 
-/*static std::unique_ptr<ResourceTable> loadTable(const Source& source, const void* data, size_t len,
-                                                IDiagnostics* diag) {
-    std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
-    BinaryResourceParser parser(diag, table.get(), source, data, len);
-    if (!parser.parse()) {
-        return {};
-    }
-    return table;
-}*/
-
 static std::unique_ptr<ResourceTable> loadTableFromPb(const Source& source,
                                                       const void* data, size_t len,
                                                       IDiagnostics* diag) {
@@ -329,7 +319,7 @@
     }
 
     for (const std::string& extension : mOptions.extensionsToNotCompress) {
-        if (util::stringEndsWith<char>(str, extension)) {
+        if (util::stringEndsWith(str, extension)) {
             return 0;
         }
     }
@@ -352,7 +342,7 @@
         return false;
     }
 
-    if (util::stringEndsWith<char>(srcPath, ".flat")) {
+    if (util::stringEndsWith(srcPath, ".flat")) {
         outFileOp->xmlToFlatten = loadBinaryXmlSkipFileExport(file->getSource(),
                                                               data->data(), data->size(),
                                                               mContext->getDiagnostics());
@@ -384,7 +374,7 @@
             // Skip this if it is a vector or animated-vector.
             xml::Element* el = xml::findRootElement(outFileOp->xmlToFlatten.get());
             if (el && el->namespaceUri.empty()) {
-                if (el->name == u"vector" || el->name == u"animated-vector") {
+                if (el->name == "vector" || el->name == "animated-vector") {
                     // We are NOT going to version this file.
                     outFileOp->skipVersion = true;
                     return true;
@@ -413,8 +403,8 @@
                                                      << versionedFileDesc.config << "'");
                 }
 
-                std::u16string genPath = util::utf8ToUtf16(ResourceUtils::buildResourceFileName(
-                        versionedFileDesc, mContext->getNameMangler()));
+                std::string genPath = ResourceUtils::buildResourceFileName(
+                        versionedFileDesc, mContext->getNameMangler());
 
                 bool added = table->addFileReferenceAllowMangled(versionedFileDesc.name,
                                                                  versionedFileDesc.config,
@@ -438,7 +428,7 @@
  */
 bool ResourceFileFlattener::flatten(ResourceTable* table, IArchiveWriter* archiveWriter) {
     bool error = false;
-    std::map<std::pair<ConfigDescription, StringPiece16>, FileOperation> configSortedFiles;
+    std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> configSortedFiles;
 
     for (auto& pkg : table->packages) {
         for (auto& type : pkg->types) {
@@ -463,12 +453,12 @@
                     }
 
                     FileOperation fileOp;
-                    fileOp.dstPath = util::utf16ToUtf8(*fileRef->path);
+                    fileOp.dstPath = *fileRef->path;
 
                     const StringPiece srcPath = file->getSource().path;
                     if (type->type != ResourceType::kRaw &&
-                            (util::stringEndsWith<char>(srcPath, ".xml.flat") ||
-                            util::stringEndsWith<char>(srcPath, ".xml"))) {
+                            (util::stringEndsWith(srcPath, ".xml.flat") ||
+                            util::stringEndsWith(srcPath, ".xml"))) {
                         ResourceFile fileDesc;
                         fileDesc.config = configValue->config;
                         fileDesc.name = ResourceName(pkg->name, type->type, entry->name);
@@ -486,7 +476,7 @@
                     // we end up copying the string in the std::make_pair() method, then creating
                     // a StringPiece16 from the copy, which would cause us to end up referencing
                     // garbage in the map.
-                    const StringPiece16 entryName(entry->name);
+                    const StringPiece entryName(entry->name);
                     configSortedFiles[std::make_pair(configValue->config, entryName)] =
                                       std::move(fileOp);
                 }
@@ -592,12 +582,12 @@
         if (xml::Element* manifestEl = xml::findRootElement(xmlRes->root.get())) {
             AppInfo appInfo;
 
-            if (!manifestEl->namespaceUri.empty() || manifestEl->name != u"manifest") {
+            if (!manifestEl->namespaceUri.empty() || manifestEl->name != "manifest") {
                 diag->error(DiagMessage(xmlRes->file.source) << "root tag must be <manifest>");
                 return {};
             }
 
-            xml::Attribute* packageAttr = manifestEl->findAttribute({}, u"package");
+            xml::Attribute* packageAttr = manifestEl->findAttribute({}, "package");
             if (!packageAttr) {
                 diag->error(DiagMessage(xmlRes->file.source)
                             << "<manifest> must have a 'package' attribute");
@@ -606,9 +596,9 @@
 
             appInfo.package = packageAttr->value;
 
-            if (xml::Element* usesSdkEl = manifestEl->findChild({}, u"uses-sdk")) {
+            if (xml::Element* usesSdkEl = manifestEl->findChild({}, "uses-sdk")) {
                 if (xml::Attribute* minSdk =
-                        usesSdkEl->findAttribute(xml::kSchemaAndroid, u"minSdkVersion")) {
+                        usesSdkEl->findAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
                     appInfo.minSdkVersion = minSdk->value;
                 }
             }
@@ -642,7 +632,7 @@
                             // Special case the occurrence of an ID that is being generated for the
                             // 'android' package. This is due to legacy reasons.
                             if (valueCast<Id>(configValue->value.get()) &&
-                                    package->name == u"android") {
+                                    package->name == "android") {
                                 mContext->getDiagnostics()->warn(
                                         DiagMessage(configValue->value->getSource())
                                         << "generated id '" << resName
@@ -752,14 +742,14 @@
         return true;
     }
 
-    bool writeJavaFile(ResourceTable* table, const StringPiece16& packageNameToGenerate,
-                       const StringPiece16& outPackage, JavaClassGeneratorOptions javaOptions) {
+    bool writeJavaFile(ResourceTable* table, const StringPiece& packageNameToGenerate,
+                       const StringPiece& outPackage, JavaClassGeneratorOptions javaOptions) {
         if (!mOptions.generateJavaClassPath) {
             return true;
         }
 
         std::string outPath = mOptions.generateJavaClassPath.value();
-        file::appendPath(&outPath, file::packageToPath(util::utf16ToUtf8(outPackage)));
+        file::appendPath(&outPath, file::packageToPath(outPackage));
         if (!file::mkdirs(outPath)) {
             mContext->getDiagnostics()->error(
                     DiagMessage() << "failed to create directory '" << outPath << "'");
@@ -813,7 +803,7 @@
             manifestClass->getCommentBuilder()->appendComment(properAnnotation);
         }
 
-        const std::string packageUtf8 = util::utf16ToUtf8(mContext->getCompilationPackage());
+        const std::string& packageUtf8 = mContext->getCompilationPackage();
 
         std::string outPath = mOptions.generateJavaClassPath.value();
         file::appendPath(&outPath, file::packageToPath(packageUtf8));
@@ -921,7 +911,7 @@
                 mOptions.extraJavaPackages.insert(pkg->name);
             }
 
-            pkg->name = u"";
+            pkg->name = "";
             if (override) {
                 result = mTableMerger->mergeOverlay(Source(input), table.get(), collection.get());
             } else {
@@ -1059,12 +1049,12 @@
      * Otherwise the files is processed on its own.
      */
     bool mergePath(const std::string& path, bool override) {
-        if (util::stringEndsWith<char>(path, ".flata") ||
-                util::stringEndsWith<char>(path, ".jar") ||
-                util::stringEndsWith<char>(path, ".jack") ||
-                util::stringEndsWith<char>(path, ".zip")) {
+        if (util::stringEndsWith(path, ".flata") ||
+                util::stringEndsWith(path, ".jar") ||
+                util::stringEndsWith(path, ".jack") ||
+                util::stringEndsWith(path, ".zip")) {
             return mergeArchive(path, override);
-        } else if (util::stringEndsWith<char>(path, ".apk")) {
+        } else if (util::stringEndsWith(path, ".apk")) {
             return mergeStaticLibrary(path, override);
         }
 
@@ -1085,10 +1075,10 @@
      */
     bool mergeFile(io::IFile* file, bool override) {
         const Source& src = file->getSource();
-        if (util::stringEndsWith<char>(src.path, ".arsc.flat")) {
+        if (util::stringEndsWith(src.path, ".arsc.flat")) {
             return mergeResourceTable(file, override);
 
-        } else if (util::stringEndsWith<char>(src.path, ".flat")){
+        } else if (util::stringEndsWith(src.path, ".flat")){
             // Try opening the file and looking for an Export header.
             std::unique_ptr<io::IData> data = file->openAsData();
             if (!data) {
@@ -1135,7 +1125,7 @@
 
         mContext->setNameManglerPolicy(NameManglerPolicy{ mContext->getCompilationPackage() });
 
-        if (mContext->getCompilationPackage() == u"android") {
+        if (mContext->getCompilationPackage() == "android") {
             mContext->setPackageId(0x01);
         } else {
             mContext->setPackageId(0x7f);
@@ -1370,8 +1360,8 @@
                 options.useFinal = false;
             }
 
-            const StringPiece16 actualPackage = mContext->getCompilationPackage();
-            StringPiece16 outputPackage = mContext->getCompilationPackage();
+            const StringPiece actualPackage = mContext->getCompilationPackage();
+            StringPiece outputPackage = mContext->getCompilationPackage();
             if (mOptions.customJavaPackage) {
                 // Override the output java package to the custom one.
                 outputPackage = mOptions.customJavaPackage.value();
@@ -1395,7 +1385,7 @@
                 return 1;
             }
 
-            for (const std::u16string& extraPackage : mOptions.extraJavaPackages) {
+            for (const std::string& extraPackage : mOptions.extraJavaPackages) {
                 if (!writeJavaFile(&mFinalTable, actualPackage, extraPackage, options)) {
                     return 1;
                 }
@@ -1440,11 +1430,6 @@
     LinkContext context;
     LinkOptions options;
     std::vector<std::string> overlayArgList;
-    Maybe<std::string> privateSymbolsPackage;
-    Maybe<std::string> minSdkVersion, targetSdkVersion;
-    Maybe<std::string> renameManifestPackage, renameInstrumentationTargetPackage;
-    Maybe<std::string> versionCode, versionName;
-    Maybe<std::string> customJavaPackage;
     std::vector<std::string> extraJavaPackages;
     Maybe<std::string> configs;
     Maybe<std::string> preferredDensity;
@@ -1489,14 +1474,19 @@
                             "by -o",
                             &options.outputToDirectory)
             .optionalFlag("--min-sdk-version", "Default minimum SDK version to use for "
-                          "AndroidManifest.xml", &minSdkVersion)
+                          "AndroidManifest.xml",
+                          &options.manifestFixerOptions.minSdkVersionDefault)
             .optionalFlag("--target-sdk-version", "Default target SDK version to use for "
-                          "AndroidManifest.xml", &targetSdkVersion)
+                          "AndroidManifest.xml",
+                          &options.manifestFixerOptions.targetSdkVersionDefault)
             .optionalFlag("--version-code", "Version code (integer) to inject into the "
-                          "AndroidManifest.xml if none is present", &versionCode)
+                          "AndroidManifest.xml if none is present",
+                          &options.manifestFixerOptions.versionCodeDefault)
             .optionalFlag("--version-name", "Version name to inject into the AndroidManifest.xml "
-                          "if none is present", &versionName)
-            .optionalSwitch("--static-lib", "Generate a static Android library", &options.staticLib)
+                          "if none is present",
+                          &options.manifestFixerOptions.versionNameDefault)
+            .optionalSwitch("--static-lib", "Generate a static Android library",
+                            &options.staticLib)
             .optionalSwitch("--no-static-lib-packages",
                             "Merge all library resources under the app's package",
                             &options.noStaticLibPackages)
@@ -1506,24 +1496,29 @@
             .optionalFlag("--private-symbols", "Package name to use when generating R.java for "
                           "private symbols.\n"
                           "If not specified, public and private symbols will use the application's "
-                          "package name", &privateSymbolsPackage)
+                          "package name",
+                          &options.privateSymbols)
             .optionalFlag("--custom-package", "Custom Java package under which to generate R.java",
-                          &customJavaPackage)
+                          &options.customJavaPackage)
             .optionalFlagList("--extra-packages", "Generate the same R.java but with different "
-                              "package names", &extraJavaPackages)
+                              "package names",
+                              &extraJavaPackages)
             .optionalFlagList("--add-javadoc-annotation", "Adds a JavaDoc annotation to all "
-                            "generated Java classes", &options.javadocAnnotations)
+                            "generated Java classes",
+                            &options.javadocAnnotations)
             .optionalSwitch("--auto-add-overlay", "Allows the addition of new resources in "
-                            "overlays without <add-resource> tags", &options.autoAddOverlay)
+                            "overlays without <add-resource> tags",
+                            &options.autoAddOverlay)
             .optionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml",
-                          &renameManifestPackage)
+                          &options.manifestFixerOptions.renameManifestPackage)
             .optionalFlag("--rename-instrumentation-target-package",
                           "Changes the name of the target package for instrumentation. Most useful "
                           "when used\nin conjunction with --rename-manifest-package",
-                          &renameInstrumentationTargetPackage)
+                          &options.manifestFixerOptions.renameInstrumentationTargetPackage)
             .optionalFlagList("-0", "File extensions not to compress",
                               &options.extensionsToNotCompress)
-            .optionalSwitch("-v", "Enables verbose logging", &verbose);
+            .optionalSwitch("-v", "Enables verbose logging",
+                            &verbose);
 
     if (!flags.parse("aapt2 link", args, &std::cerr)) {
         return 1;
@@ -1532,7 +1527,7 @@
     // Expand all argument-files passed into the command line. These start with '@'.
     std::vector<std::string> argList;
     for (const std::string& arg : flags.getArgs()) {
-        if (util::stringStartsWith<char>(arg, "@")) {
+        if (util::stringStartsWith(arg, "@")) {
             const std::string path = arg.substr(1, arg.size() - 1);
             std::string error;
             if (!file::appendArgsFromFile(path, &argList, &error)) {
@@ -1546,7 +1541,7 @@
 
     // Expand all argument-files passed to -R.
     for (const std::string& arg : overlayArgList) {
-        if (util::stringStartsWith<char>(arg, "@")) {
+        if (util::stringStartsWith(arg, "@")) {
             const std::string path = arg.substr(1, arg.size() - 1);
             std::string error;
             if (!file::appendArgsFromFile(path, &options.overlayFiles, &error)) {
@@ -1562,52 +1557,16 @@
         context.setVerbose(verbose);
     }
 
-    if (privateSymbolsPackage) {
-        options.privateSymbols = util::utf8ToUtf16(privateSymbolsPackage.value());
-    }
-
-    if (minSdkVersion) {
-        options.manifestFixerOptions.minSdkVersionDefault =
-                util::utf8ToUtf16(minSdkVersion.value());
-    }
-
-    if (targetSdkVersion) {
-        options.manifestFixerOptions.targetSdkVersionDefault =
-                util::utf8ToUtf16(targetSdkVersion.value());
-    }
-
-    if (renameManifestPackage) {
-        options.manifestFixerOptions.renameManifestPackage =
-                util::utf8ToUtf16(renameManifestPackage.value());
-    }
-
-    if (renameInstrumentationTargetPackage) {
-        options.manifestFixerOptions.renameInstrumentationTargetPackage =
-                util::utf8ToUtf16(renameInstrumentationTargetPackage.value());
-    }
-
-    if (versionCode) {
-        options.manifestFixerOptions.versionCodeDefault = util::utf8ToUtf16(versionCode.value());
-    }
-
-    if (versionName) {
-        options.manifestFixerOptions.versionNameDefault = util::utf8ToUtf16(versionName.value());
-    }
-
-    if (customJavaPackage) {
-        options.customJavaPackage = util::utf8ToUtf16(customJavaPackage.value());
-    }
-
     // Populate the set of extra packages for which to generate R.java.
     for (std::string& extraPackage : extraJavaPackages) {
         // A given package can actually be a colon separated list of packages.
         for (StringPiece package : util::split(extraPackage, ':')) {
-            options.extraJavaPackages.insert(util::utf8ToUtf16(package));
+            options.extraJavaPackages.insert(package.toString());
         }
     }
 
     if (productList) {
-        for (StringPiece product : util::tokenize<char>(productList.value(), ',')) {
+        for (StringPiece product : util::tokenize(productList.value(), ',')) {
             if (product != "" && product != "default") {
                 options.products.insert(product.toString());
             }
@@ -1616,7 +1575,7 @@
 
     AxisConfigFilter filter;
     if (configs) {
-        for (const StringPiece& configStr : util::tokenize<char>(configs.value(), ',')) {
+        for (const StringPiece& configStr : util::tokenize(configs.value(), ',')) {
             ConfigDescription config;
             LocaleValue lv;
             if (lv.initFromFilterString(configStr)) {
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index db6e06d..ef09535 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -32,11 +32,12 @@
     // We allow unqualified class names (ie: .HelloActivity)
     // Since we don't know the package name, we can just make a fake one here and
     // the test will be identical as long as the real package name is valid too.
-    Maybe<std::u16string> fullyQualifiedClassName =
-            util::getFullyQualifiedClassName(u"a", attr->value);
+    Maybe<std::string> fullyQualifiedClassName =
+            util::getFullyQualifiedClassName("a", attr->value);
 
-    StringPiece16 qualifiedClassName = fullyQualifiedClassName
+    StringPiece qualifiedClassName = fullyQualifiedClassName
             ? fullyQualifiedClassName.value() : attr->value;
+
     if (!util::isJavaClassName(qualifiedClassName)) {
         diag->error(DiagMessage(el->lineNumber)
                     << "attribute 'android:name' in <"
@@ -47,14 +48,14 @@
 }
 
 static bool optionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
-    if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) {
+    if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, "name")) {
         return nameIsJavaClassName(el, attr, diag);
     }
     return true;
 }
 
 static bool requiredNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
-    if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"name")) {
+    if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, "name")) {
         return nameIsJavaClassName(el, attr, diag);
     }
     diag->error(DiagMessage(el->lineNumber)
@@ -63,7 +64,7 @@
 }
 
 static bool verifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
-    xml::Attribute* attr = el->findAttribute({}, u"package");
+    xml::Attribute* attr = el->findAttribute({}, "package");
     if (!attr) {
         diag->error(DiagMessage(el->lineNumber) << "<manifest> tag is missing 'package' attribute");
         return false;
@@ -100,31 +101,31 @@
 
     // Common intent-filter actions.
     xml::XmlNodeAction intentFilterAction;
-    intentFilterAction[u"action"];
-    intentFilterAction[u"category"];
-    intentFilterAction[u"data"];
+    intentFilterAction["action"];
+    intentFilterAction["category"];
+    intentFilterAction["data"];
 
     // Common meta-data actions.
     xml::XmlNodeAction metaDataAction;
 
     // Manifest actions.
-    xml::XmlNodeAction& manifestAction = (*executor)[u"manifest"];
+    xml::XmlNodeAction& manifestAction = (*executor)["manifest"];
     manifestAction.action(verifyManifest);
     manifestAction.action([&](xml::Element* el) -> bool {
         if (mOptions.versionNameDefault) {
-            if (el->findAttribute(xml::kSchemaAndroid, u"versionName") == nullptr) {
+            if (el->findAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
                 el->attributes.push_back(xml::Attribute{
                         xml::kSchemaAndroid,
-                        u"versionName",
+                        "versionName",
                         mOptions.versionNameDefault.value() });
             }
         }
 
         if (mOptions.versionCodeDefault) {
-            if (el->findAttribute(xml::kSchemaAndroid, u"versionCode") == nullptr) {
+            if (el->findAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
                 el->attributes.push_back(xml::Attribute{
                         xml::kSchemaAndroid,
-                        u"versionCode",
+                        "versionCode",
                         mOptions.versionCodeDefault.value() });
             }
         }
@@ -132,87 +133,87 @@
     });
 
     // Meta tags.
-    manifestAction[u"eat-comment"];
+    manifestAction["eat-comment"];
 
     // Uses-sdk actions.
-    manifestAction[u"uses-sdk"].action([&](xml::Element* el) -> bool {
+    manifestAction["uses-sdk"].action([&](xml::Element* el) -> bool {
         if (mOptions.minSdkVersionDefault &&
-                el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion") == nullptr) {
+                el->findAttribute(xml::kSchemaAndroid, "minSdkVersion") == nullptr) {
             // There was no minSdkVersion defined and we have a default to assign.
             el->attributes.push_back(xml::Attribute{
-                    xml::kSchemaAndroid, u"minSdkVersion",
+                    xml::kSchemaAndroid, "minSdkVersion",
                     mOptions.minSdkVersionDefault.value() });
         }
 
         if (mOptions.targetSdkVersionDefault &&
-                el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion") == nullptr) {
+                el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion") == nullptr) {
             // There was no targetSdkVersion defined and we have a default to assign.
             el->attributes.push_back(xml::Attribute{
-                    xml::kSchemaAndroid, u"targetSdkVersion",
+                    xml::kSchemaAndroid, "targetSdkVersion",
                     mOptions.targetSdkVersionDefault.value() });
         }
         return true;
     });
 
     // Instrumentation actions.
-    manifestAction[u"instrumentation"].action([&](xml::Element* el) -> bool {
+    manifestAction["instrumentation"].action([&](xml::Element* el) -> bool {
         if (!mOptions.renameInstrumentationTargetPackage) {
             return true;
         }
 
-        if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, u"targetPackage")) {
+        if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, "targetPackage")) {
             attr->value = mOptions.renameInstrumentationTargetPackage.value();
         }
         return true;
     });
 
-    manifestAction[u"original-package"];
-    manifestAction[u"protected-broadcast"];
-    manifestAction[u"uses-permission"];
-    manifestAction[u"permission"];
-    manifestAction[u"permission-tree"];
-    manifestAction[u"permission-group"];
+    manifestAction["original-package"];
+    manifestAction["protected-broadcast"];
+    manifestAction["uses-permission"];
+    manifestAction["permission"];
+    manifestAction["permission-tree"];
+    manifestAction["permission-group"];
 
-    manifestAction[u"uses-configuration"];
-    manifestAction[u"uses-feature"];
-    manifestAction[u"supports-screens"];
-    manifestAction[u"compatible-screens"];
-    manifestAction[u"supports-gl-texture"];
+    manifestAction["uses-configuration"];
+    manifestAction["uses-feature"];
+    manifestAction["supports-screens"];
+    manifestAction["compatible-screens"];
+    manifestAction["supports-gl-texture"];
 
     // Application actions.
-    xml::XmlNodeAction& applicationAction = (*executor)[u"manifest"][u"application"];
+    xml::XmlNodeAction& applicationAction = manifestAction["application"];
     applicationAction.action(optionalNameIsJavaClassName);
 
     // Uses library actions.
-    applicationAction[u"uses-library"];
+    applicationAction["uses-library"];
 
     // Meta-data.
-    applicationAction[u"meta-data"] = metaDataAction;
+    applicationAction["meta-data"] = metaDataAction;
 
     // Activity actions.
-    applicationAction[u"activity"].action(requiredNameIsJavaClassName);
-    applicationAction[u"activity"][u"intent-filter"] = intentFilterAction;
-    applicationAction[u"activity"][u"meta-data"] = metaDataAction;
+    applicationAction["activity"].action(requiredNameIsJavaClassName);
+    applicationAction["activity"]["intent-filter"] = intentFilterAction;
+    applicationAction["activity"]["meta-data"] = metaDataAction;
 
     // Activity alias actions.
-    applicationAction[u"activity-alias"][u"intent-filter"] = intentFilterAction;
-    applicationAction[u"activity-alias"][u"meta-data"] = metaDataAction;
+    applicationAction["activity-alias"]["intent-filter"] = intentFilterAction;
+    applicationAction["activity-alias"]["meta-data"] = metaDataAction;
 
     // Service actions.
-    applicationAction[u"service"].action(requiredNameIsJavaClassName);
-    applicationAction[u"service"][u"intent-filter"] = intentFilterAction;
-    applicationAction[u"service"][u"meta-data"] = metaDataAction;
+    applicationAction["service"].action(requiredNameIsJavaClassName);
+    applicationAction["service"]["intent-filter"] = intentFilterAction;
+    applicationAction["service"]["meta-data"] = metaDataAction;
 
     // Receiver actions.
-    applicationAction[u"receiver"].action(requiredNameIsJavaClassName);
-    applicationAction[u"receiver"][u"intent-filter"] = intentFilterAction;
-    applicationAction[u"receiver"][u"meta-data"] = metaDataAction;
+    applicationAction["receiver"].action(requiredNameIsJavaClassName);
+    applicationAction["receiver"]["intent-filter"] = intentFilterAction;
+    applicationAction["receiver"]["meta-data"] = metaDataAction;
 
     // Provider actions.
-    applicationAction[u"provider"].action(requiredNameIsJavaClassName);
-    applicationAction[u"provider"][u"grant-uri-permissions"];
-    applicationAction[u"provider"][u"meta-data"] = metaDataAction;
-    applicationAction[u"provider"][u"path-permissions"];
+    applicationAction["provider"].action(requiredNameIsJavaClassName);
+    applicationAction["provider"]["grant-uri-permissions"];
+    applicationAction["provider"]["meta-data"] = metaDataAction;
+    applicationAction["provider"]["path-permissions"];
     return true;
 }
 
@@ -220,14 +221,14 @@
 public:
     using xml::Visitor::visit;
 
-    explicit FullyQualifiedClassNameVisitor(const StringPiece16& package) : mPackage(package) {
+    explicit FullyQualifiedClassNameVisitor(const StringPiece& package) : mPackage(package) {
     }
 
     void visit(xml::Element* el) override {
         for (xml::Attribute& attr : el->attributes) {
             if (attr.namespaceUri == xml::kSchemaAndroid
                     && mClassAttributes.find(attr.name) != mClassAttributes.end()) {
-                if (Maybe<std::u16string> newValue =
+                if (Maybe<std::string> newValue =
                         util::getFullyQualifiedClassName(mPackage, attr.value)) {
                     attr.value = std::move(newValue.value());
                 }
@@ -239,17 +240,17 @@
     }
 
 private:
-    StringPiece16 mPackage;
-    std::unordered_set<StringPiece16> mClassAttributes = { u"name" };
+    StringPiece mPackage;
+    std::unordered_set<StringPiece> mClassAttributes = { "name" };
 };
 
-static bool renameManifestPackage(const StringPiece16& packageOverride, xml::Element* manifestEl) {
-    xml::Attribute* attr = manifestEl->findAttribute({}, u"package");
+static bool renameManifestPackage(const StringPiece& packageOverride, xml::Element* manifestEl) {
+    xml::Attribute* attr = manifestEl->findAttribute({}, "package");
 
     // We've already verified that the manifest element is present, with a package name specified.
     assert(attr);
 
-    std::u16string originalPackage = std::move(attr->value);
+    std::string originalPackage = std::move(attr->value);
     attr->value = packageOverride.toString();
 
     FullyQualifiedClassNameVisitor visitor(originalPackage);
@@ -259,17 +260,17 @@
 
 bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) {
     xml::Element* root = xml::findRootElement(doc->root.get());
-    if (!root || !root->namespaceUri.empty() || root->name != u"manifest") {
+    if (!root || !root->namespaceUri.empty() || root->name != "manifest") {
         context->getDiagnostics()->error(DiagMessage(doc->file.source)
                                          << "root tag must be <manifest>");
         return false;
     }
 
     if ((mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault)
-            && root->findChild({}, u"uses-sdk") == nullptr) {
+            && root->findChild({}, "uses-sdk") == nullptr) {
         // Auto insert a <uses-sdk> element.
         std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>();
-        usesSdk->name = u"uses-sdk";
+        usesSdk->name = "uses-sdk";
         root->addChild(std::move(usesSdk));
     }
 
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 4d9356a..55b587e 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -27,12 +27,12 @@
 namespace aapt {
 
 struct ManifestFixerOptions {
-    Maybe<std::u16string> minSdkVersionDefault;
-    Maybe<std::u16string> targetSdkVersionDefault;
-    Maybe<std::u16string> renameManifestPackage;
-    Maybe<std::u16string> renameInstrumentationTargetPackage;
-    Maybe<std::u16string> versionNameDefault;
-    Maybe<std::u16string> versionCodeDefault;
+    Maybe<std::string> minSdkVersionDefault;
+    Maybe<std::string> targetSdkVersionDefault;
+    Maybe<std::string> renameManifestPackage;
+    Maybe<std::string> renameInstrumentationTargetPackage;
+    Maybe<std::string> versionNameDefault;
+    Maybe<std::string> versionCodeDefault;
 };
 
 /**
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index f993720..6d52c4c 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -27,25 +27,25 @@
 
     void SetUp() override {
         mContext = test::ContextBuilder()
-                .setCompilationPackage(u"android")
+                .setCompilationPackage("android")
                 .setPackageId(0x01)
-                .setNameManglerPolicy(NameManglerPolicy{ u"android" })
+                .setNameManglerPolicy(NameManglerPolicy{ "android" })
                 .addSymbolSource(test::StaticSymbolSourceBuilder()
-                        .addSymbol(u"@android:attr/package", ResourceId(0x01010000),
+                        .addSymbol("@android:attr/package", ResourceId(0x01010000),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_STRING)
                                         .build())
-                        .addSymbol(u"@android:attr/minSdkVersion", ResourceId(0x01010001),
+                        .addSymbol("@android:attr/minSdkVersion", ResourceId(0x01010001),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_STRING |
                                                      android::ResTable_map::TYPE_INTEGER)
                                         .build())
-                        .addSymbol(u"@android:attr/targetSdkVersion", ResourceId(0x01010002),
+                        .addSymbol("@android:attr/targetSdkVersion", ResourceId(0x01010002),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_STRING |
                                                      android::ResTable_map::TYPE_INTEGER)
                                         .build())
-                        .addSymbol(u"@android:string/str", ResourceId(0x01060000))
+                        .addSymbol("@android:string/str", ResourceId(0x01060000))
                         .build())
                 .build();
     }
@@ -83,7 +83,7 @@
 }
 
 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
-    ManifestFixerOptions options = { std::u16string(u"8"), std::u16string(u"22") };
+    ManifestFixerOptions options = { std::string("8"), std::string("22") };
 
     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -97,14 +97,14 @@
 
     el = xml::findRootElement(doc.get());
     ASSERT_NE(nullptr, el);
-    el = el->findChild({}, u"uses-sdk");
+    el = el->findChild({}, "uses-sdk");
     ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"7", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+    EXPECT_EQ("7", attr->value);
+    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"21", attr->value);
+    EXPECT_EQ("21", attr->value);
 
     doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -115,14 +115,14 @@
 
     el = xml::findRootElement(doc.get());
     ASSERT_NE(nullptr, el);
-    el = el->findChild({}, u"uses-sdk");
+    el = el->findChild({}, "uses-sdk");
     ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"8", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+    EXPECT_EQ("8", attr->value);
+    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"21", attr->value);
+    EXPECT_EQ("21", attr->value);
 
     doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -133,14 +133,14 @@
 
     el = xml::findRootElement(doc.get());
     ASSERT_NE(nullptr, el);
-    el = el->findChild({}, u"uses-sdk");
+    el = el->findChild({}, "uses-sdk");
     ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"8", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+    EXPECT_EQ("8", attr->value);
+    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"22", attr->value);
+    EXPECT_EQ("22", attr->value);
 
     doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -149,19 +149,19 @@
 
     el = xml::findRootElement(doc.get());
     ASSERT_NE(nullptr, el);
-    el = el->findChild({}, u"uses-sdk");
+    el = el->findChild({}, "uses-sdk");
     ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"minSdkVersion");
+    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"8", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, u"targetSdkVersion");
+    EXPECT_EQ("8", attr->value);
+    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(u"22", attr->value);
+    EXPECT_EQ("22", attr->value);
 }
 
 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
     ManifestFixerOptions options;
-    options.renameManifestPackage = std::u16string(u"com.android");
+    options.renameManifestPackage = std::string("com.android");
 
     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -178,40 +178,40 @@
 
     xml::Attribute* attr = nullptr;
 
-    attr = manifestEl->findAttribute({}, u"package");
+    attr = manifestEl->findAttribute({},"package");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::u16string(u"com.android"), attr->value);
+    EXPECT_EQ(std::string("com.android"), attr->value);
 
-    xml::Element* applicationEl = manifestEl->findChild({}, u"application");
+    xml::Element* applicationEl = manifestEl->findChild({}, "application");
     ASSERT_NE(nullptr, applicationEl);
 
-    attr = applicationEl->findAttribute(xml::kSchemaAndroid, u"name");
+    attr = applicationEl->findAttribute(xml::kSchemaAndroid, "name");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::u16string(u"android.MainApplication"), attr->value);
+    EXPECT_EQ(std::string("android.MainApplication"), attr->value);
 
-    attr = applicationEl->findAttribute({}, u"text");
+    attr = applicationEl->findAttribute({}, "text");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::u16string(u"hello"), attr->value);
+    EXPECT_EQ(std::string("hello"), attr->value);
 
     xml::Element* el;
-    el = applicationEl->findChild({}, u"activity");
+    el = applicationEl->findChild({}, "activity");
     ASSERT_NE(nullptr, el);
 
-    attr = el->findAttribute(xml::kSchemaAndroid, u"name");
+    attr = el->findAttribute(xml::kSchemaAndroid, "name");
     ASSERT_NE(nullptr, el);
-    EXPECT_EQ(std::u16string(u"android.activity.Start"), attr->value);
+    EXPECT_EQ(std::string("android.activity.Start"), attr->value);
 
-    el = applicationEl->findChild({}, u"receiver");
+    el = applicationEl->findChild({}, "receiver");
     ASSERT_NE(nullptr, el);
 
-    attr = el->findAttribute(xml::kSchemaAndroid, u"name");
+    attr = el->findAttribute(xml::kSchemaAndroid, "name");
     ASSERT_NE(nullptr, el);
-    EXPECT_EQ(std::u16string(u"com.google.android.Receiver"), attr->value);
+    EXPECT_EQ(std::string("com.google.android.Receiver"), attr->value);
 }
 
 TEST_F(ManifestFixerTest, RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
     ManifestFixerOptions options;
-    options.renameInstrumentationTargetPackage = std::u16string(u"com.android");
+    options.renameInstrumentationTargetPackage = std::string("com.android");
 
     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -223,18 +223,18 @@
     xml::Element* manifestEl = xml::findRootElement(doc.get());
     ASSERT_NE(nullptr, manifestEl);
 
-    xml::Element* instrumentationEl = manifestEl->findChild({}, u"instrumentation");
+    xml::Element* instrumentationEl = manifestEl->findChild({}, "instrumentation");
     ASSERT_NE(nullptr, instrumentationEl);
 
-    xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, u"targetPackage");
+    xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, "targetPackage");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::u16string(u"com.android"), attr->value);
+    EXPECT_EQ(std::string("com.android"), attr->value);
 }
 
 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
     ManifestFixerOptions options;
-    options.versionNameDefault = std::u16string(u"Beta");
-    options.versionCodeDefault = std::u16string(u"0x10000000");
+    options.versionNameDefault = std::string("Beta");
+    options.versionCodeDefault = std::string("0x10000000");
 
     std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
@@ -244,13 +244,13 @@
     xml::Element* manifestEl = xml::findRootElement(doc.get());
     ASSERT_NE(nullptr, manifestEl);
 
-    xml::Attribute* attr = manifestEl->findAttribute(xml::kSchemaAndroid, u"versionName");
+    xml::Attribute* attr = manifestEl->findAttribute(xml::kSchemaAndroid, "versionName");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::u16string(u"Beta"), attr->value);
+    EXPECT_EQ(std::string("Beta"), attr->value);
 
-    attr = manifestEl->findAttribute(xml::kSchemaAndroid, u"versionCode");
+    attr = manifestEl->findAttribute(xml::kSchemaAndroid, "versionCode");
     ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::u16string(u"0x10000000"), attr->value);
+    EXPECT_EQ(std::string("0x10000000"), attr->value);
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/link/PrivateAttributeMover_test.cpp b/tools/aapt2/link/PrivateAttributeMover_test.cpp
index dbe0c92..136e10b 100644
--- a/tools/aapt2/link/PrivateAttributeMover_test.cpp
+++ b/tools/aapt2/link/PrivateAttributeMover_test.cpp
@@ -15,10 +15,7 @@
  */
 
 #include "link/Linkers.h"
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
 
 namespace aapt {
 
@@ -26,45 +23,45 @@
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addSimple(u"@android:attr/publicA")
-            .addSimple(u"@android:attr/privateA")
-            .addSimple(u"@android:attr/publicB")
-            .addSimple(u"@android:attr/privateB")
-            .setSymbolState(u"@android:attr/publicA", ResourceId(0x01010000), SymbolState::kPublic)
-            .setSymbolState(u"@android:attr/publicB", ResourceId(0x01010000), SymbolState::kPublic)
+            .addSimple("@android:attr/publicA")
+            .addSimple("@android:attr/privateA")
+            .addSimple("@android:attr/publicB")
+            .addSimple("@android:attr/privateB")
+            .setSymbolState("@android:attr/publicA", ResourceId(0x01010000), SymbolState::kPublic)
+            .setSymbolState("@android:attr/publicB", ResourceId(0x01010000), SymbolState::kPublic)
             .build();
 
     PrivateAttributeMover mover;
     ASSERT_TRUE(mover.consume(context.get(), table.get()));
 
-    ResourceTablePackage* package = table->findPackage(u"android");
+    ResourceTablePackage* package = table->findPackage("android");
     ASSERT_NE(package, nullptr);
 
     ResourceTableType* type = package->findType(ResourceType::kAttr);
     ASSERT_NE(type, nullptr);
     ASSERT_EQ(type->entries.size(), 2u);
-    EXPECT_NE(type->findEntry(u"publicA"), nullptr);
-    EXPECT_NE(type->findEntry(u"publicB"), nullptr);
+    EXPECT_NE(type->findEntry("publicA"), nullptr);
+    EXPECT_NE(type->findEntry("publicB"), nullptr);
 
     type = package->findType(ResourceType::kAttrPrivate);
     ASSERT_NE(type, nullptr);
     ASSERT_EQ(type->entries.size(), 2u);
-    EXPECT_NE(type->findEntry(u"privateA"), nullptr);
-    EXPECT_NE(type->findEntry(u"privateB"), nullptr);
+    EXPECT_NE(type->findEntry("privateA"), nullptr);
+    EXPECT_NE(type->findEntry("privateB"), nullptr);
 }
 
 TEST(PrivateAttributeMoverTest, LeavePrivateAttributesWhenNoPublicAttributesDefined) {
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addSimple(u"@android:attr/privateA")
-            .addSimple(u"@android:attr/privateB")
+            .addSimple("@android:attr/privateA")
+            .addSimple("@android:attr/privateB")
             .build();
 
     PrivateAttributeMover mover;
     ASSERT_TRUE(mover.consume(context.get(), table.get()));
 
-    ResourceTablePackage* package = table->findPackage(u"android");
+    ResourceTablePackage* package = table->findPackage("android");
     ASSERT_NE(package, nullptr);
 
     ResourceTableType* type = package->findType(ResourceType::kAttr);
diff --git a/tools/aapt2/link/ProductFilter_test.cpp b/tools/aapt2/link/ProductFilter_test.cpp
index f4f756a..811323b 100644
--- a/tools/aapt2/link/ProductFilter_test.cpp
+++ b/tools/aapt2/link/ProductFilter_test.cpp
@@ -15,10 +15,7 @@
  */
 
 #include "link/ProductFilter.h"
-#include "test/Builders.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
 
 namespace aapt {
 
@@ -29,23 +26,23 @@
     const ConfigDescription port = test::parseConfigOrDie("port");
 
     ResourceTable table;
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   land, "",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("land/default.xml")).build(),
                                   context->getDiagnostics()));
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   land, "tablet",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("land/tablet.xml")).build(),
                                   context->getDiagnostics()));
 
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   port, "",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("port/default.xml")).build(),
                                   context->getDiagnostics()));
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   port, "tablet",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("port/tablet.xml")).build(),
@@ -54,13 +51,13 @@
     ProductFilter filter({ "tablet" });
     ASSERT_TRUE(filter.consume(context.get(), &table));
 
-    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/one",
+    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/one",
                                                              land, ""));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/one",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/one",
                                                              land, "tablet"));
-    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/one",
+    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/one",
                                                              port, ""));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/one",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/one",
                                                              port, "tablet"));
 }
 
@@ -68,12 +65,12 @@
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
     ResourceTable table;
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   ConfigDescription::defaultConfig(), "",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("default.xml")).build(),
                                   context->getDiagnostics()));
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   ConfigDescription::defaultConfig(), "tablet",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("tablet.xml")).build(),
@@ -82,10 +79,10 @@
     ProductFilter filter({});
     ASSERT_TRUE(filter.consume(context.get(), &table));
 
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/one",
+    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/one",
                                                              ConfigDescription::defaultConfig(),
                                                              ""));
-    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, u"@android:string/one",
+    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, "@android:string/one",
                                                              ConfigDescription::defaultConfig(),
                                                              "tablet"));
 }
@@ -94,17 +91,17 @@
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
     ResourceTable table;
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   ConfigDescription::defaultConfig(), "",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("default.xml")).build(),
                                   context->getDiagnostics()));
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   ConfigDescription::defaultConfig(), "tablet",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("tablet.xml")).build(),
                                   context->getDiagnostics()));
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   ConfigDescription::defaultConfig(), "no-sdcard",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("no-sdcard.xml")).build(),
@@ -118,12 +115,12 @@
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
     ResourceTable table;
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   ConfigDescription::defaultConfig(), "",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source(".xml")).build(),
                                   context->getDiagnostics()));
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie(u"@android:string/one"),
+    ASSERT_TRUE(table.addResource(test::parseNameOrDie("@android:string/one"),
                                   ConfigDescription::defaultConfig(), "default",
                                   test::ValueBuilder<Id>()
                                           .setSource(Source("default.xml")).build(),
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index 66eb0df..fe886de 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -288,7 +288,7 @@
 
 struct EmptyDeclStack : public xml::IPackageDeclStack {
     Maybe<xml::ExtractedPackage> transformPackageAlias(
-            const StringPiece16& alias, const StringPiece16& localPackage) const override {
+            const StringPiece& alias, const StringPiece& localPackage) const override {
         if (alias.empty()) {
             return xml::ExtractedPackage{ localPackage.toString(), true /* private */ };
         }
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index 76b2309..17c2636 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -23,41 +23,41 @@
 
 TEST(ReferenceLinkerTest, LinkSimpleReferences) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addReference(u"@com.app.test:string/foo", ResourceId(0x7f020000),
-                          u"@com.app.test:string/bar")
+            .setPackageId("com.app.test", 0x7f)
+            .addReference("@com.app.test:string/foo", ResourceId(0x7f020000),
+                          "@com.app.test:string/bar")
 
             // Test use of local reference (w/o package name).
-            .addReference(u"@com.app.test:string/bar", ResourceId(0x7f020001), u"@string/baz")
+            .addReference("@com.app.test:string/bar", ResourceId(0x7f020001), "@string/baz")
 
-            .addReference(u"@com.app.test:string/baz", ResourceId(0x7f020002),
-                          u"@android:string/ok")
+            .addReference("@com.app.test:string/baz", ResourceId(0x7f020002),
+                          "@android:string/ok")
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage(u"com.app.test")
+            .setCompilationPackage("com.app.test")
             .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
+            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
             .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addPublicSymbol(u"@android:string/ok", ResourceId(0x01040034))
+                                     .addPublicSymbol("@android:string/ok", ResourceId(0x01040034))
                                      .build())
             .build();
 
     ReferenceLinker linker;
     ASSERT_TRUE(linker.consume(context.get(), table.get()));
 
-    Reference* ref = test::getValue<Reference>(table.get(), u"@com.app.test:string/foo");
+    Reference* ref = test::getValue<Reference>(table.get(), "@com.app.test:string/foo");
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->id);
     EXPECT_EQ(ref->id.value(), ResourceId(0x7f020001));
 
-    ref = test::getValue<Reference>(table.get(), u"@com.app.test:string/bar");
+    ref = test::getValue<Reference>(table.get(), "@com.app.test:string/bar");
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->id);
     EXPECT_EQ(ref->id.value(), ResourceId(0x7f020002));
 
-    ref = test::getValue<Reference>(table.get(), u"@com.app.test:string/baz");
+    ref = test::getValue<Reference>(table.get(), "@com.app.test:string/baz");
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->id);
     EXPECT_EQ(ref->id.value(), ResourceId(0x01040034));
@@ -65,39 +65,39 @@
 
 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addValue(u"@com.app.test:style/Theme", test::StyleBuilder()
-                    .setParent(u"@android:style/Theme.Material")
-                    .addItem(u"@android:attr/foo", ResourceUtils::tryParseColor(u"#ff00ff"))
-                    .addItem(u"@android:attr/bar", {} /* placeholder */)
+            .setPackageId("com.app.test", 0x7f)
+            .addValue("@com.app.test:style/Theme", test::StyleBuilder()
+                    .setParent("@android:style/Theme.Material")
+                    .addItem("@android:attr/foo", ResourceUtils::tryParseColor("#ff00ff"))
+                    .addItem("@android:attr/bar", {} /* placeholder */)
                     .build())
             .build();
 
     {
         // We need to fill in the value for the attribute android:attr/bar after we build the
         // table, because we need access to the string pool.
-        Style* style = test::getValue<Style>(table.get(), u"@com.app.test:style/Theme");
+        Style* style = test::getValue<Style>(table.get(), "@com.app.test:style/Theme");
         ASSERT_NE(style, nullptr);
         style->entries.back().value = util::make_unique<RawString>(
-                table->stringPool.makeRef(u"one|two"));
+                table->stringPool.makeRef("one|two"));
     }
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage(u"com.app.test")
+            .setCompilationPackage("com.app.test")
             .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
+            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
             .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addPublicSymbol(u"@android:style/Theme.Material",
+                                     .addPublicSymbol("@android:style/Theme.Material",
                                                       ResourceId(0x01060000))
-                                     .addPublicSymbol(u"@android:attr/foo", ResourceId(0x01010001),
+                                     .addPublicSymbol("@android:attr/foo", ResourceId(0x01010001),
                                                       test::AttributeBuilder()
                                                               .setTypeMask(ResTable_map::TYPE_COLOR)
                                                               .build())
-                                     .addPublicSymbol(u"@android:attr/bar", ResourceId(0x01010002),
+                                     .addPublicSymbol("@android:attr/bar", ResourceId(0x01010002),
                                                       test::AttributeBuilder()
                                                               .setTypeMask(ResTable_map::TYPE_FLAGS)
-                                                              .addItem(u"one", 0x01)
-                                                              .addItem(u"two", 0x02)
+                                                              .addItem("one", 0x01)
+                                                              .addItem("two", 0x02)
                                                               .build())
                                      .build())
             .build();
@@ -105,7 +105,7 @@
     ReferenceLinker linker;
     ASSERT_TRUE(linker.consume(context.get(), table.get()));
 
-    Style* style = test::getValue<Style>(table.get(), u"@com.app.test:style/Theme");
+    Style* style = test::getValue<Style>(table.get(), "@com.app.test:style/Theme");
     ASSERT_NE(style, nullptr);
     AAPT_ASSERT_TRUE(style->parent);
     AAPT_ASSERT_TRUE(style->parent.value().id);
@@ -124,11 +124,11 @@
 
 TEST(ReferenceLinkerTest, LinkMangledReferencesAndAttributes) {
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage(u"com.app.test")
+            .setCompilationPackage("com.app.test")
             .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
+            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test", { "com.android.support" } })
             .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addPublicSymbol(u"@com.app.test:attr/com.android.support$foo",
+                                     .addPublicSymbol("@com.app.test:attr/com.android.support$foo",
                                                       ResourceId(0x7f010000),
                                                       test::AttributeBuilder()
                                                               .setTypeMask(ResTable_map::TYPE_COLOR)
@@ -137,17 +137,17 @@
             .build();
 
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addValue(u"@com.app.test:style/Theme", ResourceId(0x7f020000),
-                      test::StyleBuilder().addItem(u"@com.android.support:attr/foo",
-                                                   ResourceUtils::tryParseColor(u"#ff0000"))
+            .setPackageId("com.app.test", 0x7f)
+            .addValue("@com.app.test:style/Theme", ResourceId(0x7f020000),
+                      test::StyleBuilder().addItem("@com.android.support:attr/foo",
+                                                   ResourceUtils::tryParseColor("#ff0000"))
                                           .build())
             .build();
 
     ReferenceLinker linker;
     ASSERT_TRUE(linker.consume(context.get(), table.get()));
 
-    Style* style = test::getValue<Style>(table.get(), u"@com.app.test:style/Theme");
+    Style* style = test::getValue<Style>(table.get(), "@com.app.test:style/Theme");
     ASSERT_NE(style, nullptr);
     ASSERT_EQ(1u, style->entries.size());
     AAPT_ASSERT_TRUE(style->entries.front().key.id);
@@ -156,18 +156,18 @@
 
 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addReference(u"@com.app.test:string/foo", ResourceId(0x7f020000),
-                          u"@android:string/hidden")
+            .setPackageId("com.app.test", 0x7f)
+            .addReference("@com.app.test:string/foo", ResourceId(0x7f020000),
+                          "@android:string/hidden")
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage(u"com.app.test")
+            .setCompilationPackage("com.app.test")
             .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
+            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
             .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addSymbol(u"@android:string/hidden", ResourceId(0x01040034))
+                                     .addSymbol("@android:string/hidden", ResourceId(0x01040034))
                                      .build())
             .build();
 
@@ -177,18 +177,18 @@
 
 TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addReference(u"@com.app.test:string/foo", ResourceId(0x7f020000),
-                          u"@com.app.lib:string/hidden")
+            .setPackageId("com.app.test", 0x7f)
+            .addReference("@com.app.test:string/foo", ResourceId(0x7f020000),
+                          "@com.app.lib:string/hidden")
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage(u"com.app.test")
+            .setCompilationPackage("com.app.test")
             .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test", { u"com.app.lib" } })
+            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test", { "com.app.lib" } })
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
             .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addSymbol(u"@com.app.test:string/com.app.lib$hidden",
+                                     .addSymbol("@com.app.test:string/com.app.lib$hidden",
                                                 ResourceId(0x7f040034))
                                      .build())
 
@@ -200,19 +200,19 @@
 
 TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.test", 0x7f)
-            .addValue(u"@com.app.test:style/Theme", test::StyleBuilder()
-                    .addItem(u"@android:attr/hidden", ResourceUtils::tryParseColor(u"#ff00ff"))
+            .setPackageId("com.app.test", 0x7f)
+            .addValue("@com.app.test:style/Theme", test::StyleBuilder()
+                    .addItem("@android:attr/hidden", ResourceUtils::tryParseColor("#ff00ff"))
                     .build())
             .build();
 
     std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage(u"com.app.test")
+            .setCompilationPackage("com.app.test")
             .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ u"com.app.test" })
+            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
             .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
             .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addSymbol(u"@android:attr/hidden", ResourceId(0x01010001),
+                                     .addSymbol("@android:attr/hidden", ResourceId(0x01010001),
                                                 test::AttributeBuilder()
                                                         .setTypeMask(
                                                                 android::ResTable_map::TYPE_COLOR)
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index 7471e15..2cd2639 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -67,7 +67,7 @@
                 callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
                                FileReference* newFile, FileReference* oldFile) -> bool {
                     // The old file's path points inside the APK, so we can use it as is.
-                    io::IFile* f = collection->findFile(util::utf16ToUtf8(*oldFile->path));
+                    io::IFile* f = collection->findFile(*oldFile->path);
                     if (!f) {
                         mContext->getDiagnostics()->error(DiagMessage(src) << "file '"
                                                           << *oldFile->path
@@ -95,7 +95,7 @@
 /**
  * This will merge and mangle resources from a static library.
  */
-bool TableMerger::mergeAndMangle(const Source& src, const StringPiece16& packageName,
+bool TableMerger::mergeAndMangle(const Source& src, const StringPiece& packageName,
                                  ResourceTable* table, io::IFileCollection* collection) {
     bool error = false;
     for (auto& package : table->packages) {
@@ -112,7 +112,7 @@
         auto callback = [&](const ResourceNameRef& name, const ConfigDescription& config,
                             FileReference* newFile, FileReference* oldFile) -> bool {
             // The old file's path points inside the APK, so we can use it as is.
-            io::IFile* f = collection->findFile(util::utf16ToUtf8(*oldFile->path));
+            io::IFile* f = collection->findFile(*oldFile->path);
             if (!f) {
                 mContext->getDiagnostics()->error(DiagMessage(src) << "file '" << *oldFile->path
                                                   << "' not found");
@@ -159,8 +159,8 @@
         for (auto& srcEntry : srcType->entries) {
             ResourceEntry* dstEntry;
             if (manglePackage) {
-                std::u16string mangledName = NameMangler::mangleEntry(srcPackage->name,
-                                                                      srcEntry->name);
+                std::string mangledName = NameMangler::mangleEntry(srcPackage->name,
+                                                                   srcEntry->name);
                 if (allowNewResources) {
                     dstEntry = dstType->findOrCreateEntry(mangledName);
                 } else {
@@ -275,13 +275,13 @@
     return !error;
 }
 
-std::unique_ptr<FileReference> TableMerger::cloneAndMangleFile(const std::u16string& package,
+std::unique_ptr<FileReference> TableMerger::cloneAndMangleFile(const std::string& package,
                                                                const FileReference& fileRef) {
 
-    StringPiece16 prefix, entry, suffix;
+    StringPiece prefix, entry, suffix;
     if (util::extractResFilePathParts(*fileRef.path, &prefix, &entry, &suffix)) {
-        std::u16string mangledEntry = NameMangler::mangleEntry(package, entry.toString());
-        std::u16string newPath = prefix.toString() + mangledEntry + suffix.toString();
+        std::string mangledEntry = NameMangler::mangleEntry(package, entry.toString());
+        std::string newPath = prefix.toString() + mangledEntry + suffix.toString();
         std::unique_ptr<FileReference> newFileRef = util::make_unique<FileReference>(
                 mMasterTable->stringPool.makeRef(newPath));
         newFileRef->setComment(fileRef.getComment());
@@ -293,8 +293,7 @@
 
 bool TableMerger::mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file, bool overlay) {
     ResourceTable table;
-    std::u16string path = util::utf8ToUtf16(ResourceUtils::buildResourceFileName(fileDesc,
-                                                                                 nullptr));
+    std::string path = ResourceUtils::buildResourceFileName(fileDesc, nullptr);
     std::unique_ptr<FileReference> fileRef = util::make_unique<FileReference>(
             table.stringPool.makeRef(path));
     fileRef->setSource(fileDesc.source);
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index 80c2a5e..6997f93 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -59,7 +59,7 @@
      */
     TableMerger(IAaptContext* context, ResourceTable* outTable, const TableMergerOptions& options);
 
-    const std::set<std::u16string>& getMergedPackages() const {
+    const std::set<std::string>& getMergedPackages() const {
         return mMergedPackages;
     }
 
@@ -81,7 +81,7 @@
      * Merges resources from the given package, mangling the name. This is for static libraries.
      * An io::IFileCollection is needed in order to find the referenced Files and process them.
      */
-    bool mergeAndMangle(const Source& src, const StringPiece16& package, ResourceTable* table,
+    bool mergeAndMangle(const Source& src, const StringPiece& package, ResourceTable* table,
                         io::IFileCollection* collection);
 
     /**
@@ -104,7 +104,7 @@
     TableMergerOptions mOptions;
     ResourceTablePackage* mMasterPackage;
 
-    std::set<std::u16string> mMergedPackages;
+    std::set<std::string> mMergedPackages;
 
     bool mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file, bool overlay);
 
@@ -117,7 +117,7 @@
                  const bool allowNewResources,
                  FileMergeCallback callback);
 
-    std::unique_ptr<FileReference> cloneAndMangleFile(const std::u16string& package,
+    std::unique_ptr<FileReference> cloneAndMangleFile(const std::string& package,
                                                       const FileReference& value);
 };
 
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index 4a80d3f..1697217 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -30,13 +30,13 @@
     void SetUp() override {
         mContext = test::ContextBuilder()
                 // We are compiling this package.
-                .setCompilationPackage(u"com.app.a")
+                .setCompilationPackage("com.app.a")
 
                 // Merge all packages that have this package ID.
                 .setPackageId(0x7f)
 
                 // Mangle all packages that do not have this package name.
-                .setNameManglerPolicy(NameManglerPolicy{ u"com.app.a", { u"com.app.b" } })
+                .setNameManglerPolicy(NameManglerPolicy{ "com.app.a", { "com.app.b" } })
 
                 .build();
     }
@@ -44,17 +44,17 @@
 
 TEST_F(TableMergerTest, SimpleMerge) {
     std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.a", 0x7f)
-            .addReference(u"@com.app.a:id/foo", u"@com.app.a:id/bar")
-            .addReference(u"@com.app.a:id/bar", u"@com.app.b:id/foo")
-            .addValue(u"@com.app.a:styleable/view", test::StyleableBuilder()
-                    .addItem(u"@com.app.b:id/foo")
+            .setPackageId("com.app.a", 0x7f)
+            .addReference("@com.app.a:id/foo", "@com.app.a:id/bar")
+            .addReference("@com.app.a:id/bar", "@com.app.b:id/foo")
+            .addValue("@com.app.a:styleable/view", test::StyleableBuilder()
+                    .addItem("@com.app.b:id/foo")
                     .build())
             .build();
 
     std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.b", 0x7f)
-            .addSimple(u"@com.app.b:id/foo")
+            .setPackageId("com.app.b", 0x7f)
+            .addSimple("@com.app.b:id/foo")
             .build();
 
     ResourceTable finalTable;
@@ -62,20 +62,20 @@
     io::FileCollection collection;
 
     ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_TRUE(merger.mergeAndMangle({}, u"com.app.b", tableB.get(), &collection));
+    ASSERT_TRUE(merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
 
-    EXPECT_TRUE(merger.getMergedPackages().count(u"com.app.b") != 0);
+    EXPECT_TRUE(merger.getMergedPackages().count("com.app.b") != 0);
 
     // Entries from com.app.a should not be mangled.
-    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie(u"@com.app.a:id/foo")));
-    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie(u"@com.app.a:id/bar")));
-    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie(u"@com.app.a:styleable/view")));
+    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("@com.app.a:id/foo")));
+    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("@com.app.a:id/bar")));
+    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("@com.app.a:styleable/view")));
 
     // The unmangled name should not be present.
-    AAPT_EXPECT_FALSE(finalTable.findResource(test::parseNameOrDie(u"@com.app.b:id/foo")));
+    AAPT_EXPECT_FALSE(finalTable.findResource(test::parseNameOrDie("@com.app.b:id/foo")));
 
     // Look for the mangled name.
-    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie(u"@com.app.a:id/com.app.b$foo")));
+    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("@com.app.a:id/com.app.b$foo")));
 }
 
 TEST_F(TableMergerTest, MergeFile) {
@@ -86,17 +86,17 @@
 
     ResourceFile fileDesc;
     fileDesc.config = test::parseConfigOrDie("hdpi-v4");
-    fileDesc.name = test::parseNameOrDie(u"@layout/main");
+    fileDesc.name = test::parseNameOrDie("@layout/main");
     fileDesc.source = Source("res/layout-hdpi/main.xml");
     test::TestFile testFile("path/to/res/layout-hdpi/main.xml.flat");
 
     ASSERT_TRUE(merger.mergeFile(fileDesc, &testFile));
 
     FileReference* file = test::getValueForConfig<FileReference>(&finalTable,
-                                                                 u"@com.app.a:layout/main",
+                                                                 "@com.app.a:layout/main",
                                                                  test::parseConfigOrDie("hdpi-v4"));
     ASSERT_NE(nullptr, file);
-    EXPECT_EQ(std::u16string(u"res/layout-hdpi-v4/main.xml"), *file->path);
+    EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path);
 }
 
 TEST_F(TableMergerTest, MergeFileOverlay) {
@@ -106,7 +106,7 @@
     TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
 
     ResourceFile fileDesc;
-    fileDesc.name = test::parseNameOrDie(u"@xml/foo");
+    fileDesc.name = test::parseNameOrDie("@xml/foo");
     test::TestFile fileA("path/to/fileA.xml.flat");
     test::TestFile fileB("path/to/fileB.xml.flat");
 
@@ -116,12 +116,12 @@
 
 TEST_F(TableMergerTest, MergeFileReferences) {
     std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.a", 0x7f)
-            .addFileReference(u"@com.app.a:xml/file", u"res/xml/file.xml")
+            .setPackageId("com.app.a", 0x7f)
+            .addFileReference("@com.app.a:xml/file", "res/xml/file.xml")
             .build();
     std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.b", 0x7f)
-            .addFileReference(u"@com.app.b:xml/file", u"res/xml/file.xml")
+            .setPackageId("com.app.b", 0x7f)
+            .addFileReference("@com.app.b:xml/file", "res/xml/file.xml")
             .build();
 
     ResourceTable finalTable;
@@ -130,25 +130,25 @@
     collection.insertFile("res/xml/file.xml");
 
     ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_TRUE(merger.mergeAndMangle({}, u"com.app.b", tableB.get(), &collection));
+    ASSERT_TRUE(merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
 
-    FileReference* f = test::getValue<FileReference>(&finalTable, u"@com.app.a:xml/file");
+    FileReference* f = test::getValue<FileReference>(&finalTable, "@com.app.a:xml/file");
     ASSERT_NE(f, nullptr);
-    EXPECT_EQ(std::u16string(u"res/xml/file.xml"), *f->path);
+    EXPECT_EQ(std::string("res/xml/file.xml"), *f->path);
 
-    f = test::getValue<FileReference>(&finalTable, u"@com.app.a:xml/com.app.b$file");
+    f = test::getValue<FileReference>(&finalTable, "@com.app.a:xml/com.app.b$file");
     ASSERT_NE(f, nullptr);
-    EXPECT_EQ(std::u16string(u"res/xml/com.app.b$file.xml"), *f->path);
+    EXPECT_EQ(std::string("res/xml/com.app.b$file.xml"), *f->path);
 }
 
 TEST_F(TableMergerTest, OverrideResourceWithOverlay) {
     std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x00)
-            .addValue(u"@bool/foo", ResourceUtils::tryParseBool(u"true"))
+            .setPackageId("", 0x00)
+            .addValue("@bool/foo", ResourceUtils::tryParseBool("true"))
             .build();
     std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x00)
-            .addValue(u"@bool/foo", ResourceUtils::tryParseBool(u"false"))
+            .setPackageId("", 0x00)
+            .addValue("@bool/foo", ResourceUtils::tryParseBool("false"))
             .build();
 
     ResourceTable finalTable;
@@ -159,19 +159,19 @@
     ASSERT_TRUE(merger.merge({}, base.get()));
     ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
 
-    BinaryPrimitive* foo = test::getValue<BinaryPrimitive>(&finalTable, u"@com.app.a:bool/foo");
+    BinaryPrimitive* foo = test::getValue<BinaryPrimitive>(&finalTable, "@com.app.a:bool/foo");
     ASSERT_NE(nullptr, foo);
     EXPECT_EQ(0x0u, foo->value.data);
 }
 
 TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
     std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x7f)
-            .setSymbolState(u"@bool/foo", {}, SymbolState::kUndefined)
+            .setPackageId("", 0x7f)
+            .setSymbolState("@bool/foo", {}, SymbolState::kUndefined)
             .build();
     std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x7f)
-            .addValue(u"@bool/foo", ResourceUtils::tryParseBool(u"true"))
+            .setPackageId("", 0x7f)
+            .addValue("@bool/foo", ResourceUtils::tryParseBool("true"))
             .build();
 
     ResourceTable finalTable;
@@ -183,11 +183,11 @@
 
 TEST_F(TableMergerTest, MergeAddResourceFromOverlayWithAutoAddOverlay) {
     std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x7f)
+            .setPackageId("", 0x7f)
             .build();
     std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x7f)
-            .addValue(u"@bool/foo", ResourceUtils::tryParseBool(u"true"))
+            .setPackageId("", 0x7f)
+            .addValue("@bool/foo", ResourceUtils::tryParseBool("true"))
             .build();
 
     ResourceTable finalTable;
@@ -201,11 +201,11 @@
 
 TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
     std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x7f)
+            .setPackageId("", 0x7f)
             .build();
     std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId(u"", 0x7f)
-            .addValue(u"@bool/foo", ResourceUtils::tryParseBool(u"true"))
+            .setPackageId("", 0x7f)
+            .addValue("@bool/foo", ResourceUtils::tryParseBool("true"))
             .build();
 
     ResourceTable finalTable;
diff --git a/tools/aapt2/link/VersionCollapser_test.cpp b/tools/aapt2/link/VersionCollapser_test.cpp
index b5387fe..4113450 100644
--- a/tools/aapt2/link/VersionCollapser_test.cpp
+++ b/tools/aapt2/link/VersionCollapser_test.cpp
@@ -22,7 +22,7 @@
 template <typename T>
 using uptr = std::unique_ptr<T>;
 
-static uptr<ResourceTable> buildTableWithConfigs(const StringPiece16& name,
+static uptr<ResourceTable> buildTableWithConfigs(const StringPiece& name,
                                                  std::initializer_list<std::string> list) {
     test::ResourceTableBuilder builder;
     for (const std::string& item : list) {
@@ -34,7 +34,7 @@
 TEST(VersionCollapserTest, CollapseVersions) {
     uptr<IAaptContext> context = test::ContextBuilder().setMinSdkVersion(7).build();
 
-    const StringPiece16 resName = u"@android:string/foo";
+    const StringPiece resName = "@android:string/foo";
 
     uptr<ResourceTable> table =
             buildTableWithConfigs(resName,
@@ -64,7 +64,7 @@
 TEST(VersionCollapserTest, CollapseVersionsWhenMinSdkIsHighest) {
     uptr<IAaptContext> context = test::ContextBuilder().setMinSdkVersion(26).build();
 
-    const StringPiece16 resName = u"@android:string/foo";
+    const StringPiece resName = "@android:string/foo";
 
     uptr<ResourceTable> table =
                 buildTableWithConfigs(resName,
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 568bc74..02af5e3 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -81,7 +81,7 @@
                     xml::extractPackageFromNamespace(attr.namespaceUri);
             if (maybePackage) {
                 // There is a valid package name for this attribute. We will look this up.
-                StringPiece16 package = maybePackage.value().package;
+                StringPiece package = maybePackage.value().package;
                 if (package.empty()) {
                     // Empty package means the 'current' or 'local' package.
                     package = mContext->getCompilationPackage();
diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp
index af9098b..d48de42 100644
--- a/tools/aapt2/link/XmlReferenceLinker_test.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp
@@ -14,7 +14,6 @@
  * limitations under the License.
  */
 
-#include <test/Context.h>
 #include "link/Linkers.h"
 #include "test/Test.h"
 
@@ -24,44 +23,44 @@
 public:
     void SetUp() override {
         mContext = test::ContextBuilder()
-                .setCompilationPackage(u"com.app.test")
+                .setCompilationPackage("com.app.test")
                 .setNameManglerPolicy(
-                        NameManglerPolicy{ u"com.app.test", { u"com.android.support" } })
+                        NameManglerPolicy{ "com.app.test", { "com.android.support" } })
                 .addSymbolSource(test::StaticSymbolSourceBuilder()
-                        .addPublicSymbol(u"@android:attr/layout_width", ResourceId(0x01010000),
+                        .addPublicSymbol("@android:attr/layout_width", ResourceId(0x01010000),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_ENUM |
                                                      android::ResTable_map::TYPE_DIMENSION)
-                                        .addItem(u"match_parent", 0xffffffff)
+                                        .addItem("match_parent", 0xffffffff)
                                         .build())
-                        .addPublicSymbol(u"@android:attr/background", ResourceId(0x01010001),
+                        .addPublicSymbol("@android:attr/background", ResourceId(0x01010001),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
-                        .addPublicSymbol(u"@android:attr/attr", ResourceId(0x01010002),
+                        .addPublicSymbol("@android:attr/attr", ResourceId(0x01010002),
                                    test::AttributeBuilder().build())
-                        .addPublicSymbol(u"@android:attr/text", ResourceId(0x01010003),
+                        .addPublicSymbol("@android:attr/text", ResourceId(0x01010003),
                                    test::AttributeBuilder()
                                         .setTypeMask(android::ResTable_map::TYPE_STRING)
                                         .build())
 
                          // Add one real symbol that was introduces in v21
-                        .addPublicSymbol(u"@android:attr/colorAccent", ResourceId(0x01010435),
+                        .addPublicSymbol("@android:attr/colorAccent", ResourceId(0x01010435),
                                    test::AttributeBuilder().build())
 
                         // Private symbol.
-                        .addSymbol(u"@android:color/hidden", ResourceId(0x01020001))
+                        .addSymbol("@android:color/hidden", ResourceId(0x01020001))
 
-                        .addPublicSymbol(u"@android:id/id", ResourceId(0x01030000))
-                        .addSymbol(u"@com.app.test:id/id", ResourceId(0x7f030000))
-                        .addSymbol(u"@com.app.test:color/green", ResourceId(0x7f020000))
-                        .addSymbol(u"@com.app.test:color/red", ResourceId(0x7f020001))
-                        .addSymbol(u"@com.app.test:attr/colorAccent", ResourceId(0x7f010000),
+                        .addPublicSymbol("@android:id/id", ResourceId(0x01030000))
+                        .addSymbol("@com.app.test:id/id", ResourceId(0x7f030000))
+                        .addSymbol("@com.app.test:color/green", ResourceId(0x7f020000))
+                        .addSymbol("@com.app.test:color/red", ResourceId(0x7f020001))
+                        .addSymbol("@com.app.test:attr/colorAccent", ResourceId(0x7f010000),
                                    test::AttributeBuilder()
                                        .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
-                        .addPublicSymbol(u"@com.app.test:attr/com.android.support$colorAccent",
+                        .addPublicSymbol("@com.app.test:attr/com.android.support$colorAccent",
                                    ResourceId(0x7f010001), test::AttributeBuilder()
                                        .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
-                        .addPublicSymbol(u"@com.app.test:attr/attr", ResourceId(0x7f010002),
+                        .addPublicSymbol("@com.app.test:attr/attr", ResourceId(0x7f010002),
                                    test::AttributeBuilder().build())
                         .build())
                 .build();
@@ -85,8 +84,7 @@
     xml::Element* viewEl = xml::findRootElement(doc.get());
     ASSERT_NE(viewEl, nullptr);
 
-    xml::Attribute* xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android",
-                                                    u"layout_width");
+    xml::Attribute* xmlAttr = viewEl->findAttribute(xml::kSchemaAndroid, "layout_width");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
@@ -94,7 +92,7 @@
     ASSERT_NE(xmlAttr->compiledValue, nullptr);
     ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
 
-    xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android", u"background");
+    xmlAttr = viewEl->findAttribute(xml::kSchemaAndroid, "background");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
@@ -103,17 +101,17 @@
     Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
     ASSERT_NE(ref, nullptr);
     AAPT_ASSERT_TRUE(ref->name);
-    EXPECT_EQ(ref->name.value(), test::parseNameOrDie(u"@color/green")); // Make sure the name
-                                                                         // didn't change.
+    EXPECT_EQ(ref->name.value(), test::parseNameOrDie("@color/green")); // Make sure the name
+                                                                        // didn't change.
     AAPT_ASSERT_TRUE(ref->id);
     EXPECT_EQ(ref->id.value(), ResourceId(0x7f020000));
 
-    xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android", u"text");
+    xmlAttr = viewEl->findAttribute(xml::kSchemaAndroid, "text");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     ASSERT_FALSE(xmlAttr->compiledValue);   // Strings don't get compiled for memory sake.
 
-    xmlAttr = viewEl->findAttribute(u"", u"class");
+    xmlAttr = viewEl->findAttribute("", "class");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_FALSE(xmlAttr->compiledAttribute);
     ASSERT_EQ(xmlAttr->compiledValue, nullptr);
@@ -159,7 +157,7 @@
     ASSERT_NE(viewEl, nullptr);
 
     xml::Attribute* xmlAttr = viewEl->findAttribute(
-            u"http://schemas.android.com/apk/res/com.android.support", u"colorAccent");
+            xml::buildPackageNamespace("com.android.support"), "colorAccent");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
@@ -178,8 +176,7 @@
     xml::Element* viewEl = xml::findRootElement(doc.get());
     ASSERT_NE(viewEl, nullptr);
 
-    xml::Attribute* xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res-auto",
-                                                    u"colorAccent");
+    xml::Attribute* xmlAttr = viewEl->findAttribute(xml::kSchemaAuto, "colorAccent");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
@@ -206,8 +203,7 @@
     ASSERT_NE(viewEl, nullptr);
 
     // All attributes and references in this element should be referring to "android" (0x01).
-    xml::Attribute* xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/android",
-                                                    u"attr");
+    xml::Attribute* xmlAttr = viewEl->findAttribute(xml::kSchemaAndroid, "attr");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
@@ -222,7 +218,7 @@
     ASSERT_NE(viewEl, nullptr);
 
     // All attributes and references in this element should be referring to "com.app.test" (0x7f).
-    xmlAttr = viewEl->findAttribute(u"http://schemas.android.com/apk/res/com.app.test", u"attr");
+    xmlAttr = viewEl->findAttribute(xml::buildPackageNamespace("com.app.test"), "attr");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
@@ -245,8 +241,8 @@
     ASSERT_NE(viewEl, nullptr);
 
     // All attributes and references in this element should be referring to "com.app.test" (0x7f).
-    xml::Attribute* xmlAttr = viewEl->findAttribute(
-            u"http://schemas.android.com/apk/res/com.app.test", u"attr");
+    xml::Attribute* xmlAttr = viewEl->findAttribute(xml::buildPackageNamespace("com.app.test"),
+                                                    "attr");
     ASSERT_NE(xmlAttr, nullptr);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
     AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
diff --git a/tools/aapt2/process/IResourceTableConsumer.h b/tools/aapt2/process/IResourceTableConsumer.h
index 762725d..69b7d92 100644
--- a/tools/aapt2/process/IResourceTableConsumer.h
+++ b/tools/aapt2/process/IResourceTableConsumer.h
@@ -37,7 +37,7 @@
 
     virtual SymbolTable* getExternalSymbols() = 0;
     virtual IDiagnostics* getDiagnostics() = 0;
-    virtual const std::u16string& getCompilationPackage() = 0;
+    virtual const std::string& getCompilationPackage() = 0;
     virtual uint8_t getPackageId() = 0;
     virtual NameMangler* getNameMangler() = 0;
     virtual bool verbose() = 0;
diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp
index eaaf06f..6c506df 100644
--- a/tools/aapt2/process/SymbolTable.cpp
+++ b/tools/aapt2/process/SymbolTable.cpp
@@ -16,6 +16,7 @@
 
 #include "ConfigDescription.h"
 #include "Resource.h"
+#include "ResourceUtils.h"
 #include "ValueVisitor.h"
 #include "process/SymbolTable.h"
 #include "util/Util.h"
@@ -84,7 +85,7 @@
 const SymbolTable::Symbol* SymbolTable::findByReference(const Reference& ref) {
     // First try the ID. This is because when we lookup by ID, we only fill in the ID cache.
     // Looking up by name fills in the name and ID cache. So a cache miss will cause a failed
-    // ID lookup, then a successfull name lookup. Subsequent look ups will hit immediately
+    // ID lookup, then a successful name lookup. Subsequent look ups will hit immediately
     // because the ID is cached too.
     //
     // If we looked up by name first, a cache miss would mean we failed to lookup by name, then
@@ -184,18 +185,13 @@
                 return nullptr;
             }
 
-            const ResourceType* parsedType = parseResourceType(
-                    StringPiece16(entryName.type, entryName.typeLen));
-            if (!parsedType) {
-                table.unlockBag(entry);
+            Maybe<ResourceName> parsedName = ResourceUtils::toResourceName(entryName);
+            if (!parsedName) {
                 return nullptr;
             }
 
             Attribute::Symbol symbol;
-            symbol.symbol.name = ResourceName(
-                    StringPiece16(entryName.package, entryName.packageLen),
-                    *parsedType,
-                    StringPiece16(entryName.name, entryName.nameLen));
+            symbol.symbol.name = parsedName.value();
             symbol.symbol.id = ResourceId(mapEntry.name.ident);
             symbol.value = mapEntry.value.data;
             s->attribute->symbols.push_back(std::move(symbol));
@@ -208,11 +204,15 @@
 std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findByName(
         const ResourceName& name) {
     const android::ResTable& table = mAssets.getResources(false);
-    StringPiece16 typeStr = toString(name.type);
+
+    const std::u16string package16 = util::utf8ToUtf16(name.package);
+    const std::u16string type16 = util::utf8ToUtf16(toString(name.type));
+    const std::u16string entry16 = util::utf8ToUtf16(name.entry);
+
     uint32_t typeSpecFlags = 0;
-    ResourceId resId = table.identifierForName(name.entry.data(), name.entry.size(),
-                                               typeStr.data(), typeStr.size(),
-                                               name.package.data(), name.package.size(),
+    ResourceId resId = table.identifierForName(entry16.data(), entry16.size(),
+                                               type16.data(), type16.size(),
+                                               package16.data(), package16.size(),
                                                &typeSpecFlags);
     if (!resId.isValid()) {
         return {};
@@ -238,37 +238,7 @@
     if (!table.getResourceName(id.id, true, &resName)) {
         return {};
     }
-
-    ResourceName name;
-    if (resName.package) {
-        name.package = StringPiece16(resName.package, resName.packageLen).toString();
-    }
-
-    const ResourceType* type;
-    if (resName.type) {
-        type = parseResourceType(StringPiece16(resName.type, resName.typeLen));
-
-    } else if (resName.type8) {
-        type = parseResourceType(util::utf8ToUtf16(StringPiece(resName.type8, resName.typeLen)));
-    } else {
-        return {};
-    }
-
-    if (!type) {
-        return {};
-    }
-
-    name.type = *type;
-
-    if (resName.name) {
-        name.entry = StringPiece16(resName.name, resName.nameLen).toString();
-    } else if (resName.name8) {
-        name.entry = util::utf8ToUtf16(StringPiece(resName.name8, resName.nameLen));
-    } else {
-        return {};
-    }
-
-    return name;
+    return ResourceUtils::toResourceName(resName);
 }
 
 std::unique_ptr<SymbolTable::Symbol> AssetManagerSymbolSource::findById(ResourceId id) {
diff --git a/tools/aapt2/process/SymbolTable.h b/tools/aapt2/process/SymbolTable.h
index e684bb0..43f4dd7 100644
--- a/tools/aapt2/process/SymbolTable.h
+++ b/tools/aapt2/process/SymbolTable.h
@@ -34,7 +34,7 @@
 namespace aapt {
 
 inline android::hash_t hash_type(const ResourceName& name) {
-    std::hash<std::u16string> strHash;
+    std::hash<std::string> strHash;
     android::hash_t hash = 0;
     hash = android::JenkinsHashMix(hash, (uint32_t) strHash(name.package));
     hash = android::JenkinsHashMix(hash, (uint32_t) name.type);
diff --git a/tools/aapt2/process/SymbolTable_test.cpp b/tools/aapt2/process/SymbolTable_test.cpp
index 34f31be..6866974 100644
--- a/tools/aapt2/process/SymbolTable_test.cpp
+++ b/tools/aapt2/process/SymbolTable_test.cpp
@@ -21,31 +21,31 @@
 
 TEST(ResourceTableSymbolSourceTest, FindSymbols) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addSimple(u"@android:id/foo", ResourceId(0x01020000))
-            .addSimple(u"@android:id/bar")
-            .addValue(u"@android:attr/foo", ResourceId(0x01010000),
+            .addSimple("@android:id/foo", ResourceId(0x01020000))
+            .addSimple("@android:id/bar")
+            .addValue("@android:attr/foo", ResourceId(0x01010000),
                       test::AttributeBuilder().build())
             .build();
 
     ResourceTableSymbolSource symbolSource(table.get());
-    EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie(u"@android:id/foo")));
-    EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie(u"@android:id/bar")));
+    EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie("@android:id/foo")));
+    EXPECT_NE(nullptr, symbolSource.findByName(test::parseNameOrDie("@android:id/bar")));
 
     std::unique_ptr<SymbolTable::Symbol> s = symbolSource.findByName(
-            test::parseNameOrDie(u"@android:attr/foo"));
+            test::parseNameOrDie("@android:attr/foo"));
     ASSERT_NE(nullptr, s);
     EXPECT_NE(nullptr, s->attribute);
 }
 
 TEST(ResourceTableSymbolSourceTest, FindPrivateAttrSymbol) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addValue(u"@android:^attr-private/foo", ResourceId(0x01010000),
+            .addValue("@android:^attr-private/foo", ResourceId(0x01010000),
                       test::AttributeBuilder().build())
             .build();
 
     ResourceTableSymbolSource symbolSource(table.get());
     std::unique_ptr<SymbolTable::Symbol> s = symbolSource.findByName(
-                test::parseNameOrDie(u"@android:attr/foo"));
+                test::parseNameOrDie("@android:attr/foo"));
     ASSERT_NE(nullptr, s);
     EXPECT_NE(nullptr, s->attribute);
 }
diff --git a/tools/aapt2/proto/ProtoHelpers.cpp b/tools/aapt2/proto/ProtoHelpers.cpp
index 99981c5..2aa8aa5 100644
--- a/tools/aapt2/proto/ProtoHelpers.cpp
+++ b/tools/aapt2/proto/ProtoHelpers.cpp
@@ -33,7 +33,7 @@
 }
 
 void serializeSourceToPb(const Source& source, StringPool* srcPool, pb::Source* outPbSource) {
-    StringPool::Ref ref = srcPool->makeRef(util::utf8ToUtf16(source.path));
+    StringPool::Ref ref = srcPool->makeRef(source.path);
     outPbSource->set_path_idx(static_cast<uint32_t>(ref.getIndex()));
     if (source.line) {
         outPbSource->set_line_no(static_cast<uint32_t>(source.line.value()));
@@ -43,7 +43,7 @@
 void deserializeSourceFromPb(const pb::Source& pbSource, const android::ResStringPool& srcPool,
                              Source* outSource) {
     if (pbSource.has_path_idx()) {
-        outSource->path = util::getString8(srcPool, pbSource.path_idx()).toString();
+        outSource->path = util::getString(srcPool, pbSource.path_idx());
     }
 
     if (pbSource.has_line_no()) {
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index a7798e7..98ff87f 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -70,10 +70,9 @@
 
         std::map<ResourceId, ResourceNameRef> idIndex;
 
-        ResourceTablePackage* pkg = table->createPackage(
-                util::utf8ToUtf16(pbPackage.package_name()), id);
+        ResourceTablePackage* pkg = table->createPackage(pbPackage.package_name(), id);
         for (const pb::Type& pbType : pbPackage.types()) {
-            const ResourceType* resType = parseResourceType(util::utf8ToUtf16(pbType.name()));
+            const ResourceType* resType = parseResourceType(pbType.name());
             if (!resType) {
                 mDiag->error(DiagMessage(mSource) << "unknown type '" << pbType.name() << "'");
                 return {};
@@ -82,7 +81,7 @@
             ResourceTableType* type = pkg->findOrCreateType(*resType);
 
             for (const pb::Entry& pbEntry : pbType.entries()) {
-                ResourceEntry* entry = type->findOrCreateEntry(util::utf8ToUtf16(pbEntry.name()));
+                ResourceEntry* entry = type->findOrCreateEntry(pbEntry.name());
 
                 // Deserialize the symbol status (public/private with source and comments).
                 if (pbEntry.has_symbol_status()) {
@@ -93,7 +92,7 @@
                     }
 
                     if (pbStatus.has_comment()) {
-                        entry->symbolStatus.comment = util::utf8ToUtf16(pbStatus.comment());
+                        entry->symbolStatus.comment = pbStatus.comment();
                     }
 
                     SymbolState visibility = deserializeVisibilityFromPb(pbStatus.visibility());
@@ -179,14 +178,14 @@
 
         } else if (pbItem.has_str()) {
             const uint32_t idx = pbItem.str().idx();
-            StringPiece16 str = util::getString(*mValuePool, idx);
+            const std::string str = util::getString(*mValuePool, idx);
 
             const android::ResStringPool_span* spans = mValuePool->styleAt(idx);
             if (spans && spans->name.index != android::ResStringPool_span::END) {
-                StyleString styleStr = { str.toString() };
+                StyleString styleStr = { str };
                 while (spans->name.index != android::ResStringPool_span::END) {
                     styleStr.spans.push_back(Span{
-                            util::getString(*mValuePool, spans->name.index).toString(),
+                            util::getString(*mValuePool, spans->name.index),
                             spans->firstChar,
                             spans->lastChar
                     });
@@ -200,13 +199,13 @@
 
         } else if (pbItem.has_raw_str()) {
             const uint32_t idx = pbItem.raw_str().idx();
-            StringPiece16 str = util::getString(*mValuePool, idx);
+            const std::string str = util::getString(*mValuePool, idx);
             return util::make_unique<RawString>(
                     pool->makeRef(str, StringPool::Context{ 1, config }));
 
         } else if (pbItem.has_file()) {
             const uint32_t idx = pbItem.file().path_idx();
-            StringPiece16 str = util::getString(*mValuePool, idx);
+            const std::string str = util::getString(*mValuePool, idx);
             return util::make_unique<FileReference>(
                     pool->makeRef(str, StringPool::Context{ 0, config }));
 
@@ -351,7 +350,7 @@
         }
 
         if (pbRef.has_symbol_idx()) {
-            StringPiece16 strSymbol = util::getString(*mSymbolPool, pbRef.symbol_idx());
+            const std::string strSymbol = util::getString(*mSymbolPool, pbRef.symbol_idx());
             ResourceNameRef nameRef;
             if (!ResourceUtils::parseResourceName(strSymbol, &nameRef, nullptr)) {
                 mDiag->error(DiagMessage(mSource) << "invalid reference name '"
@@ -373,7 +372,7 @@
         }
 
         if (pbItem.has_comment()) {
-            outValue->setComment(util::utf8ToUtf16(pbItem.comment()));
+            outValue->setComment(pbItem.comment());
         }
     }
 
@@ -446,8 +445,7 @@
     ResourceNameRef nameRef;
 
     // Need to create an lvalue here so that nameRef can point to something real.
-    std::u16string utf16Name = util::utf8ToUtf16(pbFile.resource_name());
-    if (!ResourceUtils::parseResourceName(utf16Name, &nameRef)) {
+    if (!ResourceUtils::parseResourceName(pbFile.resource_name(), &nameRef)) {
         diag->error(DiagMessage(source) << "invalid resource name in compiled file header: "
                     << pbFile.resource_name());
         return {};
@@ -458,8 +456,7 @@
 
     for (const pb::CompiledFile_Symbol& pbSymbol : pbFile.exported_symbols()) {
         // Need to create an lvalue here so that nameRef can point to something real.
-        utf16Name = util::utf8ToUtf16(pbSymbol.resource_name());
-        if (!ResourceUtils::parseResourceName(utf16Name, &nameRef)) {
+        if (!ResourceUtils::parseResourceName(pbSymbol.resource_name(), &nameRef)) {
             diag->error(DiagMessage(source) << "invalid resource name for exported symbol in "
                                                "compiled file header: "
                                             << pbFile.resource_name());
diff --git a/tools/aapt2/proto/TableProtoSerializer.cpp b/tools/aapt2/proto/TableProtoSerializer.cpp
index 5d1b72b..425fca6 100644
--- a/tools/aapt2/proto/TableProtoSerializer.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer.cpp
@@ -171,7 +171,7 @@
     void serializeItemCommonToPb(const Item& item, T* pbItem) {
         serializeSourceToPb(item.getSource(), mSourcePool, pbItem->mutable_source());
         if (!item.getComment().empty()) {
-            pbItem->set_comment(util::utf16ToUtf8(item.getComment()));
+            pbItem->set_comment(item.getComment());
         }
     }
 
@@ -220,28 +220,28 @@
         if (package->id) {
             pbPackage->set_package_id(package->id.value());
         }
-        pbPackage->set_package_name(util::utf16ToUtf8(package->name));
+        pbPackage->set_package_name(package->name);
 
         for (auto& type : package->types) {
             pb::Type* pbType = pbPackage->add_types();
             if (type->id) {
                 pbType->set_id(type->id.value());
             }
-            pbType->set_name(util::utf16ToUtf8(toString(type->type)));
+            pbType->set_name(toString(type->type).toString());
 
             for (auto& entry : type->entries) {
                 pb::Entry* pbEntry = pbType->add_entries();
                 if (entry->id) {
                     pbEntry->set_id(entry->id.value());
                 }
-                pbEntry->set_name(util::utf16ToUtf8(entry->name));
+                pbEntry->set_name(entry->name);
 
                 // Write the SymbolStatus struct.
                 pb::SymbolStatus* pbStatus = pbEntry->mutable_symbol_status();
                 pbStatus->set_visibility(serializeVisibilityToPb(entry->symbolStatus.state));
                 serializeSourceToPb(entry->symbolStatus.source, &sourcePool,
                                     pbStatus->mutable_source());
-                pbStatus->set_comment(util::utf16ToUtf8(entry->symbolStatus.comment));
+                pbStatus->set_comment(entry->symbolStatus.comment);
 
                 for (auto& configValue : entry->values) {
                     pb::ConfigValue* pbConfigValue = pbEntry->add_config_values();
@@ -254,7 +254,7 @@
                     serializeSourceToPb(configValue->value->getSource(), &sourcePool,
                                         pbValue->mutable_source());
                     if (!configValue->value->getComment().empty()) {
-                        pbValue->set_comment(util::utf16ToUtf8(configValue->value->getComment()));
+                        pbValue->set_comment(configValue->value->getComment());
                     }
 
                     if (configValue->value->isWeak()) {
@@ -275,13 +275,13 @@
 
 std::unique_ptr<pb::CompiledFile> serializeCompiledFileToPb(const ResourceFile& file) {
     std::unique_ptr<pb::CompiledFile> pbFile = util::make_unique<pb::CompiledFile>();
-    pbFile->set_resource_name(util::utf16ToUtf8(file.name.toString()));
+    pbFile->set_resource_name(file.name.toString());
     pbFile->set_source_path(file.source.path);
     serializeConfig(file.config, pbFile->mutable_config());
 
     for (const SourcedResourceName& exported : file.exportedSymbols) {
         pb::CompiledFile_Symbol* pbSymbol = pbFile->add_exported_symbols();
-        pbSymbol->set_resource_name(util::utf16ToUtf8(exported.name.toString()));
+        pbSymbol->set_resource_name(exported.name.toString());
         pbSymbol->set_line_no(exported.line);
     }
     return pbFile;
diff --git a/tools/aapt2/proto/TableProtoSerializer_test.cpp b/tools/aapt2/proto/TableProtoSerializer_test.cpp
index dd995d8..78b32f7 100644
--- a/tools/aapt2/proto/TableProtoSerializer_test.cpp
+++ b/tools/aapt2/proto/TableProtoSerializer_test.cpp
@@ -16,49 +16,45 @@
 
 #include "ResourceTable.h"
 #include "proto/ProtoSerialize.h"
-#include "test/Builders.h"
-#include "test/Common.h"
-#include "test/Context.h"
-
-#include <gtest/gtest.h>
+#include "test/Test.h"
 
 namespace aapt {
 
 TEST(TableProtoSerializer, SerializeSinglePackage) {
     std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId(u"com.app.a", 0x7f)
-            .addFileReference(u"@com.app.a:layout/main", ResourceId(0x7f020000),
-                              u"res/layout/main.xml")
-            .addReference(u"@com.app.a:layout/other", ResourceId(0x7f020001),
-                          u"@com.app.a:layout/main")
-            .addString(u"@com.app.a:string/text", {}, u"hi")
-            .addValue(u"@com.app.a:id/foo", {}, util::make_unique<Id>())
+            .setPackageId("com.app.a", 0x7f)
+            .addFileReference("@com.app.a:layout/main", ResourceId(0x7f020000),
+                              "res/layout/main.xml")
+            .addReference("@com.app.a:layout/other", ResourceId(0x7f020001),
+                          "@com.app.a:layout/main")
+            .addString("@com.app.a:string/text", {}, "hi")
+            .addValue("@com.app.a:id/foo", {}, util::make_unique<Id>())
             .build();
 
     Symbol publicSymbol;
     publicSymbol.state = SymbolState::kPublic;
-    ASSERT_TRUE(table->setSymbolState(test::parseNameOrDie(u"@com.app.a:layout/main"),
+    ASSERT_TRUE(table->setSymbolState(test::parseNameOrDie("@com.app.a:layout/main"),
                                       ResourceId(0x7f020000),
                                       publicSymbol, context->getDiagnostics()));
 
-    Id* id = test::getValue<Id>(table.get(), u"@com.app.a:id/foo");
+    Id* id = test::getValue<Id>(table.get(), "@com.app.a:id/foo");
     ASSERT_NE(nullptr, id);
 
     // Make a plural.
     std::unique_ptr<Plural> plural = util::make_unique<Plural>();
-    plural->values[Plural::One] = util::make_unique<String>(table->stringPool.makeRef(u"one"));
-    ASSERT_TRUE(table->addResource(test::parseNameOrDie(u"@com.app.a:plurals/hey"),
-                                   ConfigDescription{}, std::string(), std::move(plural),
+    plural->values[Plural::One] = util::make_unique<String>(table->stringPool.makeRef("one"));
+    ASSERT_TRUE(table->addResource(test::parseNameOrDie("@com.app.a:plurals/hey"),
+                                   ConfigDescription{}, {}, std::move(plural),
                                    context->getDiagnostics()));
 
     // Make a resource with different products.
-    ASSERT_TRUE(table->addResource(test::parseNameOrDie(u"@com.app.a:integer/one"),
-                                   test::parseConfigOrDie("land"), std::string(),
+    ASSERT_TRUE(table->addResource(test::parseNameOrDie("@com.app.a:integer/one"),
+                                   test::parseConfigOrDie("land"), {},
                                    test::buildPrimitive(android::Res_value::TYPE_INT_DEC, 123u),
                                    context->getDiagnostics()));
-    ASSERT_TRUE(table->addResource(test::parseNameOrDie(u"@com.app.a:integer/one"),
-                                       test::parseConfigOrDie("land"), std::string("tablet"),
+    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()));
 
@@ -66,10 +62,10 @@
     // The reference should point to a resource outside of this table to test that both
     // name and id get serialized.
     Reference expectedRef;
-    expectedRef.name = test::parseNameOrDie(u"@android:layout/main");
+    expectedRef.name = test::parseNameOrDie("@android:layout/main");
     expectedRef.id = ResourceId(0x01020000);
-    ASSERT_TRUE(table->addResource(test::parseNameOrDie(u"@com.app.a:layout/abc"),
-                                   ConfigDescription::defaultConfig(), std::string(),
+    ASSERT_TRUE(table->addResource(test::parseNameOrDie("@com.app.a:layout/abc"),
+                                   ConfigDescription::defaultConfig(), {},
                                    util::make_unique<Reference>(expectedRef),
                                    context->getDiagnostics()));
 
@@ -81,28 +77,28 @@
                                                                      context->getDiagnostics());
     ASSERT_NE(nullptr, newTable);
 
-    Id* newId = test::getValue<Id>(newTable.get(), u"@com.app.a:id/foo");
+    Id* newId = test::getValue<Id>(newTable.get(), "@com.app.a:id/foo");
     ASSERT_NE(nullptr, newId);
     EXPECT_EQ(id->isWeak(), newId->isWeak());
 
     Maybe<ResourceTable::SearchResult> result = newTable->findResource(
-            test::parseNameOrDie(u"@com.app.a:layout/main"));
+            test::parseNameOrDie("@com.app.a:layout/main"));
     AAPT_ASSERT_TRUE(result);
     EXPECT_EQ(SymbolState::kPublic, result.value().type->symbolStatus.state);
     EXPECT_EQ(SymbolState::kPublic, result.value().entry->symbolStatus.state);
 
     // Find the product-dependent values
     BinaryPrimitive* prim = test::getValueForConfigAndProduct<BinaryPrimitive>(
-            newTable.get(), u"@com.app.a:integer/one", test::parseConfigOrDie("land"), "");
+            newTable.get(), "@com.app.a:integer/one", test::parseConfigOrDie("land"), "");
     ASSERT_NE(nullptr, prim);
     EXPECT_EQ(123u, prim->value.data);
 
     prim = test::getValueForConfigAndProduct<BinaryPrimitive>(
-            newTable.get(), u"@com.app.a:integer/one", test::parseConfigOrDie("land"), "tablet");
+            newTable.get(), "@com.app.a:integer/one", test::parseConfigOrDie("land"), "tablet");
     ASSERT_NE(nullptr, prim);
     EXPECT_EQ(321u, prim->value.data);
 
-    Reference* actualRef = test::getValue<Reference>(newTable.get(), u"@com.app.a:layout/abc");
+    Reference* actualRef = test::getValue<Reference>(newTable.get(), "@com.app.a:layout/abc");
     ASSERT_NE(nullptr, actualRef);
     AAPT_ASSERT_TRUE(actualRef->name);
     AAPT_ASSERT_TRUE(actualRef->id);
@@ -115,9 +111,9 @@
 
     ResourceFile f;
     f.config = test::parseConfigOrDie("hdpi-v9");
-    f.name = test::parseNameOrDie(u"@com.app.a:layout/main");
+    f.name = test::parseNameOrDie("@com.app.a:layout/main");
     f.source.path = "res/layout-hdpi-v9/main.xml";
-    f.exportedSymbols.push_back(SourcedResourceName{ test::parseNameOrDie(u"@+id/unchecked"), 23u });
+    f.exportedSymbols.push_back(SourcedResourceName{ test::parseNameOrDie("@+id/unchecked"), 23u });
 
     const std::string expectedData = "1234";
 
@@ -136,7 +132,7 @@
     const pb::CompiledFile* newPbFile = inFileStream.CompiledFile();
     ASSERT_NE(nullptr, newPbFile);
 
-    std::unique_ptr<ResourceFile> file = deserializeCompiledFileFromPb(*newPbFile, Source{ "test" },
+    std::unique_ptr<ResourceFile> file = deserializeCompiledFileFromPb(*newPbFile, Source("test"),
                                                                        context->getDiagnostics());
     ASSERT_NE(nullptr, file);
 
@@ -145,7 +141,7 @@
     EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(inFileStream.data()) & 0x03);
 
     ASSERT_EQ(1u, file->exportedSymbols.size());
-    EXPECT_EQ(test::parseNameOrDie(u"@+id/unchecked"), file->exportedSymbols[0].name);
+    EXPECT_EQ(test::parseNameOrDie("@+id/unchecked"), file->exportedSymbols[0].name);
 }
 
 TEST(TableProtoSerializer, DeserializeCorruptHeaderSafely) {
diff --git a/tools/aapt2/split/TableSplitter_test.cpp b/tools/aapt2/split/TableSplitter_test.cpp
index 2d013e4..a6dfd62 100644
--- a/tools/aapt2/split/TableSplitter_test.cpp
+++ b/tools/aapt2/split/TableSplitter_test.cpp
@@ -21,15 +21,15 @@
 
 TEST(TableSplitterTest, NoSplitPreferredDensity) {
     std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addFileReference(u"@android:drawable/icon", u"res/drawable-mdpi/icon.png",
+            .addFileReference("@android:drawable/icon", "res/drawable-mdpi/icon.png",
                               test::parseConfigOrDie("mdpi"))
-            .addFileReference(u"@android:drawable/icon", u"res/drawable-hdpi/icon.png",
+            .addFileReference("@android:drawable/icon", "res/drawable-hdpi/icon.png",
                               test::parseConfigOrDie("hdpi"))
-            .addFileReference(u"@android:drawable/icon", u"res/drawable-xhdpi/icon.png",
+            .addFileReference("@android:drawable/icon", "res/drawable-xhdpi/icon.png",
                               test::parseConfigOrDie("xhdpi"))
-            .addFileReference(u"@android:drawable/icon", u"res/drawable-xxhdpi/icon.png",
+            .addFileReference("@android:drawable/icon", "res/drawable-xxhdpi/icon.png",
                               test::parseConfigOrDie("xxhdpi"))
-            .addSimple(u"@android:string/one")
+            .addSimple("@android:string/one")
             .build();
 
     TableSplitterOptions options;
@@ -38,24 +38,24 @@
     splitter.splitTable(table.get());
 
     EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(table.get(),
-                                                              u"@android:drawable/icon",
+                                                              "@android:drawable/icon",
                                                               test::parseConfigOrDie("mdpi")));
     EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(table.get(),
-                                                              u"@android:drawable/icon",
+                                                              "@android:drawable/icon",
                                                               test::parseConfigOrDie("hdpi")));
     EXPECT_NE(nullptr, test::getValueForConfig<FileReference>(table.get(),
-                                                              u"@android:drawable/icon",
+                                                              "@android:drawable/icon",
                                                               test::parseConfigOrDie("xhdpi")));
     EXPECT_EQ(nullptr, test::getValueForConfig<FileReference>(table.get(),
-                                                              u"@android:drawable/icon",
+                                                              "@android:drawable/icon",
                                                               test::parseConfigOrDie("xxhdpi")));
-    EXPECT_NE(nullptr, test::getValue<Id>(table.get(), u"@android:string/one"));
+    EXPECT_NE(nullptr, test::getValue<Id>(table.get(), "@android:string/one"));
 }
 
 TEST(TableSplitterTest, SplitTableByConfigAndDensity) {
     ResourceTable table;
 
-    const ResourceName foo = test::parseNameOrDie(u"@android:string/foo");
+    const ResourceName foo = test::parseNameOrDie("@android:string/foo");
     ASSERT_TRUE(table.addResource(foo, test::parseConfigOrDie("land-hdpi"), {},
                                   util::make_unique<Id>(),
                                   test::getDiagnostics()));
@@ -79,25 +79,25 @@
     ResourceTable* splitTwo = splitter.getSplits()[1].get();
 
     // Since a split was defined, all densities should be gone from base.
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, u"@android:string/foo",
+    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, "@android:string/foo",
                                                    test::parseConfigOrDie("land-hdpi")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, u"@android:string/foo",
+    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, "@android:string/foo",
                                                    test::parseConfigOrDie("land-xhdpi")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, u"@android:string/foo",
+    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(&table, "@android:string/foo",
                                                    test::parseConfigOrDie("land-xxhdpi")));
 
-    EXPECT_NE(nullptr, test::getValueForConfig<Id>(splitOne, u"@android:string/foo",
+    EXPECT_NE(nullptr, test::getValueForConfig<Id>(splitOne, "@android:string/foo",
                                                    test::parseConfigOrDie("land-hdpi")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitOne, u"@android:string/foo",
+    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitOne, "@android:string/foo",
                                                    test::parseConfigOrDie("land-xhdpi")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitOne, u"@android:string/foo",
+    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitOne, "@android:string/foo",
                                                    test::parseConfigOrDie("land-xxhdpi")));
 
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitTwo, u"@android:string/foo",
+    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitTwo, "@android:string/foo",
                                                    test::parseConfigOrDie("land-hdpi")));
-    EXPECT_NE(nullptr, test::getValueForConfig<Id>(splitTwo, u"@android:string/foo",
+    EXPECT_NE(nullptr, test::getValueForConfig<Id>(splitTwo, "@android:string/foo",
                                                    test::parseConfigOrDie("land-xhdpi")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitTwo, u"@android:string/foo",
+    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(splitTwo, "@android:string/foo",
                                                    test::parseConfigOrDie("land-xxhdpi")));
 }
 
diff --git a/tools/aapt2/test/Builders.h b/tools/aapt2/test/Builders.h
index fb1d8f8..c0c0160 100644
--- a/tools/aapt2/test/Builders.h
+++ b/tools/aapt2/test/Builders.h
@@ -40,81 +40,81 @@
         return &mTable->stringPool;
     }
 
-    ResourceTableBuilder& setPackageId(const StringPiece16& packageName, uint8_t id) {
+    ResourceTableBuilder& setPackageId(const StringPiece& packageName, uint8_t id) {
         ResourceTablePackage* package = mTable->createPackage(packageName, id);
         assert(package);
         return *this;
     }
 
-    ResourceTableBuilder& addSimple(const StringPiece16& name, const ResourceId id = {}) {
+    ResourceTableBuilder& addSimple(const StringPiece& name, const ResourceId id = {}) {
         return addValue(name, id, util::make_unique<Id>());
     }
 
-    ResourceTableBuilder& addSimple(const StringPiece16& name, const ConfigDescription& config,
+    ResourceTableBuilder& addSimple(const StringPiece& name, const ConfigDescription& config,
                                     const ResourceId id = {}) {
         return addValue(name, config, id, util::make_unique<Id>());
     }
 
-    ResourceTableBuilder& addReference(const StringPiece16& name, const StringPiece16& ref) {
+    ResourceTableBuilder& addReference(const StringPiece& name, const StringPiece& ref) {
         return addReference(name, {}, ref);
     }
 
-    ResourceTableBuilder& addReference(const StringPiece16& name, const ResourceId id,
-                                       const StringPiece16& ref) {
+    ResourceTableBuilder& addReference(const StringPiece& name, const ResourceId id,
+                                       const StringPiece& ref) {
         return addValue(name, id, util::make_unique<Reference>(parseNameOrDie(ref)));
     }
 
-    ResourceTableBuilder& addString(const StringPiece16& name, const StringPiece16& str) {
+    ResourceTableBuilder& addString(const StringPiece& name, const StringPiece& str) {
         return addString(name, {}, str);
     }
 
-    ResourceTableBuilder& addString(const StringPiece16& name, const ResourceId id,
-                                    const StringPiece16& str) {
+    ResourceTableBuilder& addString(const StringPiece& name, const ResourceId id,
+                                    const StringPiece& str) {
         return addValue(name, id, util::make_unique<String>(mTable->stringPool.makeRef(str)));
     }
 
-    ResourceTableBuilder& addString(const StringPiece16& name, const ResourceId id,
-                                    const ConfigDescription& config, const StringPiece16& str) {
+    ResourceTableBuilder& addString(const StringPiece& name, const ResourceId id,
+                                    const ConfigDescription& config, const StringPiece& str) {
         return addValue(name, config, id,
                         util::make_unique<String>(mTable->stringPool.makeRef(str)));
     }
 
-    ResourceTableBuilder& addFileReference(const StringPiece16& name, const StringPiece16& path) {
+    ResourceTableBuilder& addFileReference(const StringPiece& name, const StringPiece& path) {
         return addFileReference(name, {}, path);
     }
 
-    ResourceTableBuilder& addFileReference(const StringPiece16& name, const ResourceId id,
-                                           const StringPiece16& path) {
+    ResourceTableBuilder& addFileReference(const StringPiece& name, const ResourceId id,
+                                           const StringPiece& path) {
         return addValue(name, id,
                         util::make_unique<FileReference>(mTable->stringPool.makeRef(path)));
     }
 
-    ResourceTableBuilder& addFileReference(const StringPiece16& name, const StringPiece16& path,
+    ResourceTableBuilder& addFileReference(const StringPiece& name, const StringPiece& path,
                                            const ConfigDescription& config) {
         return addValue(name, config, {},
                         util::make_unique<FileReference>(mTable->stringPool.makeRef(path)));
     }
 
-    ResourceTableBuilder& addValue(const StringPiece16& name,
+    ResourceTableBuilder& addValue(const StringPiece& name,
                                    std::unique_ptr<Value> value) {
         return addValue(name, {}, std::move(value));
     }
 
-    ResourceTableBuilder& addValue(const StringPiece16& name, const ResourceId id,
+    ResourceTableBuilder& addValue(const StringPiece& name, const ResourceId id,
                                    std::unique_ptr<Value> value) {
         return addValue(name, {}, id, std::move(value));
     }
 
-    ResourceTableBuilder& addValue(const StringPiece16& name, const ConfigDescription& config,
+    ResourceTableBuilder& addValue(const StringPiece& name, const ConfigDescription& config,
                                    const ResourceId id, std::unique_ptr<Value> value) {
         ResourceName resName = parseNameOrDie(name);
-        bool result = mTable->addResourceAllowMangled(resName, id, config, std::string(),
+        bool result = mTable->addResourceAllowMangled(resName, id, config, {},
                                                       std::move(value), &mDiagnostics);
         assert(result);
         return *this;
     }
 
-    ResourceTableBuilder& setSymbolState(const StringPiece16& name, ResourceId id,
+    ResourceTableBuilder& setSymbolState(const StringPiece& name, ResourceId id,
                                          SymbolState state) {
         ResourceName resName = parseNameOrDie(name);
         Symbol symbol;
@@ -129,7 +129,7 @@
     }
 };
 
-inline std::unique_ptr<Reference> buildReference(const StringPiece16& ref,
+inline std::unique_ptr<Reference> buildReference(const StringPiece& ref,
                                                  Maybe<ResourceId> id = {}) {
     std::unique_ptr<Reference> reference = util::make_unique<Reference>(parseNameOrDie(ref));
     reference->id = id;
@@ -160,7 +160,7 @@
         return *this;
     }
 
-    ValueBuilder& setComment(const StringPiece16& str) {
+    ValueBuilder& setComment(const StringPiece& str) {
         mValue->setComment(str);
         return *this;
     }
@@ -184,9 +184,9 @@
         return *this;
     }
 
-    AttributeBuilder& addItem(const StringPiece16& name, uint32_t value) {
+    AttributeBuilder& addItem(const StringPiece& name, uint32_t value) {
         mAttr->symbols.push_back(Attribute::Symbol{
-                Reference(ResourceName{ {}, ResourceType::kId, name.toString()}),
+                Reference(ResourceName({}, ResourceType::kId, name)),
                 value});
         return *this;
     }
@@ -201,17 +201,17 @@
     std::unique_ptr<Style> mStyle = util::make_unique<Style>();
 
 public:
-    StyleBuilder& setParent(const StringPiece16& str) {
+    StyleBuilder& setParent(const StringPiece& str) {
         mStyle->parent = Reference(parseNameOrDie(str));
         return *this;
     }
 
-    StyleBuilder& addItem(const StringPiece16& str, std::unique_ptr<Item> value) {
+    StyleBuilder& addItem(const StringPiece& str, std::unique_ptr<Item> value) {
         mStyle->entries.push_back(Style::Entry{ Reference(parseNameOrDie(str)), std::move(value) });
         return *this;
     }
 
-    StyleBuilder& addItem(const StringPiece16& str, ResourceId id, std::unique_ptr<Item> value) {
+    StyleBuilder& addItem(const StringPiece& str, ResourceId id, std::unique_ptr<Item> value) {
         addItem(str, std::move(value));
         mStyle->entries.back().key.id = id;
         return *this;
@@ -227,7 +227,7 @@
     std::unique_ptr<Styleable> mStyleable = util::make_unique<Styleable>();
 
 public:
-    StyleableBuilder& addItem(const StringPiece16& str, Maybe<ResourceId> id = {}) {
+    StyleableBuilder& addItem(const StringPiece& str, Maybe<ResourceId> id = {}) {
         mStyleable->entries.push_back(Reference(parseNameOrDie(str)));
         mStyleable->entries.back().id = id;
         return *this;
diff --git a/tools/aapt2/test/Common.h b/tools/aapt2/test/Common.h
index faccd477..b2eaba6 100644
--- a/tools/aapt2/test/Common.h
+++ b/tools/aapt2/test/Common.h
@@ -62,7 +62,7 @@
     return &diag;
 }
 
-inline ResourceName parseNameOrDie(const StringPiece16& str) {
+inline ResourceName parseNameOrDie(const StringPiece& str) {
     ResourceNameRef ref;
     bool result = ResourceUtils::tryParseReference(str, &ref);
     assert(result && "invalid resource name");
@@ -77,7 +77,7 @@
 }
 
 template <typename T> T* getValueForConfigAndProduct(ResourceTable* table,
-                                                     const StringPiece16& resName,
+                                                     const StringPiece& resName,
                                                      const ConfigDescription& config,
                                                      const StringPiece& product) {
     Maybe<ResourceTable::SearchResult> result = table->findResource(parseNameOrDie(resName));
@@ -90,12 +90,12 @@
     return nullptr;
 }
 
-template <typename T> T* getValueForConfig(ResourceTable* table, const StringPiece16& resName,
+template <typename T> T* getValueForConfig(ResourceTable* table, const StringPiece& resName,
                                            const ConfigDescription& config) {
     return getValueForConfigAndProduct<T>(table, resName, config, {});
 }
 
-template <typename T> T* getValue(ResourceTable* table, const StringPiece16& resName) {
+template <typename T> T* getValue(ResourceTable* table, const StringPiece& resName) {
     return getValueForConfig<T>(table, resName, {});
 }
 
diff --git a/tools/aapt2/test/Context.h b/tools/aapt2/test/Context.h
index 36f568b..b053e07 100644
--- a/tools/aapt2/test/Context.h
+++ b/tools/aapt2/test/Context.h
@@ -19,7 +19,6 @@
 
 #include "NameMangler.h"
 #include "util/Util.h"
-
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
 #include "test/Common.h"
@@ -40,7 +39,7 @@
         return &mDiagnostics;
     }
 
-    const std::u16string& getCompilationPackage() override {
+    const std::string& getCompilationPackage() override {
         assert(mCompilationPackage && "package name not set");
         return mCompilationPackage.value();
     }
@@ -65,7 +64,7 @@
 private:
     friend class ContextBuilder;
 
-    Maybe<std::u16string> mCompilationPackage;
+    Maybe<std::string> mCompilationPackage;
     Maybe<uint8_t> mPackageId;
     StdErrDiagnostics mDiagnostics;
     SymbolTable mSymbols;
@@ -78,7 +77,7 @@
     std::unique_ptr<Context> mContext = std::unique_ptr<Context>(new Context());
 
 public:
-    ContextBuilder& setCompilationPackage(const StringPiece16& package) {
+    ContextBuilder& setCompilationPackage(const StringPiece& package) {
         mContext->mCompilationPackage = package.toString();
         return *this;
     }
@@ -110,7 +109,7 @@
 
 class StaticSymbolSourceBuilder {
 public:
-    StaticSymbolSourceBuilder& addPublicSymbol(const StringPiece16& name, ResourceId id,
+    StaticSymbolSourceBuilder& addPublicSymbol(const StringPiece& name, ResourceId id,
                                                std::unique_ptr<Attribute> attr = {}) {
         std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
                 id, std::move(attr), true);
@@ -120,7 +119,7 @@
         return *this;
     }
 
-    StaticSymbolSourceBuilder& addSymbol(const StringPiece16& name, ResourceId id,
+    StaticSymbolSourceBuilder& addSymbol(const StringPiece& name, ResourceId id,
                                          std::unique_ptr<Attribute> attr = {}) {
         std::unique_ptr<SymbolTable::Symbol> symbol = util::make_unique<SymbolTable::Symbol>(
                 id, std::move(attr), false);
diff --git a/tools/aapt2/unflatten/BinaryResourceParser.cpp b/tools/aapt2/unflatten/BinaryResourceParser.cpp
index d2eccbc..4fd77c8 100644
--- a/tools/aapt2/unflatten/BinaryResourceParser.cpp
+++ b/tools/aapt2/unflatten/BinaryResourceParser.cpp
@@ -178,7 +178,8 @@
         packageName[i] = util::deviceToHost16(packageHeader->name[i]);
     }
 
-    ResourceTablePackage* package = mTable->createPackage(packageName, (uint8_t) packageId);
+    ResourceTablePackage* package = mTable->createPackage(util::utf16ToUtf8(packageName),
+                                                          static_cast<uint8_t>(packageId));
     if (!package) {
         mContext->getDiagnostics()->error(DiagMessage(mSource)
                                           << "incompatible package '" << packageName
@@ -308,12 +309,12 @@
     ConfigDescription config;
     config.copyFromDtoH(type->config);
 
-    StringPiece16 typeStr16 = util::getString(mTypePool, type->id - 1);
+    const std::string typeStr = util::getString(mTypePool, type->id - 1);
 
-    const ResourceType* parsedType = parseResourceType(typeStr16);
+    const ResourceType* parsedType = parseResourceType(typeStr);
     if (!parsedType) {
         mContext->getDiagnostics()->error(DiagMessage(mSource)
-                                          << "invalid type name '" << typeStr16
+                                          << "invalid type name '" << typeStr
                                           << "' for type with ID " << (int) type->id);
         return false;
     }
@@ -327,7 +328,7 @@
 
         const ResourceName name(package->name, *parsedType,
                                 util::getString(mKeyPool,
-                                                util::deviceToHost32(entry->key.index)).toString());
+                                                util::deviceToHost32(entry->key.index)));
 
         const ResourceId resId(package->id.value(), type->id, static_cast<uint16_t>(it.index()));
 
@@ -387,16 +388,16 @@
     const uint32_t data = util::deviceToHost32(value->data);
 
     if (value->dataType == Res_value::TYPE_STRING) {
-        StringPiece16 str = util::getString(mValuePool, data);
+        const std::string str = util::getString(mValuePool, data);
 
         const ResStringPool_span* spans = mValuePool.styleAt(data);
 
         // Check if the string has a valid style associated with it.
         if (spans != nullptr && spans->name.index != ResStringPool_span::END) {
-            StyleString styleStr = { str.toString() };
+            StyleString styleStr = { str };
             while (spans->name.index != ResStringPool_span::END) {
                 styleStr.spans.push_back(Span{
-                        util::getString(mValuePool, spans->name.index).toString(),
+                        util::getString(mValuePool, spans->name.index),
                         spans->firstChar,
                         spans->lastChar
                 });
@@ -406,7 +407,7 @@
                     styleStr, StringPool::Context{1, config}));
         } else {
             if (name.type != ResourceType::kString &&
-                    util::stringStartsWith<char16_t>(str, u"res/")) {
+                    util::stringStartsWith(str, "res/")) {
                 // This must be a FileReference.
                 return util::make_unique<FileReference>(mTable->stringPool.makeRef(
                             str, StringPool::Context{ 0, config }));
diff --git a/tools/aapt2/util/Files.cpp b/tools/aapt2/util/Files.cpp
index f5e49f1..c9b3811 100644
--- a/tools/aapt2/util/Files.cpp
+++ b/tools/aapt2/util/Files.cpp
@@ -157,7 +157,7 @@
 
 std::string packageToPath(const StringPiece& package) {
     std::string outPath;
-    for (StringPiece part : util::tokenize<char>(package, '.')) {
+    for (StringPiece part : util::tokenize(package, '.')) {
         appendPath(&outPath, part);
     }
     return outPath;
@@ -199,7 +199,7 @@
         return false;
     }
 
-    for (StringPiece line : util::tokenize<char>(contents, ' ')) {
+    for (StringPiece line : util::tokenize(contents, ' ')) {
         line = util::trimWhitespace(line);
         if (!line.empty()) {
             outArgList->push_back(line.toString());
diff --git a/tools/aapt2/util/StringPiece_test.cpp b/tools/aapt2/util/StringPiece_test.cpp
index 853a9a4..a87065a 100644
--- a/tools/aapt2/util/StringPiece_test.cpp
+++ b/tools/aapt2/util/StringPiece_test.cpp
@@ -34,16 +34,16 @@
 }
 
 TEST(StringPieceTest, PiecesHaveCorrectSortOrder) {
-    std::u16string testing(u"testing");
-    std::u16string banana(u"banana");
-    std::u16string car(u"car");
+    std::string testing("testing");
+    std::string banana("banana");
+    std::string car("car");
 
-    EXPECT_TRUE(StringPiece16(testing) > banana);
-    EXPECT_TRUE(StringPiece16(testing) > car);
-    EXPECT_TRUE(StringPiece16(banana) < testing);
-    EXPECT_TRUE(StringPiece16(banana) < car);
-    EXPECT_TRUE(StringPiece16(car) < testing);
-    EXPECT_TRUE(StringPiece16(car) > banana);
+    EXPECT_TRUE(StringPiece(testing) > banana);
+    EXPECT_TRUE(StringPiece(testing) > car);
+    EXPECT_TRUE(StringPiece(banana) < testing);
+    EXPECT_TRUE(StringPiece(banana) < car);
+    EXPECT_TRUE(StringPiece(car) < testing);
+    EXPECT_TRUE(StringPiece(car) > banana);
 }
 
 TEST(StringPieceTest, PiecesHaveCorrectSortOrderUtf8) {
diff --git a/tools/aapt2/util/Util.cpp b/tools/aapt2/util/Util.cpp
index c41eb05..3c0e9bde 100644
--- a/tools/aapt2/util/Util.cpp
+++ b/tools/aapt2/util/Util.cpp
@@ -54,23 +54,18 @@
     return splitAndTransform(str, sep, ::tolower);
 }
 
-StringPiece16 trimWhitespace(const StringPiece16& str) {
-    if (str.size() == 0 || str.data() == nullptr) {
-        return str;
+bool stringStartsWith(const StringPiece& str, const StringPiece& prefix) {
+    if (str.size() < prefix.size()) {
+        return false;
     }
+    return str.substr(0, prefix.size()) == prefix;
+}
 
-    const char16_t* start = str.data();
-    const char16_t* end = str.data() + str.length();
-
-    while (start != end && util::isspace16(*start)) {
-        start++;
+bool stringEndsWith(const StringPiece& str, const StringPiece& suffix) {
+    if (str.size() < suffix.size()) {
+        return false;
     }
-
-    while (end != start && util::isspace16(*(end - 1))) {
-        end--;
-    }
-
-    return StringPiece16(start, end - start);
+    return str.substr(str.size() - suffix.size(), suffix.size()) == suffix;
 }
 
 StringPiece trimWhitespace(const StringPiece& str) {
@@ -92,11 +87,11 @@
     return StringPiece(start, end - start);
 }
 
-StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
-        const StringPiece16& allowedChars) {
+StringPiece::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece& str,
+                                                           const StringPiece& allowedChars) {
     const auto endIter = str.end();
     for (auto iter = str.begin(); iter != endIter; ++iter) {
-        char16_t c = *iter;
+        char c = *iter;
         if ((c >= u'a' && c <= u'z') ||
                 (c >= u'A' && c <= u'Z') ||
                 (c >= u'0' && c <= u'9')) {
@@ -104,7 +99,7 @@
         }
 
         bool match = false;
-        for (char16_t i : allowedChars) {
+        for (char i : allowedChars) {
             if (c == i) {
                 match = true;
                 break;
@@ -118,51 +113,51 @@
     return endIter;
 }
 
-bool isJavaClassName(const StringPiece16& str) {
+bool isJavaClassName(const StringPiece& str) {
     size_t pieces = 0;
-    for (const StringPiece16& piece : tokenize(str, u'.')) {
+    for (const StringPiece& piece : tokenize(str, '.')) {
         pieces++;
         if (piece.empty()) {
             return false;
         }
 
         // Can't have starting or trailing $ character.
-        if (piece.data()[0] == u'$' || piece.data()[piece.size() - 1] == u'$') {
+        if (piece.data()[0] == '$' || piece.data()[piece.size() - 1] == '$') {
             return false;
         }
 
-        if (findNonAlphaNumericAndNotInSet(piece, u"$_") != piece.end()) {
+        if (findNonAlphaNumericAndNotInSet(piece, "$_") != piece.end()) {
             return false;
         }
     }
     return pieces >= 2;
 }
 
-bool isJavaPackageName(const StringPiece16& str) {
+bool isJavaPackageName(const StringPiece& str) {
     if (str.empty()) {
         return false;
     }
 
     size_t pieces = 0;
-    for (const StringPiece16& piece : tokenize(str, u'.')) {
+    for (const StringPiece& piece : tokenize(str, '.')) {
         pieces++;
         if (piece.empty()) {
             return false;
         }
 
-        if (piece.data()[0] == u'_' || piece.data()[piece.size() - 1] == u'_') {
+        if (piece.data()[0] == '_' || piece.data()[piece.size() - 1] == '_') {
             return false;
         }
 
-        if (findNonAlphaNumericAndNotInSet(piece, u"_") != piece.end()) {
+        if (findNonAlphaNumericAndNotInSet(piece, "_") != piece.end()) {
             return false;
         }
     }
     return pieces >= 1;
 }
 
-Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package,
-                                                 const StringPiece16& className) {
+Maybe<std::string> getFullyQualifiedClassName(const StringPiece& package,
+                                              const StringPiece& className) {
     if (className.empty()) {
         return {};
     }
@@ -175,9 +170,9 @@
         return {};
     }
 
-    std::u16string result(package.data(), package.size());
-    if (className.data()[0] != u'.') {
-        result += u'.';
+    std::string result(package.data(), package.size());
+    if (className.data()[0] != '.') {
+        result += '.';
     }
 
     result.append(className.data(), className.size());
@@ -187,23 +182,23 @@
     return result;
 }
 
-static size_t consumeDigits(const char16_t* start, const char16_t* end) {
-    const char16_t* c = start;
-    for (; c != end && *c >= u'0' && *c <= u'9'; c++) {}
+static size_t consumeDigits(const char* start, const char* end) {
+    const char* c = start;
+    for (; c != end && *c >= '0' && *c <= '9'; c++) {}
     return static_cast<size_t>(c - start);
 }
 
-bool verifyJavaStringFormat(const StringPiece16& str) {
-    const char16_t* c = str.begin();
-    const char16_t* const end = str.end();
+bool verifyJavaStringFormat(const StringPiece& str) {
+    const char* c = str.begin();
+    const char* const end = str.end();
 
     size_t argCount = 0;
     bool nonpositional = false;
     while (c != end) {
-        if (*c == u'%' && c + 1 < end) {
+        if (*c == '%' && c + 1 < end) {
             c++;
 
-            if (*c == u'%') {
+            if (*c == '%') {
                 c++;
                 continue;
             }
@@ -213,11 +208,11 @@
             size_t numDigits = consumeDigits(c, end);
             if (numDigits > 0) {
                 c += numDigits;
-                if (c != end && *c != u'$') {
+                if (c != end && *c != '$') {
                     // The digits were a size, but not a positional argument.
                     nonpositional = true;
                 }
-            } else if (*c == u'<') {
+            } else if (*c == '<') {
                 // Reusing last argument, bad idea since positions can be moved around
                 // during translation.
                 nonpositional = true;
@@ -225,7 +220,7 @@
                 c++;
 
                 // Optionally we can have a $ after
-                if (c != end && *c == u'$') {
+                if (c != end && *c == '$') {
                     c++;
                 }
             } else {
@@ -233,13 +228,13 @@
             }
 
             // Ignore size, width, flags, etc.
-            while (c != end && (*c == u'-' ||
-                    *c == u'#' ||
-                    *c == u'+' ||
-                    *c == u' ' ||
-                    *c == u',' ||
-                    *c == u'(' ||
-                    (*c >= u'0' && *c <= '9'))) {
+            while (c != end && (*c == '-' ||
+                    *c == '#' ||
+                    *c == '+' ||
+                    *c == ' ' ||
+                    *c == ',' ||
+                    *c == '(' ||
+                    (*c >= '0' && *c <= '9'))) {
                 c++;
             }
 
@@ -286,11 +281,11 @@
     return true;
 }
 
-static Maybe<char16_t> parseUnicodeCodepoint(const char16_t** start, const char16_t* end) {
-    char16_t code = 0;
+static Maybe<std::string> parseUnicodeCodepoint(const char** start, const char* end) {
+    char32_t code = 0;
     for (size_t i = 0; i < 4 && *start != end; i++, (*start)++) {
-        char16_t c = **start;
-        int a;
+        char c = **start;
+        char32_t a;
         if (c >= '0' && c <= '9') {
             a = c - '0';
         } else if (c >= 'a' && c <= 'f') {
@@ -298,51 +293,60 @@
         } else if (c >= 'A' && c <= 'F') {
             a = c - 'A' + 10;
         } else {
-            return make_nothing<char16_t>();
+            return {};
         }
         code = (code << 4) | a;
     }
-    return make_value(code);
+
+    ssize_t len = utf32_to_utf8_length(&code, 1);
+    if (len < 0) {
+        return {};
+    }
+
+    std::string resultUtf8;
+    resultUtf8.resize(len);
+    utf32_to_utf8(&code, 1, &*resultUtf8.begin(), len + 1);
+    return resultUtf8;
 }
 
-StringBuilder& StringBuilder::append(const StringPiece16& str) {
+StringBuilder& StringBuilder::append(const StringPiece& str) {
     if (!mError.empty()) {
         return *this;
     }
 
-    const char16_t* const end = str.end();
-    const char16_t* start = str.begin();
-    const char16_t* current = start;
+    const char* const end = str.end();
+    const char* start = str.begin();
+    const char* current = start;
     while (current != end) {
         if (mLastCharWasEscape) {
             switch (*current) {
-                case u't':
-                    mStr += u'\t';
+                case 't':
+                    mStr += '\t';
                     break;
-                case u'n':
-                    mStr += u'\n';
+                case 'n':
+                    mStr += '\n';
                     break;
-                case u'#':
-                    mStr += u'#';
+                case '#':
+                    mStr += '#';
                     break;
-                case u'@':
-                    mStr += u'@';
+                case '@':
+                    mStr += '@';
                     break;
-                case u'?':
-                    mStr += u'?';
+                case '?':
+                    mStr += '?';
                     break;
-                case u'"':
-                    mStr += u'"';
+                case '"':
+                    mStr += '"';
                     break;
-                case u'\'':
-                    mStr += u'\'';
+                case '\'':
+                    mStr += '\'';
                     break;
-                case u'\\':
-                    mStr += u'\\';
+                case '\\':
+                    mStr += '\\';
                     break;
-                case u'u': {
+                case 'u': {
                     current++;
-                    Maybe<char16_t> c = parseUnicodeCodepoint(&current, end);
+                    Maybe<std::string> c = parseUnicodeCodepoint(&current, end);
                     if (!c) {
                         mError = "invalid unicode escape sequence";
                         return *this;
@@ -358,7 +362,7 @@
             }
             mLastCharWasEscape = false;
             start = current + 1;
-        } else if (*current == u'"') {
+        } else if (*current == '"') {
             if (!mQuote && mTrailingSpace) {
                 // We found an opening quote, and we have
                 // trailing space, so we should append that
@@ -367,7 +371,7 @@
                     // We had trailing whitespace, so
                     // replace with a single space.
                     if (!mStr.empty()) {
-                        mStr += u' ';
+                        mStr += ' ';
                     }
                     mTrailingSpace = false;
                 }
@@ -375,17 +379,17 @@
             mQuote = !mQuote;
             mStr.append(start, current - start);
             start = current + 1;
-        } else if (*current == u'\'' && !mQuote) {
+        } else if (*current == '\'' && !mQuote) {
             // This should be escaped.
             mError = "unescaped apostrophe";
             return *this;
-        } else if (*current == u'\\') {
+        } else if (*current == '\\') {
             // This is an escape sequence, convert to the real value.
             if (!mQuote && mTrailingSpace) {
                 // We had trailing whitespace, so
                 // replace with a single space.
                 if (!mStr.empty()) {
-                    mStr += u' ';
+                    mStr += ' ';
                 }
                 mTrailingSpace = false;
             }
@@ -394,7 +398,7 @@
             mLastCharWasEscape = true;
         } else if (!mQuote) {
             // This is not quoted text, so look for whitespace.
-            if (isspace16(*current)) {
+            if (isspace(*current)) {
                 // We found whitespace, see if we have seen some
                 // before.
                 if (!mTrailingSpace) {
@@ -410,7 +414,7 @@
                 // We saw trailing space before, so replace all
                 // that trailing space with one space.
                 if (!mStr.empty()) {
-                    mStr += u' ';
+                    mStr += ' ';
                 }
                 mTrailingSpace = false;
             }
@@ -441,10 +445,8 @@
     }
 
     std::string utf8;
-    // Make room for '\0' explicitly.
-    utf8.resize(utf8Length + 1);
-    utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8Length + 1);
     utf8.resize(utf8Length);
+    utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8Length + 1);
     return utf8;
 }
 
@@ -467,15 +469,58 @@
     return data;
 }
 
-bool extractResFilePathParts(const StringPiece16& path, StringPiece16* outPrefix,
-                             StringPiece16* outEntry, StringPiece16* outSuffix) {
-    if (!stringStartsWith<char16_t>(path, u"res/")) {
+typename Tokenizer::iterator& Tokenizer::iterator::operator++() {
+    const char* start = mToken.end();
+    const char* end = mStr.end();
+    if (start == end) {
+        mEnd = true;
+        mToken.assign(mToken.end(), 0);
+        return *this;
+    }
+
+    start += 1;
+    const char* current = start;
+    while (current != end) {
+        if (*current == mSeparator) {
+            mToken.assign(start, current - start);
+            return *this;
+        }
+        ++current;
+    }
+    mToken.assign(start, end - start);
+    return *this;
+}
+
+bool Tokenizer::iterator::operator==(const iterator& rhs) const {
+    // We check equality here a bit differently.
+    // We need to know that the addresses are the same.
+    return mToken.begin() == rhs.mToken.begin() && mToken.end() == rhs.mToken.end() &&
+            mEnd == rhs.mEnd;
+}
+
+bool Tokenizer::iterator::operator!=(const iterator& rhs) const {
+    return !(*this == rhs);
+}
+
+Tokenizer::iterator::iterator(StringPiece s, char sep, StringPiece tok, bool end) :
+        mStr(s), mSeparator(sep), mToken(tok), mEnd(end) {
+}
+
+Tokenizer::Tokenizer(StringPiece str, char sep) :
+        mBegin(++iterator(str, sep, StringPiece(str.begin() - 1, 0), false)),
+        mEnd(str, sep, StringPiece(str.end(), 0), true) {
+}
+
+bool extractResFilePathParts(const StringPiece& path, StringPiece* outPrefix,
+                             StringPiece* outEntry, StringPiece* outSuffix) {
+    const StringPiece resPrefix("res/");
+    if (!stringStartsWith(path, resPrefix)) {
         return false;
     }
 
-    StringPiece16::const_iterator lastOccurence = path.end();
-    for (auto iter = path.begin() + StringPiece16(u"res/").size(); iter != path.end(); ++iter) {
-        if (*iter == u'/') {
+    StringPiece::const_iterator lastOccurence = path.end();
+    for (auto iter = path.begin() + resPrefix.size(); iter != path.end(); ++iter) {
+        if (*iter == '/') {
             lastOccurence = iter;
         }
     }
@@ -484,12 +529,30 @@
         return false;
     }
 
-    auto iter = std::find(lastOccurence, path.end(), u'.');
-    *outSuffix = StringPiece16(iter, path.end() - iter);
-    *outEntry = StringPiece16(lastOccurence + 1, iter - lastOccurence - 1);
-    *outPrefix = StringPiece16(path.begin(), lastOccurence - path.begin() + 1);
+    auto iter = std::find(lastOccurence, path.end(), '.');
+    *outSuffix = StringPiece(iter, path.end() - iter);
+    *outEntry = StringPiece(lastOccurence + 1, iter - lastOccurence - 1);
+    *outPrefix = StringPiece(path.begin(), lastOccurence - path.begin() + 1);
     return true;
 }
 
+StringPiece16 getString16(const android::ResStringPool& pool, size_t idx) {
+    size_t len;
+    const char16_t* str = pool.stringAt(idx, &len);
+    if (str != nullptr) {
+        return StringPiece16(str, len);
+    }
+    return StringPiece16();
+}
+
+std::string getString(const android::ResStringPool& pool, size_t idx) {
+    size_t len;
+    const char* str = pool.string8At(idx, &len);
+    if (str != nullptr) {
+        return std::string(str, len);
+    }
+    return utf16ToUtf8(getString16(pool, idx));
+}
+
 } // namespace util
 } // namespace aapt
diff --git a/tools/aapt2/util/Util.h b/tools/aapt2/util/Util.h
index 0dacbd7..4a10987 100644
--- a/tools/aapt2/util/Util.h
+++ b/tools/aapt2/util/Util.h
@@ -37,30 +37,18 @@
 /**
  * Returns true if the string starts with prefix.
  */
-template <typename T>
-bool stringStartsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& prefix) {
-    if (str.size() < prefix.size()) {
-        return false;
-    }
-    return str.substr(0, prefix.size()) == prefix;
-}
+bool stringStartsWith(const StringPiece& str, const StringPiece& prefix);
 
 /**
  * Returns true if the string ends with suffix.
  */
-template <typename T>
-bool stringEndsWith(const BasicStringPiece<T>& str, const BasicStringPiece<T>& suffix) {
-    if (str.size() < suffix.size()) {
-        return false;
-    }
-    return str.substr(str.size() - suffix.size(), suffix.size()) == suffix;
-}
+bool stringEndsWith(const StringPiece& str, const StringPiece& suffix);
 
 /**
  * Creates a new StringPiece16 that points to a substring
  * of the original string without leading or trailing whitespace.
  */
-StringPiece16 trimWhitespace(const StringPiece16& str);
+StringPiece trimWhitespace(const StringPiece& str);
 
 StringPiece trimWhitespace(const StringPiece& str);
 
@@ -76,18 +64,18 @@
  * Returns an iterator to the first character that is not alpha-numeric and that
  * is not in the allowedChars set.
  */
-StringPiece16::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece16& str,
-        const StringPiece16& allowedChars);
+StringPiece::const_iterator findNonAlphaNumericAndNotInSet(const StringPiece& str,
+                                                           const StringPiece& allowedChars);
 
 /**
  * Tests that the string is a valid Java class name.
  */
-bool isJavaClassName(const StringPiece16& str);
+bool isJavaClassName(const StringPiece& str);
 
 /**
  * Tests that the string is a valid Java package name.
  */
-bool isJavaPackageName(const StringPiece16& str);
+bool isJavaPackageName(const StringPiece& str);
 
 /**
  * Converts the class name to a fully qualified class name from the given `package`. Ex:
@@ -97,9 +85,8 @@
  * .a.b         --> package.a.b
  * asdf.adsf    --> asdf.adsf
  */
-Maybe<std::u16string> getFullyQualifiedClassName(const StringPiece16& package,
-                                                 const StringPiece16& className);
-
+Maybe<std::string> getFullyQualifiedClassName(const StringPiece& package,
+                                              const StringPiece& className);
 
 /**
  * Makes a std::unique_ptr<> with the template parameter inferred by the compiler.
@@ -147,25 +134,17 @@
 }
 
 /**
- * Helper method to extract a string from a StringPool.
+ * Helper method to extract a UTF-16 string from a StringPool. If the string is stored as UTF-8,
+ * the conversion to UTF-16 happens within ResStringPool.
  */
-inline StringPiece16 getString(const android::ResStringPool& pool, size_t idx) {
-    size_t len;
-    const char16_t* str = pool.stringAt(idx, &len);
-    if (str != nullptr) {
-        return StringPiece16(str, len);
-    }
-    return StringPiece16();
-}
+StringPiece16 getString16(const android::ResStringPool& pool, size_t idx);
 
-inline StringPiece getString8(const android::ResStringPool& pool, size_t idx) {
-    size_t len;
-    const char* str = pool.string8At(idx, &len);
-    if (str != nullptr) {
-        return StringPiece(str, len);
-    }
-    return StringPiece();
-}
+/**
+ * Helper method to extract a UTF-8 string from a StringPool. If the string is stored as UTF-16,
+ * the conversion from UTF-16 to UTF-8 does not happen in ResStringPool and is done by this method,
+ * which maintains no state or cache. This means we must return an std::string copy.
+ */
+std::string getString(const android::ResStringPool& pool, size_t idx);
 
 /**
  * Checks that the Java string format contains no non-positional arguments (arguments without
@@ -173,24 +152,24 @@
  * because translations may rearrange the order of the arguments in the string, which will
  * break the string interpolation.
  */
-bool verifyJavaStringFormat(const StringPiece16& str);
+bool verifyJavaStringFormat(const StringPiece& str);
 
 class StringBuilder {
 public:
-    StringBuilder& append(const StringPiece16& str);
-    const std::u16string& str() const;
+    StringBuilder& append(const StringPiece& str);
+    const std::string& str() const;
     const std::string& error() const;
     operator bool() const;
 
 private:
-    std::u16string mStr;
+    std::string mStr;
     bool mQuote = false;
     bool mTrailingSpace = false;
     bool mLastCharWasEscape = false;
     std::string mError;
 };
 
-inline const std::u16string& StringBuilder::str() const {
+inline const std::string& StringBuilder::str() const {
     return mStr;
 }
 
@@ -206,7 +185,7 @@
  * Converts a UTF8 string to a UTF16 string.
  */
 std::u16string utf8ToUtf16(const StringPiece& utf8);
-std::string utf16ToUtf8(const StringPiece16& utf8);
+std::string utf16ToUtf8(const StringPiece16& utf16);
 
 /**
  * Writes the entire BigBuffer to the output stream.
@@ -222,7 +201,6 @@
  * A Tokenizer implemented as an iterable collection. It does not allocate
  * any memory on the heap nor use standard containers.
  */
-template <typename Char>
 class Tokenizer {
 public:
     class iterator {
@@ -231,96 +209,41 @@
         iterator& operator=(const iterator&) = default;
 
         iterator& operator++();
-        BasicStringPiece<Char> operator*();
+
+        StringPiece operator*() {
+            return mToken;
+        }
         bool operator==(const iterator& rhs) const;
         bool operator!=(const iterator& rhs) const;
 
     private:
-        friend class Tokenizer<Char>;
+        friend class Tokenizer;
 
-        iterator(BasicStringPiece<Char> s, Char sep, BasicStringPiece<Char> tok, bool end);
+        iterator(StringPiece s, char sep, StringPiece tok, bool end);
 
-        BasicStringPiece<Char> mStr;
-        Char mSeparator;
-        BasicStringPiece<Char> mToken;
+        StringPiece mStr;
+        char mSeparator;
+        StringPiece mToken;
         bool mEnd;
     };
 
-    Tokenizer(BasicStringPiece<Char> str, Char sep);
-    iterator begin();
-    iterator end();
+    Tokenizer(StringPiece str, char sep);
+
+    iterator begin() {
+        return mBegin;
+    }
+
+    iterator end() {
+        return mEnd;
+    }
 
 private:
     const iterator mBegin;
     const iterator mEnd;
 };
 
-template <typename Char>
-inline Tokenizer<Char> tokenize(BasicStringPiece<Char> str, Char sep) {
-    return Tokenizer<Char>(str, sep);
-}
-
-template <typename Char>
-typename Tokenizer<Char>::iterator& Tokenizer<Char>::iterator::operator++() {
-    const Char* start = mToken.end();
-    const Char* end = mStr.end();
-    if (start == end) {
-        mEnd = true;
-        mToken.assign(mToken.end(), 0);
-        return *this;
-    }
-
-    start += 1;
-    const Char* current = start;
-    while (current != end) {
-        if (*current == mSeparator) {
-            mToken.assign(start, current - start);
-            return *this;
-        }
-        ++current;
-    }
-    mToken.assign(start, end - start);
-    return *this;
-}
-
-template <typename Char>
-inline BasicStringPiece<Char> Tokenizer<Char>::iterator::operator*() {
-    return mToken;
-}
-
-template <typename Char>
-inline bool Tokenizer<Char>::iterator::operator==(const iterator& rhs) const {
-    // We check equality here a bit differently.
-    // We need to know that the addresses are the same.
-    return mToken.begin() == rhs.mToken.begin() && mToken.end() == rhs.mToken.end() &&
-            mEnd == rhs.mEnd;
-}
-
-template <typename Char>
-inline bool Tokenizer<Char>::iterator::operator!=(const iterator& rhs) const {
-    return !(*this == rhs);
-}
-
-template <typename Char>
-inline Tokenizer<Char>::iterator::iterator(BasicStringPiece<Char> s, Char sep,
-                                           BasicStringPiece<Char> tok, bool end) :
-        mStr(s), mSeparator(sep), mToken(tok), mEnd(end) {
-}
-
-template <typename Char>
-inline typename Tokenizer<Char>::iterator Tokenizer<Char>::begin() {
-    return mBegin;
-}
-
-template <typename Char>
-inline typename Tokenizer<Char>::iterator Tokenizer<Char>::end() {
-    return mEnd;
-}
-
-template <typename Char>
-inline Tokenizer<Char>::Tokenizer(BasicStringPiece<Char> str, Char sep) :
-        mBegin(++iterator(str, sep, BasicStringPiece<Char>(str.begin() - 1, 0), false)),
-        mEnd(str, sep, BasicStringPiece<Char>(str.end(), 0), true) {
+inline Tokenizer tokenize(StringPiece str, char sep) {
+    return Tokenizer(str, sep);
 }
 
 inline uint16_t hostToDevice16(uint16_t value) {
@@ -348,8 +271,8 @@
  *
  * Returns true if successful.
  */
-bool extractResFilePathParts(const StringPiece16& path, StringPiece16* outPrefix,
-                             StringPiece16* outEntry, StringPiece16* outSuffix);
+bool extractResFilePathParts(const StringPiece& path, StringPiece* outPrefix,
+                             StringPiece* outEntry, StringPiece* outSuffix);
 
 } // namespace util
 
diff --git a/tools/aapt2/util/Util_test.cpp b/tools/aapt2/util/Util_test.cpp
index fad1afb..0e27213 100644
--- a/tools/aapt2/util/Util_test.cpp
+++ b/tools/aapt2/util/Util_test.cpp
@@ -14,192 +14,191 @@
  * limitations under the License.
  */
 
-#include "test/Common.h"
+#include "test/Test.h"
 #include "util/StringPiece.h"
 #include "util/Util.h"
 
-#include <gtest/gtest.h>
 #include <string>
 
 namespace aapt {
 
 TEST(UtilTest, TrimOnlyWhitespace) {
-    const std::u16string full = u"\n        ";
+    const std::string full = "\n        ";
 
-    StringPiece16 trimmed = util::trimWhitespace(full);
+    StringPiece trimmed = util::trimWhitespace(full);
     EXPECT_TRUE(trimmed.empty());
     EXPECT_EQ(0u, trimmed.size());
 }
 
 TEST(UtilTest, StringEndsWith) {
-    EXPECT_TRUE(util::stringEndsWith<char>("hello.xml", ".xml"));
+    EXPECT_TRUE(util::stringEndsWith("hello.xml", ".xml"));
 }
 
 TEST(UtilTest, StringStartsWith) {
-    EXPECT_TRUE(util::stringStartsWith<char>("hello.xml", "he"));
+    EXPECT_TRUE(util::stringStartsWith("hello.xml", "he"));
 }
 
 TEST(UtilTest, StringBuilderSplitEscapeSequence) {
-    EXPECT_EQ(StringPiece16(u"this is a new\nline."),
-              util::StringBuilder().append(u"this is a new\\")
-                                   .append(u"nline.")
+    EXPECT_EQ(StringPiece("this is a new\nline."),
+              util::StringBuilder().append("this is a new\\")
+                                   .append("nline.")
                                    .str());
 }
 
 TEST(UtilTest, StringBuilderWhitespaceRemoval) {
-    EXPECT_EQ(StringPiece16(u"hey guys this is so cool"),
-              util::StringBuilder().append(u"    hey guys ")
-                                   .append(u" this is so cool ")
+    EXPECT_EQ(StringPiece("hey guys this is so cool"),
+              util::StringBuilder().append("    hey guys ")
+                                   .append(" this is so cool ")
                                    .str());
 
-    EXPECT_EQ(StringPiece16(u" wow,  so many \t spaces. what?"),
-              util::StringBuilder().append(u" \" wow,  so many \t ")
-                                   .append(u"spaces. \"what? ")
+    EXPECT_EQ(StringPiece(" wow,  so many \t spaces. what?"),
+              util::StringBuilder().append(" \" wow,  so many \t ")
+                                   .append("spaces. \"what? ")
                                    .str());
 
-    EXPECT_EQ(StringPiece16(u"where is the pie?"),
-              util::StringBuilder().append(u"  where \t ")
-                                   .append(u" \nis the "" pie?")
+    EXPECT_EQ(StringPiece("where is the pie?"),
+              util::StringBuilder().append("  where \t ")
+                                   .append(" \nis the "" pie?")
                                    .str());
 }
 
 TEST(UtilTest, StringBuilderEscaping) {
-    EXPECT_EQ(StringPiece16(u"hey guys\n this \t is so\\ cool"),
-              util::StringBuilder().append(u"    hey guys\\n ")
-                                   .append(u" this \\t is so\\\\ cool ")
+    EXPECT_EQ(StringPiece("hey guys\n this \t is so\\ cool"),
+              util::StringBuilder().append("    hey guys\\n ")
+                                   .append(" this \\t is so\\\\ cool ")
                                    .str());
 
-    EXPECT_EQ(StringPiece16(u"@?#\\\'"),
-              util::StringBuilder().append(u"\\@\\?\\#\\\\\\'")
+    EXPECT_EQ(StringPiece("@?#\\\'"),
+              util::StringBuilder().append("\\@\\?\\#\\\\\\'")
                                    .str());
 }
 
 TEST(UtilTest, StringBuilderMisplacedQuote) {
     util::StringBuilder builder{};
-    EXPECT_FALSE(builder.append(u"they're coming!"));
+    EXPECT_FALSE(builder.append("they're coming!"));
 }
 
 TEST(UtilTest, StringBuilderUnicodeCodes) {
-    EXPECT_EQ(StringPiece16(u"\u00AF\u0AF0 woah"),
-              util::StringBuilder().append(u"\\u00AF\\u0AF0 woah")
+    EXPECT_EQ(std::string("\u00AF\u0AF0 woah"),
+              util::StringBuilder().append("\\u00AF\\u0AF0 woah")
                                    .str());
 
-    EXPECT_FALSE(util::StringBuilder().append(u"\\u00 yo"));
+    EXPECT_FALSE(util::StringBuilder().append("\\u00 yo"));
 }
 
 TEST(UtilTest, TokenizeInput) {
-    auto tokenizer = util::tokenize(StringPiece16(u"this| is|the|end"), u'|');
+    auto tokenizer = util::tokenize(StringPiece("this| is|the|end"), '|');
     auto iter = tokenizer.begin();
-    ASSERT_EQ(*iter, StringPiece16(u"this"));
+    ASSERT_EQ(*iter, StringPiece("this"));
     ++iter;
-    ASSERT_EQ(*iter, StringPiece16(u" is"));
+    ASSERT_EQ(*iter, StringPiece(" is"));
     ++iter;
-    ASSERT_EQ(*iter, StringPiece16(u"the"));
+    ASSERT_EQ(*iter, StringPiece("the"));
     ++iter;
-    ASSERT_EQ(*iter, StringPiece16(u"end"));
+    ASSERT_EQ(*iter, StringPiece("end"));
     ++iter;
     ASSERT_EQ(tokenizer.end(), iter);
 }
 
 TEST(UtilTest, TokenizeEmptyString) {
-    auto tokenizer = util::tokenize(StringPiece16(u""), u'|');
+    auto tokenizer = util::tokenize(StringPiece(""), '|');
     auto iter = tokenizer.begin();
     ASSERT_NE(tokenizer.end(), iter);
-    ASSERT_EQ(StringPiece16(), *iter);
+    ASSERT_EQ(StringPiece(), *iter);
     ++iter;
     ASSERT_EQ(tokenizer.end(), iter);
 }
 
 TEST(UtilTest, TokenizeAtEnd) {
-    auto tokenizer = util::tokenize(StringPiece16(u"one."), u'.');
+    auto tokenizer = util::tokenize(StringPiece("one."), '.');
     auto iter = tokenizer.begin();
-    ASSERT_EQ(*iter, StringPiece16(u"one"));
+    ASSERT_EQ(*iter, StringPiece("one"));
     ++iter;
     ASSERT_NE(iter, tokenizer.end());
-    ASSERT_EQ(*iter, StringPiece16());
+    ASSERT_EQ(*iter, StringPiece());
 }
 
 TEST(UtilTest, IsJavaClassName) {
-    EXPECT_TRUE(util::isJavaClassName(u"android.test.Class"));
-    EXPECT_TRUE(util::isJavaClassName(u"android.test.Class$Inner"));
-    EXPECT_TRUE(util::isJavaClassName(u"android_test.test.Class"));
-    EXPECT_TRUE(util::isJavaClassName(u"_android_.test._Class_"));
-    EXPECT_FALSE(util::isJavaClassName(u"android.test.$Inner"));
-    EXPECT_FALSE(util::isJavaClassName(u"android.test.Inner$"));
-    EXPECT_FALSE(util::isJavaClassName(u".test.Class"));
-    EXPECT_FALSE(util::isJavaClassName(u"android"));
+    EXPECT_TRUE(util::isJavaClassName("android.test.Class"));
+    EXPECT_TRUE(util::isJavaClassName("android.test.Class$Inner"));
+    EXPECT_TRUE(util::isJavaClassName("android_test.test.Class"));
+    EXPECT_TRUE(util::isJavaClassName("_android_.test._Class_"));
+    EXPECT_FALSE(util::isJavaClassName("android.test.$Inner"));
+    EXPECT_FALSE(util::isJavaClassName("android.test.Inner$"));
+    EXPECT_FALSE(util::isJavaClassName(".test.Class"));
+    EXPECT_FALSE(util::isJavaClassName("android"));
 }
 
 TEST(UtilTest, IsJavaPackageName) {
-    EXPECT_TRUE(util::isJavaPackageName(u"android"));
-    EXPECT_TRUE(util::isJavaPackageName(u"android.test"));
-    EXPECT_TRUE(util::isJavaPackageName(u"android.test_thing"));
-    EXPECT_FALSE(util::isJavaPackageName(u"_android"));
-    EXPECT_FALSE(util::isJavaPackageName(u"android_"));
-    EXPECT_FALSE(util::isJavaPackageName(u"android."));
-    EXPECT_FALSE(util::isJavaPackageName(u".android"));
-    EXPECT_FALSE(util::isJavaPackageName(u"android._test"));
-    EXPECT_FALSE(util::isJavaPackageName(u".."));
+    EXPECT_TRUE(util::isJavaPackageName("android"));
+    EXPECT_TRUE(util::isJavaPackageName("android.test"));
+    EXPECT_TRUE(util::isJavaPackageName("android.test_thing"));
+    EXPECT_FALSE(util::isJavaPackageName("_android"));
+    EXPECT_FALSE(util::isJavaPackageName("android_"));
+    EXPECT_FALSE(util::isJavaPackageName("android."));
+    EXPECT_FALSE(util::isJavaPackageName(".android"));
+    EXPECT_FALSE(util::isJavaPackageName("android._test"));
+    EXPECT_FALSE(util::isJavaPackageName(".."));
 }
 
 TEST(UtilTest, FullyQualifiedClassName) {
-    Maybe<std::u16string> res = util::getFullyQualifiedClassName(u"android", u".asdf");
+    Maybe<std::string> res = util::getFullyQualifiedClassName("android", ".asdf");
     AAPT_ASSERT_TRUE(res);
-    EXPECT_EQ(res.value(), u"android.asdf");
+    EXPECT_EQ(res.value(), "android.asdf");
 
-    res = util::getFullyQualifiedClassName(u"android", u".a.b");
+    res = util::getFullyQualifiedClassName("android", ".a.b");
     AAPT_ASSERT_TRUE(res);
-    EXPECT_EQ(res.value(), u"android.a.b");
+    EXPECT_EQ(res.value(), "android.a.b");
 
-    res = util::getFullyQualifiedClassName(u"android", u"a.b");
+    res = util::getFullyQualifiedClassName("android", "a.b");
     AAPT_ASSERT_TRUE(res);
-    EXPECT_EQ(res.value(), u"a.b");
+    EXPECT_EQ(res.value(), "a.b");
 
-    res = util::getFullyQualifiedClassName(u"", u"a.b");
+    res = util::getFullyQualifiedClassName("", "a.b");
     AAPT_ASSERT_TRUE(res);
-    EXPECT_EQ(res.value(), u"a.b");
+    EXPECT_EQ(res.value(), "a.b");
 
-    res = util::getFullyQualifiedClassName(u"android", u"Class");
+    res = util::getFullyQualifiedClassName("android", "Class");
     AAPT_ASSERT_TRUE(res);
-    EXPECT_EQ(res.value(), u"android.Class");
+    EXPECT_EQ(res.value(), "android.Class");
 
-    res = util::getFullyQualifiedClassName(u"", u"");
+    res = util::getFullyQualifiedClassName("", "");
     AAPT_ASSERT_FALSE(res);
 
-    res = util::getFullyQualifiedClassName(u"android", u"./Apple");
+    res = util::getFullyQualifiedClassName("android", "./Apple");
     AAPT_ASSERT_FALSE(res);
 }
 
 TEST(UtilTest, ExtractResourcePathComponents) {
-    StringPiece16 prefix, entry, suffix;
-    ASSERT_TRUE(util::extractResFilePathParts(u"res/xml-sw600dp/entry.xml", &prefix, &entry,
+    StringPiece prefix, entry, suffix;
+    ASSERT_TRUE(util::extractResFilePathParts("res/xml-sw600dp/entry.xml", &prefix, &entry,
                                               &suffix));
-    EXPECT_EQ(prefix, u"res/xml-sw600dp/");
-    EXPECT_EQ(entry, u"entry");
-    EXPECT_EQ(suffix, u".xml");
+    EXPECT_EQ(prefix, "res/xml-sw600dp/");
+    EXPECT_EQ(entry, "entry");
+    EXPECT_EQ(suffix, ".xml");
 
-    ASSERT_TRUE(util::extractResFilePathParts(u"res/xml-sw600dp/entry.9.png", &prefix, &entry,
+    ASSERT_TRUE(util::extractResFilePathParts("res/xml-sw600dp/entry.9.png", &prefix, &entry,
                                               &suffix));
 
-    EXPECT_EQ(prefix, u"res/xml-sw600dp/");
-    EXPECT_EQ(entry, u"entry");
-    EXPECT_EQ(suffix, u".9.png");
+    EXPECT_EQ(prefix, "res/xml-sw600dp/");
+    EXPECT_EQ(entry, "entry");
+    EXPECT_EQ(suffix, ".9.png");
 
-    EXPECT_FALSE(util::extractResFilePathParts(u"AndroidManifest.xml", &prefix, &entry, &suffix));
-    EXPECT_FALSE(util::extractResFilePathParts(u"res/.xml", &prefix, &entry, &suffix));
+    EXPECT_FALSE(util::extractResFilePathParts("AndroidManifest.xml", &prefix, &entry, &suffix));
+    EXPECT_FALSE(util::extractResFilePathParts("res/.xml", &prefix, &entry, &suffix));
 
-    ASSERT_TRUE(util::extractResFilePathParts(u"res//.", &prefix, &entry, &suffix));
-    EXPECT_EQ(prefix, u"res//");
-    EXPECT_EQ(entry, u"");
-    EXPECT_EQ(suffix, u".");
+    ASSERT_TRUE(util::extractResFilePathParts("res//.", &prefix, &entry, &suffix));
+    EXPECT_EQ(prefix, "res//");
+    EXPECT_EQ(entry, "");
+    EXPECT_EQ(suffix, ".");
 }
 
 TEST(UtilTest, VerifyJavaStringFormat) {
-    ASSERT_TRUE(util::verifyJavaStringFormat(u"%09.34f"));
-    ASSERT_TRUE(util::verifyJavaStringFormat(u"%9$.34f %8$"));
-    ASSERT_TRUE(util::verifyJavaStringFormat(u"%% %%"));
-    ASSERT_FALSE(util::verifyJavaStringFormat(u"%09$f %f"));
-    ASSERT_FALSE(util::verifyJavaStringFormat(u"%09f %08s"));
+    ASSERT_TRUE(util::verifyJavaStringFormat("%09.34f"));
+    ASSERT_TRUE(util::verifyJavaStringFormat("%9$.34f %8$"));
+    ASSERT_TRUE(util::verifyJavaStringFormat("%% %%"));
+    ASSERT_FALSE(util::verifyJavaStringFormat("%09$f %f"));
+    ASSERT_FALSE(util::verifyJavaStringFormat("%09f %08s"));
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/xml/XmlActionExecutor.cpp b/tools/aapt2/xml/XmlActionExecutor.cpp
index 0ef67ea..745079c 100644
--- a/tools/aapt2/xml/XmlActionExecutor.cpp
+++ b/tools/aapt2/xml/XmlActionExecutor.cpp
@@ -57,8 +57,7 @@
 
     for (Element* childEl : el->getChildElements()) {
         if (childEl->namespaceUri.empty()) {
-            std::map<std::u16string, XmlNodeAction>::const_iterator iter =
-                    mMap.find(childEl->name);
+            std::map<std::string, XmlNodeAction>::const_iterator iter = mMap.find(childEl->name);
             if (iter != mMap.end()) {
                 error |= !iter->second.execute(policy, diag, childEl);
                 continue;
@@ -91,7 +90,7 @@
     }
 
     if (el->namespaceUri.empty()) {
-        std::map<std::u16string, XmlNodeAction>::const_iterator iter = mMap.find(el->name);
+        std::map<std::string, XmlNodeAction>::const_iterator iter = mMap.find(el->name);
         if (iter != mMap.end()) {
             return iter->second.execute(policy, &sourceDiag, el);
         }
diff --git a/tools/aapt2/xml/XmlActionExecutor.h b/tools/aapt2/xml/XmlActionExecutor.h
index 36b94db..cad508c 100644
--- a/tools/aapt2/xml/XmlActionExecutor.h
+++ b/tools/aapt2/xml/XmlActionExecutor.h
@@ -55,7 +55,7 @@
      * Find or create a child XmlNodeAction that will be performed for the child element
      * with the name `name`.
      */
-    XmlNodeAction& operator[](const std::u16string& name) {
+    XmlNodeAction& operator[](const std::string& name) {
         return mMap[name];
     }
 
@@ -70,7 +70,7 @@
 
     bool execute(XmlActionExecutorPolicy policy, SourcePathDiagnostics* diag, Element* el) const;
 
-    std::map<std::u16string, XmlNodeAction> mMap;
+    std::map<std::string, XmlNodeAction> mMap;
     std::vector<ActionFuncWithDiag> mActions;
 };
 
@@ -86,7 +86,7 @@
      * Find or create a root XmlNodeAction that will be performed for the root XML element
      * with the name `name`.
      */
-    XmlNodeAction& operator[](const std::u16string& name) {
+    XmlNodeAction& operator[](const std::string& name) {
         return mMap[name];
     }
 
@@ -97,7 +97,7 @@
     bool execute(XmlActionExecutorPolicy policy, IDiagnostics* diag, XmlResource* doc) const;
 
 private:
-    std::map<std::u16string, XmlNodeAction> mMap;
+    std::map<std::string, XmlNodeAction> mMap;
 
     DISALLOW_COPY_AND_ASSIGN(XmlActionExecutor);
 };
diff --git a/tools/aapt2/xml/XmlActionExecutor_test.cpp b/tools/aapt2/xml/XmlActionExecutor_test.cpp
index ebf287a..106e856 100644
--- a/tools/aapt2/xml/XmlActionExecutor_test.cpp
+++ b/tools/aapt2/xml/XmlActionExecutor_test.cpp
@@ -22,8 +22,8 @@
 
 TEST(XmlActionExecutorTest, BuildsAccessibleNestedPattern) {
     XmlActionExecutor executor;
-    XmlNodeAction& manifestAction = executor[u"manifest"];
-    XmlNodeAction& applicationAction = manifestAction[u"application"];
+    XmlNodeAction& manifestAction = executor["manifest"];
+    XmlNodeAction& applicationAction = manifestAction["application"];
 
     Element* manifestEl = nullptr;
     manifestAction.action([&](Element* manifest) -> bool {
@@ -42,15 +42,15 @@
     StdErrDiagnostics diag;
     ASSERT_TRUE(executor.execute(XmlActionExecutorPolicy::None, &diag, doc.get()));
     ASSERT_NE(nullptr, manifestEl);
-    EXPECT_EQ(std::u16string(u"manifest"), manifestEl->name);
+    EXPECT_EQ(std::string("manifest"), manifestEl->name);
 
     ASSERT_NE(nullptr, applicationEl);
-    EXPECT_EQ(std::u16string(u"application"), applicationEl->name);
+    EXPECT_EQ(std::string("application"), applicationEl->name);
 }
 
 TEST(XmlActionExecutorTest, FailsWhenUndefinedHierarchyExists) {
     XmlActionExecutor executor;
-    executor[u"manifest"][u"application"];
+    executor["manifest"]["application"];
 
     std::unique_ptr<XmlResource> doc = test::buildXmlDom(
             "<manifest><application /><activity /></manifest>");
diff --git a/tools/aapt2/xml/XmlDom.cpp b/tools/aapt2/xml/XmlDom.cpp
index 0ce333a..39bd5bf 100644
--- a/tools/aapt2/xml/XmlDom.cpp
+++ b/tools/aapt2/xml/XmlDom.cpp
@@ -33,13 +33,13 @@
 struct Stack {
     std::unique_ptr<xml::Node> root;
     std::stack<xml::Node*> nodeStack;
-    std::u16string pendingComment;
+    std::string pendingComment;
 };
 
 /**
  * Extracts the namespace and name of an expanded element or attribute name.
  */
-static void splitName(const char* name, std::u16string* outNs, std::u16string* outName) {
+static void splitName(const char* name, std::string* outNs, std::string* outName) {
     const char* p = name;
     while (*p != 0 && *p != kXmlNamespaceSep) {
         p++;
@@ -47,10 +47,10 @@
 
     if (*p == 0) {
         outNs->clear();
-        *outName = util::utf8ToUtf16(name);
+        *outName = StringPiece(name).toString();
     } else {
-        *outNs = util::utf8ToUtf16(StringPiece(name, (p - name)));
-        *outName = util::utf8ToUtf16(p + 1);
+        *outNs = StringPiece(name, (p - name)).toString();
+        *outName = StringPiece(p + 1).toString();
     }
 }
 
@@ -76,11 +76,11 @@
 
     std::unique_ptr<Namespace> ns = util::make_unique<Namespace>();
     if (prefix) {
-        ns->namespacePrefix = util::utf8ToUtf16(prefix);
+        ns->namespacePrefix = StringPiece(prefix).toString();
     }
 
     if (uri) {
-        ns->namespaceUri = util::utf8ToUtf16(uri);
+        ns->namespaceUri = StringPiece(uri).toString();
     }
 
     addToStack(stack, parser, std::move(ns));
@@ -109,7 +109,7 @@
     while (*attrs) {
         Attribute attribute;
         splitName(*attrs++, &attribute.namespaceUri, &attribute.name);
-        attribute.value = util::utf8ToUtf16(*attrs++);
+        attribute.value = StringPiece(*attrs++).toString();
 
         // Insert in sorted order.
         auto iter = std::lower_bound(el->attributes.begin(), el->attributes.end(), attribute,
@@ -144,14 +144,14 @@
         if (!currentParent->children.empty()) {
             Node* lastChild = currentParent->children.back().get();
             if (Text* text = nodeCast<Text>(lastChild)) {
-                text->text += util::utf8ToUtf16(StringPiece(s, len));
+                text->text += StringPiece(s, len).toString();
                 return;
             }
         }
     }
 
     std::unique_ptr<Text> text = util::make_unique<Text>();
-    text->text = util::utf8ToUtf16(StringPiece(s, len));
+    text->text = StringPiece(s, len).toString();
     addToStack(stack, parser, std::move(text));
 }
 
@@ -162,7 +162,7 @@
     if (!stack->pendingComment.empty()) {
         stack->pendingComment += '\n';
     }
-    stack->pendingComment += util::utf8ToUtf16(comment);
+    stack->pendingComment += comment;
 }
 
 std::unique_ptr<XmlResource> inflate(std::istream* in, IDiagnostics* diag, const Source& source) {
@@ -209,17 +209,17 @@
             size_t len;
             const char16_t* str16 = parser->getAttributeNamespace(i, &len);
             if (str16) {
-                attr.namespaceUri.assign(str16, len);
+                attr.namespaceUri = util::utf16ToUtf8(StringPiece16(str16, len));
             }
 
             str16 = parser->getAttributeName(i, &len);
             if (str16) {
-                attr.name.assign(str16, len);
+                attr.name = util::utf16ToUtf8(StringPiece16(str16, len));
             }
 
             str16 = parser->getAttributeStringValue(i, &len);
             if (str16) {
-                attr.value.assign(str16, len);
+                attr.value = util::utf16ToUtf8(StringPiece16(str16, len));
             }
             el->attributes.push_back(std::move(attr));
         }
@@ -250,12 +250,12 @@
                 size_t len;
                 const char16_t* str16 = tree.getNamespacePrefix(&len);
                 if (str16) {
-                    node->namespacePrefix.assign(str16, len);
+                    node->namespacePrefix = util::utf16ToUtf8(StringPiece16(str16, len));
                 }
 
                 str16 = tree.getNamespaceUri(&len);
                 if (str16) {
-                    node->namespaceUri.assign(str16, len);
+                    node->namespaceUri = util::utf16ToUtf8(StringPiece16(str16, len));
                 }
                 newNode = std::move(node);
                 break;
@@ -266,12 +266,12 @@
                 size_t len;
                 const char16_t* str16 = tree.getElementNamespace(&len);
                 if (str16) {
-                    node->namespaceUri.assign(str16, len);
+                    node->namespaceUri = util::utf16ToUtf8(StringPiece16(str16, len));
                 }
 
                 str16 = tree.getElementName(&len);
                 if (str16) {
-                    node->name.assign(str16, len);
+                    node->name = util::utf16ToUtf8(StringPiece16(str16, len));
                 }
 
                 copyAttributes(node.get(), &tree);
@@ -285,7 +285,7 @@
                 size_t len;
                 const char16_t* str16 = tree.getText(&len);
                 if (str16) {
-                    node->text.assign(str16, len);
+                    node->text = util::utf16ToUtf8(StringPiece16(str16, len));
                 }
                 newNode = std::move(node);
                 break;
@@ -347,7 +347,7 @@
     children.push_back(std::move(child));
 }
 
-Attribute* Element::findAttribute(const StringPiece16& ns, const StringPiece16& name) {
+Attribute* Element::findAttribute(const StringPiece& ns, const StringPiece& name) {
     for (auto& attr : attributes) {
         if (ns == attr.namespaceUri && name == attr.name) {
             return &attr;
@@ -356,13 +356,13 @@
     return nullptr;
 }
 
-Element* Element::findChild(const StringPiece16& ns, const StringPiece16& name) {
+Element* Element::findChild(const StringPiece& ns, const StringPiece& name) {
     return findChildWithAttribute(ns, name, {}, {}, {});
 }
 
-Element* Element::findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name,
-                                         const StringPiece16& attrNs, const StringPiece16& attrName,
-                                         const StringPiece16& attrValue) {
+Element* Element::findChildWithAttribute(const StringPiece& ns, const StringPiece& name,
+                                         const StringPiece& attrNs, const StringPiece& attrName,
+                                         const StringPiece& attrValue) {
     for (auto& childNode : children) {
         Node* child = childNode.get();
         while (nodeCast<Namespace>(child)) {
@@ -422,7 +422,7 @@
 }
 
 Maybe<ExtractedPackage> PackageAwareVisitor::transformPackageAlias(
-       const StringPiece16& alias, const StringPiece16& localPackage) const {
+       const StringPiece& alias, const StringPiece& localPackage) const {
    if (alias.empty()) {
        return ExtractedPackage{ localPackage.toString(), false /* private */ };
    }
diff --git a/tools/aapt2/xml/XmlDom.h b/tools/aapt2/xml/XmlDom.h
index b374d20..d083d82 100644
--- a/tools/aapt2/xml/XmlDom.h
+++ b/tools/aapt2/xml/XmlDom.h
@@ -41,7 +41,7 @@
     Node* parent = nullptr;
     size_t lineNumber = 0;
     size_t columnNumber = 0;
-    std::u16string comment;
+    std::string comment;
     std::vector<std::unique_ptr<Node>> children;
 
     virtual ~Node() = default;
@@ -63,8 +63,8 @@
  * A Namespace XML node. Can only have one child.
  */
 struct Namespace : public BaseNode<Namespace> {
-    std::u16string namespacePrefix;
-    std::u16string namespaceUri;
+    std::string namespacePrefix;
+    std::string namespaceUri;
 };
 
 struct AaptAttribute {
@@ -76,9 +76,9 @@
  * An XML attribute.
  */
 struct Attribute {
-    std::u16string namespaceUri;
-    std::u16string name;
-    std::u16string value;
+    std::string namespaceUri;
+    std::string name;
+    std::string value;
 
     Maybe<AaptAttribute> compiledAttribute;
     std::unique_ptr<Item> compiledValue;
@@ -88,16 +88,16 @@
  * An Element XML node.
  */
 struct Element : public BaseNode<Element> {
-    std::u16string namespaceUri;
-    std::u16string name;
+    std::string namespaceUri;
+    std::string name;
     std::vector<Attribute> attributes;
 
-    Attribute* findAttribute(const StringPiece16& ns, const StringPiece16& name);
-    xml::Element* findChild(const StringPiece16& ns, const StringPiece16& name);
-    xml::Element* findChildWithAttribute(const StringPiece16& ns, const StringPiece16& name,
-                                         const StringPiece16& attrNs,
-                                         const StringPiece16& attrName,
-                                         const StringPiece16& attrValue);
+    Attribute* findAttribute(const StringPiece& ns, const StringPiece& name);
+    xml::Element* findChild(const StringPiece& ns, const StringPiece& name);
+    xml::Element* findChildWithAttribute(const StringPiece& ns, const StringPiece& name,
+                                         const StringPiece& attrNs,
+                                         const StringPiece& attrName,
+                                         const StringPiece& attrValue);
     std::vector<xml::Element*> getChildElements();
 };
 
@@ -105,7 +105,7 @@
  * A Text (CDATA) XML node. Can not have any children.
  */
 struct Text : public BaseNode<Text> {
-    std::u16string text;
+    std::string text;
 };
 
 /**
@@ -175,7 +175,7 @@
 class PackageAwareVisitor : public Visitor, public IPackageDeclStack {
 private:
     struct PackageDecl {
-        std::u16string prefix;
+        std::string prefix;
         ExtractedPackage package;
     };
 
@@ -186,7 +186,7 @@
 
     void visit(Namespace* ns) override;
     Maybe<ExtractedPackage> transformPackageAlias(
-            const StringPiece16& alias, const StringPiece16& localPackage) const override;
+            const StringPiece& alias, const StringPiece& localPackage) const override;
 };
 
 // Implementations
diff --git a/tools/aapt2/xml/XmlDom_test.cpp b/tools/aapt2/xml/XmlDom_test.cpp
index 431ee2c..1909f75 100644
--- a/tools/aapt2/xml/XmlDom_test.cpp
+++ b/tools/aapt2/xml/XmlDom_test.cpp
@@ -43,8 +43,8 @@
 
     xml::Namespace* ns = xml::nodeCast<xml::Namespace>(doc->root.get());
     ASSERT_NE(ns, nullptr);
-    EXPECT_EQ(ns->namespaceUri, u"http://schemas.android.com/apk/res/android");
-    EXPECT_EQ(ns->namespacePrefix, u"android");
+    EXPECT_EQ(ns->namespaceUri, xml::kSchemaAndroid);
+    EXPECT_EQ(ns->namespacePrefix, "android");
 }
 
 } // namespace aapt
diff --git a/tools/aapt2/xml/XmlPullParser.cpp b/tools/aapt2/xml/XmlPullParser.cpp
index 323ec05..4a944f1 100644
--- a/tools/aapt2/xml/XmlPullParser.cpp
+++ b/tools/aapt2/xml/XmlPullParser.cpp
@@ -98,7 +98,7 @@
     return mLastError;
 }
 
-const std::u16string& XmlPullParser::getComment() const {
+const std::string& XmlPullParser::getComment() const {
     return mEventQueue.front().data1;
 }
 
@@ -110,14 +110,14 @@
     return mEventQueue.front().depth;
 }
 
-const std::u16string& XmlPullParser::getText() const {
+const std::string& XmlPullParser::getText() const {
     if (getEvent() != Event::kText) {
         return mEmpty;
     }
     return mEventQueue.front().data1;
 }
 
-const std::u16string& XmlPullParser::getNamespacePrefix() const {
+const std::string& XmlPullParser::getNamespacePrefix() const {
     const Event currentEvent = getEvent();
     if (currentEvent != Event::kStartNamespace && currentEvent != Event::kEndNamespace) {
         return mEmpty;
@@ -125,7 +125,7 @@
     return mEventQueue.front().data1;
 }
 
-const std::u16string& XmlPullParser::getNamespaceUri() const {
+const std::string& XmlPullParser::getNamespaceUri() const {
     const Event currentEvent = getEvent();
     if (currentEvent != Event::kStartNamespace && currentEvent != Event::kEndNamespace) {
         return mEmpty;
@@ -134,7 +134,7 @@
 }
 
 Maybe<ExtractedPackage> XmlPullParser::transformPackageAlias(
-        const StringPiece16& alias, const StringPiece16& localPackage) const {
+        const StringPiece& alias, const StringPiece& localPackage) const {
     if (alias.empty()) {
         return ExtractedPackage{ localPackage.toString(), false /* private */ };
     }
@@ -152,7 +152,7 @@
     return {};
 }
 
-const std::u16string& XmlPullParser::getElementNamespace() const {
+const std::string& XmlPullParser::getElementNamespace() const {
     const Event currentEvent = getEvent();
     if (currentEvent != Event::kStartElement && currentEvent != Event::kEndElement) {
         return mEmpty;
@@ -160,7 +160,7 @@
     return mEventQueue.front().data1;
 }
 
-const std::u16string& XmlPullParser::getElementName() const {
+const std::string& XmlPullParser::getElementName() const {
     const Event currentEvent = getEvent();
     if (currentEvent != Event::kStartElement && currentEvent != Event::kEndElement) {
         return mEmpty;
@@ -186,31 +186,31 @@
 /**
  * Extracts the namespace and name of an expanded element or attribute name.
  */
-static void splitName(const char* name, std::u16string& outNs, std::u16string& outName) {
+static void splitName(const char* name, std::string& outNs, std::string& outName) {
     const char* p = name;
     while (*p != 0 && *p != kXmlNamespaceSep) {
         p++;
     }
 
     if (*p == 0) {
-        outNs = std::u16string();
-        outName = util::utf8ToUtf16(name);
+        outNs = std::string();
+        outName = name;
     } else {
-        outNs = util::utf8ToUtf16(StringPiece(name, (p - name)));
-        outName = util::utf8ToUtf16(p + 1);
+        outNs = StringPiece(name, (p - name)).toString();
+        outName = p + 1;
     }
 }
 
 void XMLCALL XmlPullParser::startNamespaceHandler(void* userData, const char* prefix,
         const char* uri) {
     XmlPullParser* parser = reinterpret_cast<XmlPullParser*>(userData);
-    std::u16string namespaceUri = uri != nullptr ? util::utf8ToUtf16(uri) : std::u16string();
+    std::string namespaceUri = uri != nullptr ? uri : std::string();
     parser->mNamespaceUris.push(namespaceUri);
     parser->mEventQueue.push(EventData{
             Event::kStartNamespace,
             XML_GetCurrentLineNumber(parser->mParser),
             parser->mDepth++,
-            prefix != nullptr ? util::utf8ToUtf16(prefix) : std::u16string(),
+            prefix != nullptr ? prefix : std::string(),
             namespaceUri
     });
 }
@@ -227,7 +227,7 @@
     while (*attrs) {
         Attribute attribute;
         splitName(*attrs++, attribute.namespaceUri, attribute.name);
-        attribute.value = util::utf8ToUtf16(*attrs++);
+        attribute.value = *attrs++;
 
         // Insert in sorted order.
         auto iter = std::lower_bound(data.attributes.begin(), data.attributes.end(), attribute);
@@ -245,7 +245,7 @@
             Event::kText,
             XML_GetCurrentLineNumber(parser->mParser),
             parser->mDepth,
-            util::utf8ToUtf16(StringPiece(s, len))
+            StringPiece(s, len).toString()
     });
 }
 
@@ -268,7 +268,7 @@
             Event::kEndNamespace,
             XML_GetCurrentLineNumber(parser->mParser),
             --(parser->mDepth),
-            prefix != nullptr ? util::utf8ToUtf16(prefix) : std::u16string(),
+            prefix != nullptr ? prefix : std::string(),
             parser->mNamespaceUris.top()
     });
     parser->mNamespaceUris.pop();
@@ -281,22 +281,22 @@
             Event::kComment,
             XML_GetCurrentLineNumber(parser->mParser),
             parser->mDepth,
-            util::utf8ToUtf16(comment)
+            comment
     });
 }
 
-Maybe<StringPiece16> findAttribute(const XmlPullParser* parser, const StringPiece16& name) {
-    auto iter = parser->findAttribute(u"", name);
+Maybe<StringPiece> findAttribute(const XmlPullParser* parser, const StringPiece& name) {
+    auto iter = parser->findAttribute("", name);
     if (iter != parser->endAttributes()) {
-        return StringPiece16(util::trimWhitespace(iter->value));
+        return StringPiece(util::trimWhitespace(iter->value));
     }
     return {};
 }
 
-Maybe<StringPiece16> findNonEmptyAttribute(const XmlPullParser* parser, const StringPiece16& name) {
-    auto iter = parser->findAttribute(u"", name);
+Maybe<StringPiece> findNonEmptyAttribute(const XmlPullParser* parser, const StringPiece& name) {
+    auto iter = parser->findAttribute("", name);
     if (iter != parser->endAttributes()) {
-        StringPiece16 trimmed = util::trimWhitespace(iter->value);
+        StringPiece trimmed = util::trimWhitespace(iter->value);
         if (!trimmed.empty()) {
             return trimmed;
         }
diff --git a/tools/aapt2/xml/XmlPullParser.h b/tools/aapt2/xml/XmlPullParser.h
index 7e7070e..ee51b36 100644
--- a/tools/aapt2/xml/XmlPullParser.h
+++ b/tools/aapt2/xml/XmlPullParser.h
@@ -80,28 +80,28 @@
     // These are available for all nodes.
     //
 
-    const std::u16string& getComment() const;
+    const std::string& getComment() const;
     size_t getLineNumber() const;
     size_t getDepth() const;
 
     /**
      * Returns the character data for a Text event.
      */
-    const std::u16string& getText() const;
+    const std::string& getText() const;
 
     //
     // Namespace prefix and URI are available for StartNamespace and EndNamespace.
     //
 
-    const std::u16string& getNamespacePrefix() const;
-    const std::u16string& getNamespaceUri() const;
+    const std::string& getNamespacePrefix() const;
+    const std::string& getNamespaceUri() const;
 
     //
     // These are available for StartElement and EndElement.
     //
 
-    const std::u16string& getElementNamespace() const;
-    const std::u16string& getElementName() const;
+    const std::string& getElementNamespace() const;
+    const std::string& getElementName() const;
 
     /*
      * Uses the current stack of namespaces to resolve the package. Eg:
@@ -115,7 +115,7 @@
      * 'package' will be set to 'defaultPackage'.
      */
     Maybe<ExtractedPackage> transformPackageAlias(
-            const StringPiece16& alias, const StringPiece16& localPackage) const override;
+            const StringPiece& alias, const StringPiece& localPackage) const override;
 
     //
     // Remaining methods are for retrieving information about attributes
@@ -126,9 +126,9 @@
     //
 
     struct Attribute {
-        std::u16string namespaceUri;
-        std::u16string name;
-        std::u16string value;
+        std::string namespaceUri;
+        std::string name;
+        std::string value;
 
         int compare(const Attribute& rhs) const;
         bool operator<(const Attribute& rhs) const;
@@ -141,7 +141,7 @@
     const_iterator beginAttributes() const;
     const_iterator endAttributes() const;
     size_t getAttributeCount() const;
-    const_iterator findAttribute(StringPiece16 namespaceUri, StringPiece16 name) const;
+    const_iterator findAttribute(StringPiece namespaceUri, StringPiece name) const;
 
 private:
     static void XMLCALL startNamespaceHandler(void* userData, const char* prefix, const char* uri);
@@ -155,8 +155,8 @@
         Event event;
         size_t lineNumber;
         size_t depth;
-        std::u16string data1;
-        std::u16string data2;
+        std::string data1;
+        std::string data2;
         std::vector<Attribute> attributes;
     };
 
@@ -165,12 +165,12 @@
     char mBuffer[16384];
     std::queue<EventData> mEventQueue;
     std::string mLastError;
-    const std::u16string mEmpty;
+    const std::string mEmpty;
     size_t mDepth;
-    std::stack<std::u16string> mNamespaceUris;
+    std::stack<std::string> mNamespaceUris;
 
     struct PackageDecl {
-        std::u16string prefix;
+        std::string prefix;
         ExtractedPackage package;
     };
     std::vector<PackageDecl> mPackageAliases;
@@ -179,13 +179,13 @@
 /**
  * Finds the attribute in the current element within the global namespace.
  */
-Maybe<StringPiece16> findAttribute(const XmlPullParser* parser, const StringPiece16& name);
+Maybe<StringPiece> findAttribute(const XmlPullParser* parser, const StringPiece& name);
 
 /**
  * Finds the attribute in the current element within the global namespace. The attribute's value
  * must not be the empty string.
  */
-Maybe<StringPiece16> findNonEmptyAttribute(const XmlPullParser* parser, const StringPiece16& name);
+Maybe<StringPiece> findNonEmptyAttribute(const XmlPullParser* parser, const StringPiece& name);
 
 //
 // Implementation
@@ -270,12 +270,12 @@
     return compare(rhs) != 0;
 }
 
-inline XmlPullParser::const_iterator XmlPullParser::findAttribute(StringPiece16 namespaceUri,
-                                                                  StringPiece16 name) const {
+inline XmlPullParser::const_iterator XmlPullParser::findAttribute(StringPiece namespaceUri,
+                                                                  StringPiece name) const {
     const auto endIter = endAttributes();
     const auto iter = std::lower_bound(beginAttributes(), endIter,
-            std::pair<StringPiece16, StringPiece16>(namespaceUri, name),
-            [](const Attribute& attr, const std::pair<StringPiece16, StringPiece16>& rhs) -> bool {
+            std::pair<StringPiece, StringPiece>(namespaceUri, name),
+            [](const Attribute& attr, const std::pair<StringPiece, StringPiece>& rhs) -> bool {
                 int cmp = attr.namespaceUri.compare(0, attr.namespaceUri.size(),
                         rhs.first.data(), rhs.first.size());
                 if (cmp < 0) return true;
diff --git a/tools/aapt2/xml/XmlPullParser_test.cpp b/tools/aapt2/xml/XmlPullParser_test.cpp
index 8fa2c6d..2c1fdc7 100644
--- a/tools/aapt2/xml/XmlPullParser_test.cpp
+++ b/tools/aapt2/xml/XmlPullParser_test.cpp
@@ -14,10 +14,10 @@
  * limitations under the License.
  */
 
+#include "test/Test.h"
 #include "util/StringPiece.h"
 #include "xml/XmlPullParser.h"
 
-#include <gtest/gtest.h>
 #include <sstream>
 
 namespace aapt {
@@ -32,21 +32,21 @@
     ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthOuter));
 
     EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
-    EXPECT_EQ(StringPiece16(u"a"), StringPiece16(parser.getElementName()));
+    EXPECT_EQ(StringPiece("a"), StringPiece(parser.getElementName()));
 
     const size_t depthA = parser.getDepth();
     ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthA));
     EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
-    EXPECT_EQ(StringPiece16(u"b"), StringPiece16(parser.getElementName()));
+    EXPECT_EQ(StringPiece("b"), StringPiece(parser.getElementName()));
 
     const size_t depthB = parser.getDepth();
     ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthB));
     EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
-    EXPECT_EQ(StringPiece16(u"c"), StringPiece16(parser.getElementName()));
+    EXPECT_EQ(StringPiece("c"), StringPiece(parser.getElementName()));
 
     ASSERT_TRUE(xml::XmlPullParser::nextChildNode(&parser, depthB));
     EXPECT_EQ(xml::XmlPullParser::Event::kStartElement, parser.getEvent());
-    EXPECT_EQ(StringPiece16(u"e"), StringPiece16(parser.getElementName()));
+    EXPECT_EQ(StringPiece("e"), StringPiece(parser.getElementName()));
 
     ASSERT_FALSE(xml::XmlPullParser::nextChildNode(&parser, depthOuter));
     EXPECT_EQ(xml::XmlPullParser::Event::kEndDocument, parser.getEvent());
diff --git a/tools/aapt2/xml/XmlUtil.cpp b/tools/aapt2/xml/XmlUtil.cpp
index ab9f544..0e9d005 100644
--- a/tools/aapt2/xml/XmlUtil.cpp
+++ b/tools/aapt2/xml/XmlUtil.cpp
@@ -23,19 +23,25 @@
 namespace aapt {
 namespace xml {
 
-Maybe<ExtractedPackage> extractPackageFromNamespace(const std::u16string& namespaceUri) {
-    if (util::stringStartsWith<char16_t>(namespaceUri, kSchemaPublicPrefix)) {
-        StringPiece16 schemaPrefix = kSchemaPublicPrefix;
-        StringPiece16 package = namespaceUri;
+std::string buildPackageNamespace(const StringPiece& package) {
+    std::string result = kSchemaPublicPrefix;
+    result.append(package.data(), package.size());
+    return result;
+}
+
+Maybe<ExtractedPackage> extractPackageFromNamespace(const std::string& namespaceUri) {
+    if (util::stringStartsWith(namespaceUri, kSchemaPublicPrefix)) {
+        StringPiece schemaPrefix = kSchemaPublicPrefix;
+        StringPiece package = namespaceUri;
         package = package.substr(schemaPrefix.size(), package.size() - schemaPrefix.size());
         if (package.empty()) {
             return {};
         }
         return ExtractedPackage{ package.toString(), false /* isPrivate */ };
 
-    } else if (util::stringStartsWith<char16_t>(namespaceUri, kSchemaPrivatePrefix)) {
-        StringPiece16 schemaPrefix = kSchemaPrivatePrefix;
-        StringPiece16 package = namespaceUri;
+    } else if (util::stringStartsWith(namespaceUri, kSchemaPrivatePrefix)) {
+        StringPiece schemaPrefix = kSchemaPrivatePrefix;
+        StringPiece package = namespaceUri;
         package = package.substr(schemaPrefix.size(), package.size() - schemaPrefix.size());
         if (package.empty()) {
             return {};
@@ -43,13 +49,13 @@
         return ExtractedPackage{ package.toString(), true /* isPrivate */ };
 
     } else if (namespaceUri == kSchemaAuto) {
-        return ExtractedPackage{ std::u16string(), true /* isPrivate */ };
+        return ExtractedPackage{ std::string(), true /* isPrivate */ };
     }
     return {};
 }
 
 void transformReferenceFromNamespace(IPackageDeclStack* declStack,
-                                     const StringPiece16& localPackage, Reference* inRef) {
+                                     const StringPiece& localPackage, Reference* inRef) {
     if (inRef->name) {
         if (Maybe<ExtractedPackage> transformedPackage =
                    declStack->transformPackageAlias(inRef->name.value().package, localPackage)) {
diff --git a/tools/aapt2/xml/XmlUtil.h b/tools/aapt2/xml/XmlUtil.h
index 98e5520..f0d59b7 100644
--- a/tools/aapt2/xml/XmlUtil.h
+++ b/tools/aapt2/xml/XmlUtil.h
@@ -25,10 +25,10 @@
 namespace aapt {
 namespace xml {
 
-constexpr const char16_t* kSchemaAuto = u"http://schemas.android.com/apk/res-auto";
-constexpr const char16_t* kSchemaPublicPrefix = u"http://schemas.android.com/apk/res/";
-constexpr const char16_t* kSchemaPrivatePrefix = u"http://schemas.android.com/apk/prv/res/";
-constexpr const char16_t* kSchemaAndroid = u"http://schemas.android.com/apk/res/android";
+constexpr const char* kSchemaAuto = "http://schemas.android.com/apk/res-auto";
+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";
 
 /**
  * Result of extracting a package name from a namespace URI declaration.
@@ -38,7 +38,7 @@
      * The name of the package. This can be the empty string, which means that the package
      * should be assumed to be the package being compiled.
      */
-    std::u16string package;
+    std::string package;
 
     /**
      * True if the package's private namespace was declared. This means that private resources
@@ -55,7 +55,14 @@
  * Special case: if namespaceUri is http://schemas.android.com/apk/res-auto,
  * returns an empty package name.
  */
-Maybe<ExtractedPackage> extractPackageFromNamespace(const std::u16string& namespaceUri);
+Maybe<ExtractedPackage> extractPackageFromNamespace(const std::string& namespaceUri);
+
+/**
+ * Returns an XML Android namespace for the given package of the form:
+ *
+ * http://schemas.android.com/apk/res/<package>
+ */
+std::string buildPackageNamespace(const StringPiece& package);
 
 /**
  * Interface representing a stack of XML namespace declarations. When looking up the package
@@ -68,7 +75,7 @@
      * Returns an ExtractedPackage struct if the alias given corresponds with a package declaration.
      */
     virtual Maybe<ExtractedPackage> transformPackageAlias(
-            const StringPiece16& alias, const StringPiece16& localPackage) const = 0;
+            const StringPiece& alias, const StringPiece& localPackage) const = 0;
 };
 
 /**
@@ -77,7 +84,7 @@
  * the package declaration was private.
  */
 void transformReferenceFromNamespace(IPackageDeclStack* declStack,
-                                     const StringPiece16& localPackage, Reference* inRef);
+                                     const StringPiece& localPackage, Reference* inRef);
 
 } // namespace xml
 } // namespace aapt
diff --git a/tools/aapt2/xml/XmlUtil_test.cpp b/tools/aapt2/xml/XmlUtil_test.cpp
index 319e770..cbeb8bc 100644
--- a/tools/aapt2/xml/XmlUtil_test.cpp
+++ b/tools/aapt2/xml/XmlUtil_test.cpp
@@ -14,40 +14,37 @@
  * limitations under the License.
  */
 
-#include "test/Common.h"
+#include "test/Test.h"
 #include "xml/XmlUtil.h"
 
-#include <gtest/gtest.h>
-
 namespace aapt {
 
 TEST(XmlUtilTest, ExtractPackageFromNamespace) {
-    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace(u"com.android"));
-    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace(u"http://schemas.android.com/apk"));
-    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res"));
-    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res/"));
-    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace(
-            u"http://schemas.android.com/apk/prv/res/"));
+    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace("com.android"));
+    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace("http://schemas.android.com/apk"));
+    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace("http://schemas.android.com/apk/res"));
+    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace("http://schemas.android.com/apk/res/"));
+    AAPT_ASSERT_FALSE(xml::extractPackageFromNamespace("http://schemas.android.com/apk/prv/res/"));
 
     Maybe<xml::ExtractedPackage> p =
-            xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res/a");
+            xml::extractPackageFromNamespace("http://schemas.android.com/apk/res/a");
     AAPT_ASSERT_TRUE(p);
-    EXPECT_EQ(std::u16string(u"a"), p.value().package);
+    EXPECT_EQ(std::string("a"), p.value().package);
     EXPECT_FALSE(p.value().privateNamespace);
 
-    p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/prv/res/android");
+    p = xml::extractPackageFromNamespace("http://schemas.android.com/apk/prv/res/android");
     AAPT_ASSERT_TRUE(p);
-    EXPECT_EQ(std::u16string(u"android"), p.value().package);
+    EXPECT_EQ(std::string("android"), p.value().package);
     EXPECT_TRUE(p.value().privateNamespace);
 
-    p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/prv/res/com.test");
+    p = xml::extractPackageFromNamespace("http://schemas.android.com/apk/prv/res/com.test");
     AAPT_ASSERT_TRUE(p);
-    EXPECT_EQ(std::u16string(u"com.test"), p.value().package);
+    EXPECT_EQ(std::string("com.test"), p.value().package);
     EXPECT_TRUE(p.value().privateNamespace);
 
-    p = xml::extractPackageFromNamespace(u"http://schemas.android.com/apk/res-auto");
+    p = xml::extractPackageFromNamespace("http://schemas.android.com/apk/res-auto");
     AAPT_ASSERT_TRUE(p);
-    EXPECT_EQ(std::u16string(), p.value().package);
+    EXPECT_EQ(std::string(), p.value().package);
     EXPECT_TRUE(p.value().privateNamespace);
 }