Use Google3 style guide with .clang-format

Test: style change only, builds ok
Change-Id: I885180e24cb2e7b58cfb4967c3bcb40058ce4078
diff --git a/tools/aapt2/link/AutoVersioner.cpp b/tools/aapt2/link/AutoVersioner.cpp
index 8ed27c3..5ba9819 100644
--- a/tools/aapt2/link/AutoVersioner.cpp
+++ b/tools/aapt2/link/AutoVersioner.cpp
@@ -25,117 +25,128 @@
 
 namespace aapt {
 
-bool shouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config,
+bool shouldGenerateVersionedResource(const ResourceEntry* entry,
+                                     const ConfigDescription& config,
                                      const int sdkVersionToGenerate) {
-    // We assume the caller is trying to generate a version greater than the current configuration.
-    assert(sdkVersionToGenerate > config.sdkVersion);
+  // We assume the caller is trying to generate a version greater than the
+  // current configuration.
+  assert(sdkVersionToGenerate > config.sdkVersion);
 
-    const auto endIter = entry->values.end();
-    auto iter = entry->values.begin();
-    for (; iter != endIter; ++iter) {
-        if ((*iter)->config == config) {
-            break;
-        }
+  const auto endIter = entry->values.end();
+  auto iter = entry->values.begin();
+  for (; iter != endIter; ++iter) {
+    if ((*iter)->config == config) {
+      break;
     }
+  }
 
-    // The source config came from this list, so it should be here.
-    assert(iter != entry->values.end());
-    ++iter;
+  // The source config came from this list, so it should be here.
+  assert(iter != entry->values.end());
+  ++iter;
 
-    // The next configuration either only varies in sdkVersion, or it is completely different
-    // and therefore incompatible. If it is incompatible, we must generate the versioned resource.
+  // The next configuration either only varies in sdkVersion, or it is
+  // completely different
+  // and therefore incompatible. If it is incompatible, we must generate the
+  // versioned resource.
 
-    // NOTE: The ordering of configurations takes sdkVersion as higher precedence than other
-    // qualifiers, so we need to iterate through the entire list to be sure there
-    // are no higher sdk level versions of this resource.
-    ConfigDescription tempConfig(config);
-    for (; iter != endIter; ++iter) {
-        tempConfig.sdkVersion = (*iter)->config.sdkVersion;
-        if (tempConfig == (*iter)->config) {
-            // The two configs are the same, check the sdk version.
-            return sdkVersionToGenerate < (*iter)->config.sdkVersion;
-        }
+  // NOTE: The ordering of configurations takes sdkVersion as higher precedence
+  // than other
+  // qualifiers, so we need to iterate through the entire list to be sure there
+  // are no higher sdk level versions of this resource.
+  ConfigDescription tempConfig(config);
+  for (; iter != endIter; ++iter) {
+    tempConfig.sdkVersion = (*iter)->config.sdkVersion;
+    if (tempConfig == (*iter)->config) {
+      // The two configs are the same, check the sdk version.
+      return sdkVersionToGenerate < (*iter)->config.sdkVersion;
     }
+  }
 
-    // No match was found, so we should generate the versioned resource.
-    return true;
+  // No match was found, so we should generate the versioned resource.
+  return true;
 }
 
 bool AutoVersioner::consume(IAaptContext* context, ResourceTable* table) {
-    for (auto& package : table->packages) {
-        for (auto& type : package->types) {
-            if (type->type != ResourceType::kStyle) {
-                continue;
-            }
+  for (auto& package : table->packages) {
+    for (auto& type : package->types) {
+      if (type->type != ResourceType::kStyle) {
+        continue;
+      }
 
-            for (auto& entry : type->entries) {
-                for (size_t i = 0; i < entry->values.size(); i++) {
-                    ResourceConfigValue* configValue = entry->values[i].get();
-                    if (configValue->config.sdkVersion >= SDK_LOLLIPOP_MR1) {
-                        // If this configuration is only used on L-MR1 then we don't need
-                        // to do anything since we use private attributes since that version.
-                        continue;
-                    }
+      for (auto& entry : type->entries) {
+        for (size_t i = 0; i < entry->values.size(); i++) {
+          ResourceConfigValue* configValue = entry->values[i].get();
+          if (configValue->config.sdkVersion >= SDK_LOLLIPOP_MR1) {
+            // If this configuration is only used on L-MR1 then we don't need
+            // to do anything since we use private attributes since that
+            // version.
+            continue;
+          }
 
-                    if (Style* style = valueCast<Style>(configValue->value.get())) {
-                        Maybe<size_t> minSdkStripped;
-                        std::vector<Style::Entry> stripped;
+          if (Style* style = valueCast<Style>(configValue->value.get())) {
+            Maybe<size_t> minSdkStripped;
+            std::vector<Style::Entry> stripped;
 
-                        auto iter = style->entries.begin();
-                        while (iter != style->entries.end()) {
-                            assert(iter->key.id && "IDs must be assigned and linked");
+            auto iter = style->entries.begin();
+            while (iter != style->entries.end()) {
+              assert(iter->key.id && "IDs must be assigned and linked");
 
-                            // Find the SDK level that is higher than the configuration allows.
-                            const size_t sdkLevel = findAttributeSdkLevel(iter->key.id.value());
-                            if (sdkLevel > std::max<size_t>(configValue->config.sdkVersion, 1)) {
-                                // Record that we are about to strip this.
-                                stripped.emplace_back(std::move(*iter));
+              // Find the SDK level that is higher than the configuration
+              // allows.
+              const size_t sdkLevel =
+                  findAttributeSdkLevel(iter->key.id.value());
+              if (sdkLevel >
+                  std::max<size_t>(configValue->config.sdkVersion, 1)) {
+                // Record that we are about to strip this.
+                stripped.emplace_back(std::move(*iter));
 
-                                // We use the smallest SDK level to generate the new style.
-                                if (minSdkStripped) {
-                                    minSdkStripped = std::min(minSdkStripped.value(), sdkLevel);
-                                } else {
-                                    minSdkStripped = sdkLevel;
-                                }
-
-                                // Erase this from this style.
-                                iter = style->entries.erase(iter);
-                                continue;
-                            }
-                            ++iter;
-                        }
-
-                        if (minSdkStripped && !stripped.empty()) {
-                            // We found attributes from a higher SDK level. Check that
-                            // there is no other defined resource for the version we want to
-                            // generate.
-                            if (shouldGenerateVersionedResource(entry.get(),
-                                                                configValue->config,
-                                                                minSdkStripped.value())) {
-                                // Let's create a new Style for this versioned resource.
-                                ConfigDescription newConfig(configValue->config);
-                                newConfig.sdkVersion = minSdkStripped.value();
-
-                                std::unique_ptr<Style> newStyle(style->clone(&table->stringPool));
-                                newStyle->setComment(style->getComment());
-                                newStyle->setSource(style->getSource());
-
-                                // Move the previously stripped attributes into this style.
-                                newStyle->entries.insert(newStyle->entries.end(),
-                                                         std::make_move_iterator(stripped.begin()),
-                                                         std::make_move_iterator(stripped.end()));
-
-                                // Insert the new Resource into the correct place.
-                                entry->findOrCreateValue(newConfig, {})->value =
-                                        std::move(newStyle);
-                            }
-                        }
-                    }
+                // We use the smallest SDK level to generate the new style.
+                if (minSdkStripped) {
+                  minSdkStripped = std::min(minSdkStripped.value(), sdkLevel);
+                } else {
+                  minSdkStripped = sdkLevel;
                 }
+
+                // Erase this from this style.
+                iter = style->entries.erase(iter);
+                continue;
+              }
+              ++iter;
             }
+
+            if (minSdkStripped && !stripped.empty()) {
+              // We found attributes from a higher SDK level. Check that
+              // there is no other defined resource for the version we want to
+              // generate.
+              if (shouldGenerateVersionedResource(entry.get(),
+                                                  configValue->config,
+                                                  minSdkStripped.value())) {
+                // Let's create a new Style for this versioned resource.
+                ConfigDescription newConfig(configValue->config);
+                newConfig.sdkVersion = minSdkStripped.value();
+
+                std::unique_ptr<Style> newStyle(
+                    style->clone(&table->stringPool));
+                newStyle->setComment(style->getComment());
+                newStyle->setSource(style->getSource());
+
+                // Move the previously stripped attributes into this style.
+                newStyle->entries.insert(
+                    newStyle->entries.end(),
+                    std::make_move_iterator(stripped.begin()),
+                    std::make_move_iterator(stripped.end()));
+
+                // Insert the new Resource into the correct place.
+                entry->findOrCreateValue(newConfig, {})->value =
+                    std::move(newStyle);
+              }
+            }
+          }
         }
+      }
     }
-    return true;
+  }
+  return true;
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/AutoVersioner_test.cpp b/tools/aapt2/link/AutoVersioner_test.cpp
index 3a61da5..04bf9cd 100644
--- a/tools/aapt2/link/AutoVersioner_test.cpp
+++ b/tools/aapt2/link/AutoVersioner_test.cpp
@@ -21,102 +21,114 @@
 namespace aapt {
 
 TEST(AutoVersionerTest, GenerateVersionedResources) {
-    const ConfigDescription defaultConfig = {};
-    const ConfigDescription landConfig = test::parseConfigOrDie("land");
-    const ConfigDescription sw600dpLandConfig = test::parseConfigOrDie("sw600dp-land");
+  const ConfigDescription defaultConfig = {};
+  const ConfigDescription landConfig = test::parseConfigOrDie("land");
+  const ConfigDescription sw600dpLandConfig =
+      test::parseConfigOrDie("sw600dp-land");
 
-    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, ""));
+  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, ""));
 
-    EXPECT_TRUE(shouldGenerateVersionedResource(&entry, defaultConfig, 17));
-    EXPECT_TRUE(shouldGenerateVersionedResource(&entry, landConfig, 17));
+  EXPECT_TRUE(shouldGenerateVersionedResource(&entry, defaultConfig, 17));
+  EXPECT_TRUE(shouldGenerateVersionedResource(&entry, landConfig, 17));
 }
 
 TEST(AutoVersionerTest, GenerateVersionedResourceWhenHigherVersionExists) {
-    const ConfigDescription defaultConfig = {};
-    const ConfigDescription sw600dpV13Config = test::parseConfigOrDie("sw600dp-v13");
-    const ConfigDescription v21Config = test::parseConfigOrDie("v21");
+  const ConfigDescription defaultConfig = {};
+  const ConfigDescription sw600dpV13Config =
+      test::parseConfigOrDie("sw600dp-v13");
+  const ConfigDescription v21Config = test::parseConfigOrDie("v21");
 
-    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, ""));
+  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, ""));
 
-    EXPECT_TRUE(shouldGenerateVersionedResource(&entry, defaultConfig, 17));
-    EXPECT_FALSE(shouldGenerateVersionedResource(&entry, defaultConfig, 22));
+  EXPECT_TRUE(shouldGenerateVersionedResource(&entry, defaultConfig, 17));
+  EXPECT_FALSE(shouldGenerateVersionedResource(&entry, defaultConfig, 22));
 }
 
 TEST(AutoVersionerTest, VersionStylesForTable) {
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId("app", 0x7f)
-            .addValue("app:style/Foo", test::parseConfigOrDie("v4"), ResourceId(0x7f020000),
-                      test::StyleBuilder()
-                            .addItem("android:attr/onClick", ResourceId(0x0101026f),
-                                     util::make_unique<Id>())
-                            .addItem("android:attr/paddingStart", ResourceId(0x010103b3),
-                                     util::make_unique<Id>())
-                            .addItem("android:attr/requiresSmallestWidthDp",
-                                     ResourceId(0x01010364), util::make_unique<Id>())
-                            .addItem("android:attr/colorAccent", ResourceId(0x01010435),
-                                     util::make_unique<Id>())
-                            .build())
-            .addValue("app:style/Foo", test::parseConfigOrDie("v21"), ResourceId(0x7f020000),
-                      test::StyleBuilder()
-                            .addItem("android:attr/paddingEnd", ResourceId(0x010103b4),
-                                     util::make_unique<Id>())
-                            .build())
-            .build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .setPackageId("app", 0x7f)
+          .addValue(
+              "app:style/Foo", test::parseConfigOrDie("v4"),
+              ResourceId(0x7f020000),
+              test::StyleBuilder()
+                  .addItem("android:attr/onClick", ResourceId(0x0101026f),
+                           util::make_unique<Id>())
+                  .addItem("android:attr/paddingStart", ResourceId(0x010103b3),
+                           util::make_unique<Id>())
+                  .addItem("android:attr/requiresSmallestWidthDp",
+                           ResourceId(0x01010364), util::make_unique<Id>())
+                  .addItem("android:attr/colorAccent", ResourceId(0x01010435),
+                           util::make_unique<Id>())
+                  .build())
+          .addValue(
+              "app:style/Foo", test::parseConfigOrDie("v21"),
+              ResourceId(0x7f020000),
+              test::StyleBuilder()
+                  .addItem("android:attr/paddingEnd", ResourceId(0x010103b4),
+                           util::make_unique<Id>())
+                  .build())
+          .build();
 
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage("app")
-            .setPackageId(0x7f)
-            .build();
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder()
+                                              .setCompilationPackage("app")
+                                              .setPackageId(0x7f)
+                                              .build();
 
-    AutoVersioner versioner;
-    ASSERT_TRUE(versioner.consume(context.get(), table.get()));
+  AutoVersioner versioner;
+  ASSERT_TRUE(versioner.consume(context.get(), table.get()));
 
-    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("android:attr/onClick"));
+  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("android:attr/onClick"));
 
-    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("android:attr/onClick"));
-    AAPT_ASSERT_TRUE(style->entries[1].key.name);
-    EXPECT_EQ(style->entries[1].key.name.value(),
-                  test::parseNameOrDie("android:attr/requiresSmallestWidthDp"));
+  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("android:attr/onClick"));
+  AAPT_ASSERT_TRUE(style->entries[1].key.name);
+  EXPECT_EQ(style->entries[1].key.name.value(),
+            test::parseNameOrDie("android:attr/requiresSmallestWidthDp"));
 
-    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("android:attr/onClick"));
-    AAPT_ASSERT_TRUE(style->entries[1].key.name);
-    EXPECT_EQ(style->entries[1].key.name.value(),
-                  test::parseNameOrDie("android:attr/requiresSmallestWidthDp"));
-    AAPT_ASSERT_TRUE(style->entries[2].key.name);
-    EXPECT_EQ(style->entries[2].key.name.value(),
-                  test::parseNameOrDie("android:attr/paddingStart"));
+  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("android:attr/onClick"));
+  AAPT_ASSERT_TRUE(style->entries[1].key.name);
+  EXPECT_EQ(style->entries[1].key.name.value(),
+            test::parseNameOrDie("android:attr/requiresSmallestWidthDp"));
+  AAPT_ASSERT_TRUE(style->entries[2].key.name);
+  EXPECT_EQ(style->entries[2].key.name.value(),
+            test::parseNameOrDie("android:attr/paddingStart"));
 
-    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("android:attr/paddingEnd"));
+  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("android:attr/paddingEnd"));
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/Link.cpp b/tools/aapt2/link/Link.cpp
index b6b4b473..a42d868 100644
--- a/tools/aapt2/link/Link.cpp
+++ b/tools/aapt2/link/Link.cpp
@@ -31,9 +31,9 @@
 #include "java/ManifestClassGenerator.h"
 #include "java/ProguardRules.h"
 #include "link/Linkers.h"
+#include "link/ManifestFixer.h"
 #include "link/ProductFilter.h"
 #include "link/ReferenceLinker.h"
-#include "link/ManifestFixer.h"
 #include "link/TableMerger.h"
 #include "process/IResourceTableConsumer.h"
 #include "process/SymbolTable.h"
@@ -47,9 +47,9 @@
 #include <android-base/file.h>
 #include <google/protobuf/io/coded_stream.h>
 
+#include <sys/stat.h>
 #include <fstream>
 #include <queue>
-#include <sys/stat.h>
 #include <unordered_map>
 #include <vector>
 
@@ -58,1908 +58,2043 @@
 namespace aapt {
 
 struct LinkOptions {
-    std::string outputPath;
-    std::string manifestPath;
-    std::vector<std::string> includePaths;
-    std::vector<std::string> overlayFiles;
+  std::string outputPath;
+  std::string manifestPath;
+  std::vector<std::string> includePaths;
+  std::vector<std::string> overlayFiles;
 
-    // Java/Proguard options.
-    Maybe<std::string> generateJavaClassPath;
-    Maybe<std::string> customJavaPackage;
-    std::set<std::string> extraJavaPackages;
-    Maybe<std::string> generateProguardRulesPath;
-    Maybe<std::string> generateMainDexProguardRulesPath;
+  // Java/Proguard options.
+  Maybe<std::string> generateJavaClassPath;
+  Maybe<std::string> customJavaPackage;
+  std::set<std::string> extraJavaPackages;
+  Maybe<std::string> generateProguardRulesPath;
+  Maybe<std::string> generateMainDexProguardRulesPath;
 
-    bool noAutoVersion = false;
-    bool noVersionVectors = false;
-    bool noResourceDeduping = false;
-    bool staticLib = false;
-    bool noStaticLibPackages = false;
-    bool generateNonFinalIds = false;
-    std::vector<std::string> javadocAnnotations;
-    bool outputToDirectory = false;
-    bool noXmlNamespaces = false;
-    bool autoAddOverlay = false;
-    bool doNotCompressAnything = false;
-    std::unordered_set<std::string> extensionsToNotCompress;
-    Maybe<std::string> privateSymbols;
-    ManifestFixerOptions manifestFixerOptions;
-    std::unordered_set<std::string> products;
+  bool noAutoVersion = false;
+  bool noVersionVectors = false;
+  bool noResourceDeduping = false;
+  bool staticLib = false;
+  bool noStaticLibPackages = false;
+  bool generateNonFinalIds = false;
+  std::vector<std::string> javadocAnnotations;
+  bool outputToDirectory = false;
+  bool noXmlNamespaces = false;
+  bool autoAddOverlay = false;
+  bool doNotCompressAnything = false;
+  std::unordered_set<std::string> extensionsToNotCompress;
+  Maybe<std::string> privateSymbols;
+  ManifestFixerOptions manifestFixerOptions;
+  std::unordered_set<std::string> products;
 
-    // Split APK options.
-    TableSplitterOptions tableSplitterOptions;
-    std::vector<SplitConstraints> splitConstraints;
-    std::vector<std::string> splitPaths;
+  // Split APK options.
+  TableSplitterOptions tableSplitterOptions;
+  std::vector<SplitConstraints> splitConstraints;
+  std::vector<std::string> splitPaths;
 
-    // Stable ID options.
-    std::unordered_map<ResourceName, ResourceId> stableIdMap;
-    Maybe<std::string> resourceIdMapPath;
+  // Stable ID options.
+  std::unordered_map<ResourceName, ResourceId> stableIdMap;
+  Maybe<std::string> resourceIdMapPath;
 };
 
 class LinkContext : public IAaptContext {
-public:
-    LinkContext() : mNameMangler({}) {
-    }
+ public:
+  LinkContext() : mNameMangler({}) {}
 
-    IDiagnostics* getDiagnostics() override {
-        return &mDiagnostics;
-    }
+  IDiagnostics* getDiagnostics() override { return &mDiagnostics; }
 
-    NameMangler* getNameMangler() override {
-        return &mNameMangler;
-    }
+  NameMangler* getNameMangler() override { return &mNameMangler; }
 
-    void setNameManglerPolicy(const NameManglerPolicy& policy) {
-        mNameMangler = NameMangler(policy);
-    }
+  void setNameManglerPolicy(const NameManglerPolicy& policy) {
+    mNameMangler = NameMangler(policy);
+  }
 
-    const std::string& getCompilationPackage() override {
-        return mCompilationPackage;
-    }
+  const std::string& getCompilationPackage() override {
+    return mCompilationPackage;
+  }
 
-    void setCompilationPackage(const StringPiece& packageName) {
-        mCompilationPackage = packageName.toString();
-    }
+  void setCompilationPackage(const StringPiece& packageName) {
+    mCompilationPackage = packageName.toString();
+  }
 
-    uint8_t getPackageId() override {
-        return mPackageId;
-    }
+  uint8_t getPackageId() override { return mPackageId; }
 
-    void setPackageId(uint8_t id) {
-        mPackageId = id;
-    }
+  void setPackageId(uint8_t id) { mPackageId = id; }
 
-    SymbolTable* getExternalSymbols() override {
-        return &mSymbols;
-    }
+  SymbolTable* getExternalSymbols() override { return &mSymbols; }
 
-    bool verbose() override {
-        return mVerbose;
-    }
+  bool verbose() override { return mVerbose; }
 
-    void setVerbose(bool val) {
-        mVerbose = val;
-    }
+  void setVerbose(bool val) { mVerbose = val; }
 
-    int getMinSdkVersion() override {
-        return mMinSdkVersion;
-    }
+  int getMinSdkVersion() override { return mMinSdkVersion; }
 
-    void setMinSdkVersion(int minSdk) {
-        mMinSdkVersion = minSdk;
-    }
+  void setMinSdkVersion(int minSdk) { mMinSdkVersion = minSdk; }
 
-private:
-    StdErrDiagnostics mDiagnostics;
-    NameMangler mNameMangler;
-    std::string mCompilationPackage;
-    uint8_t mPackageId = 0x0;
-    SymbolTable mSymbols;
-    bool mVerbose = false;
-    int mMinSdkVersion = 0;
+ private:
+  StdErrDiagnostics mDiagnostics;
+  NameMangler mNameMangler;
+  std::string mCompilationPackage;
+  uint8_t mPackageId = 0x0;
+  SymbolTable mSymbols;
+  bool mVerbose = false;
+  int mMinSdkVersion = 0;
 };
 
 static bool copyFileToArchive(io::IFile* file, const std::string& outPath,
-                              uint32_t compressionFlags,
-                              IArchiveWriter* writer, IAaptContext* context) {
-    std::unique_ptr<io::IData> data = file->openAsData();
-    if (!data) {
-        context->getDiagnostics()->error(DiagMessage(file->getSource())
-                                         << "failed to open file");
-        return false;
-    }
-
-    const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data->data());
-    const size_t bufferSize = data->size();
-
-    if (context->verbose()) {
-        context->getDiagnostics()->note(DiagMessage() << "writing " << outPath << " to archive");
-    }
-
-    if (writer->startEntry(outPath, compressionFlags)) {
-        if (writer->writeEntry(buffer, bufferSize)) {
-            if (writer->finishEntry()) {
-                return true;
-            }
-        }
-    }
-
-    context->getDiagnostics()->error(DiagMessage() << "failed to write file " << outPath);
+                              uint32_t compressionFlags, IArchiveWriter* writer,
+                              IAaptContext* context) {
+  std::unique_ptr<io::IData> data = file->openAsData();
+  if (!data) {
+    context->getDiagnostics()->error(DiagMessage(file->getSource())
+                                     << "failed to open file");
     return false;
+  }
+
+  const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data->data());
+  const size_t bufferSize = data->size();
+
+  if (context->verbose()) {
+    context->getDiagnostics()->note(DiagMessage() << "writing " << outPath
+                                                  << " to archive");
+  }
+
+  if (writer->startEntry(outPath, compressionFlags)) {
+    if (writer->writeEntry(buffer, bufferSize)) {
+      if (writer->finishEntry()) {
+        return true;
+      }
+    }
+  }
+
+  context->getDiagnostics()->error(DiagMessage() << "failed to write file "
+                                                 << outPath);
+  return false;
 }
 
-static bool flattenXml(xml::XmlResource* xmlRes, const StringPiece& path, Maybe<size_t> maxSdkLevel,
-                       bool keepRawValues, IArchiveWriter* writer, IAaptContext* context) {
-    BigBuffer buffer(1024);
-    XmlFlattenerOptions options = {};
-    options.keepRawValues = keepRawValues;
-    options.maxSdkLevel = maxSdkLevel;
-    XmlFlattener flattener(&buffer, options);
-    if (!flattener.consume(context, xmlRes)) {
-        return false;
-    }
-
-    if (context->verbose()) {
-        DiagMessage msg;
-        msg << "writing " << path << " to archive";
-        if (maxSdkLevel) {
-            msg << " maxSdkLevel=" << maxSdkLevel.value() << " keepRawValues=" << keepRawValues;
-        }
-        context->getDiagnostics()->note(msg);
-    }
-
-    if (writer->startEntry(path, ArchiveEntry::kCompress)) {
-        if (writer->writeEntry(buffer)) {
-            if (writer->finishEntry()) {
-                return true;
-            }
-        }
-    }
-    context->getDiagnostics()->error(DiagMessage() << "failed to write " << path << " to archive");
+static bool flattenXml(xml::XmlResource* xmlRes, const StringPiece& path,
+                       Maybe<size_t> maxSdkLevel, bool keepRawValues,
+                       IArchiveWriter* writer, IAaptContext* context) {
+  BigBuffer buffer(1024);
+  XmlFlattenerOptions options = {};
+  options.keepRawValues = keepRawValues;
+  options.maxSdkLevel = maxSdkLevel;
+  XmlFlattener flattener(&buffer, options);
+  if (!flattener.consume(context, xmlRes)) {
     return false;
+  }
+
+  if (context->verbose()) {
+    DiagMessage msg;
+    msg << "writing " << path << " to archive";
+    if (maxSdkLevel) {
+      msg << " maxSdkLevel=" << maxSdkLevel.value()
+          << " keepRawValues=" << keepRawValues;
+    }
+    context->getDiagnostics()->note(msg);
+  }
+
+  if (writer->startEntry(path, ArchiveEntry::kCompress)) {
+    if (writer->writeEntry(buffer)) {
+      if (writer->finishEntry()) {
+        return true;
+      }
+    }
+  }
+  context->getDiagnostics()->error(DiagMessage() << "failed to write " << path
+                                                 << " to archive");
+  return false;
 }
 
 static std::unique_ptr<ResourceTable> loadTableFromPb(const Source& source,
-                                                      const void* data, size_t len,
+                                                      const void* data,
+                                                      size_t len,
                                                       IDiagnostics* diag) {
-    pb::ResourceTable pbTable;
-    if (!pbTable.ParseFromArray(data, len)) {
-        diag->error(DiagMessage(source) << "invalid compiled table");
-        return {};
-    }
+  pb::ResourceTable pbTable;
+  if (!pbTable.ParseFromArray(data, len)) {
+    diag->error(DiagMessage(source) << "invalid compiled table");
+    return {};
+  }
 
-    std::unique_ptr<ResourceTable> table = deserializeTableFromPb(pbTable, source, diag);
-    if (!table) {
-        return {};
-    }
-    return table;
+  std::unique_ptr<ResourceTable> table =
+      deserializeTableFromPb(pbTable, source, diag);
+  if (!table) {
+    return {};
+  }
+  return table;
 }
 
 /**
  * Inflates an XML file from the source path.
  */
-static std::unique_ptr<xml::XmlResource> loadXml(const std::string& path, IDiagnostics* diag) {
-    std::ifstream fin(path, std::ifstream::binary);
-    if (!fin) {
-        diag->error(DiagMessage(path) << strerror(errno));
-        return {};
-    }
-    return xml::inflate(&fin, diag, Source(path));
+static std::unique_ptr<xml::XmlResource> loadXml(const std::string& path,
+                                                 IDiagnostics* diag) {
+  std::ifstream fin(path, std::ifstream::binary);
+  if (!fin) {
+    diag->error(DiagMessage(path) << strerror(errno));
+    return {};
+  }
+  return xml::inflate(&fin, diag, Source(path));
 }
 
 struct ResourceFileFlattenerOptions {
-    bool noAutoVersion = false;
-    bool noVersionVectors = false;
-    bool noXmlNamespaces = false;
-    bool keepRawValues = false;
-    bool doNotCompressAnything = false;
-    bool updateProguardSpec = false;
-    std::unordered_set<std::string> extensionsToNotCompress;
+  bool noAutoVersion = false;
+  bool noVersionVectors = false;
+  bool noXmlNamespaces = false;
+  bool keepRawValues = false;
+  bool doNotCompressAnything = false;
+  bool updateProguardSpec = false;
+  std::unordered_set<std::string> extensionsToNotCompress;
 };
 
 class ResourceFileFlattener {
-public:
-    ResourceFileFlattener(const ResourceFileFlattenerOptions& options,
-                          IAaptContext* context, proguard::KeepSet* keepSet) :
-            mOptions(options), mContext(context), mKeepSet(keepSet) {
-    }
+ public:
+  ResourceFileFlattener(const ResourceFileFlattenerOptions& options,
+                        IAaptContext* context, proguard::KeepSet* keepSet)
+      : mOptions(options), mContext(context), mKeepSet(keepSet) {}
 
-    bool flatten(ResourceTable* table, IArchiveWriter* archiveWriter);
+  bool flatten(ResourceTable* table, IArchiveWriter* archiveWriter);
 
-private:
-    struct FileOperation {
-        ConfigDescription config;
+ private:
+  struct FileOperation {
+    ConfigDescription config;
 
-        // The entry this file came from.
-        const ResourceEntry* entry;
+    // The entry this file came from.
+    const ResourceEntry* entry;
 
-        // The file to copy as-is.
-        io::IFile* fileToCopy;
+    // The file to copy as-is.
+    io::IFile* fileToCopy;
 
-        // The XML to process and flatten.
-        std::unique_ptr<xml::XmlResource> xmlToFlatten;
+    // The XML to process and flatten.
+    std::unique_ptr<xml::XmlResource> xmlToFlatten;
 
-        // The destination to write this file to.
-        std::string dstPath;
-        bool skipVersion = false;
-    };
+    // The destination to write this file to.
+    std::string dstPath;
+    bool skipVersion = false;
+  };
 
-    uint32_t getCompressionFlags(const StringPiece& str);
+  uint32_t getCompressionFlags(const StringPiece& str);
 
-    bool linkAndVersionXmlFile(ResourceTable* table, FileOperation* fileOp,
-                               std::queue<FileOperation>* outFileOpQueue);
+  bool linkAndVersionXmlFile(ResourceTable* table, FileOperation* fileOp,
+                             std::queue<FileOperation>* outFileOpQueue);
 
-    ResourceFileFlattenerOptions mOptions;
-    IAaptContext* mContext;
-    proguard::KeepSet* mKeepSet;
+  ResourceFileFlattenerOptions mOptions;
+  IAaptContext* mContext;
+  proguard::KeepSet* mKeepSet;
 };
 
 uint32_t ResourceFileFlattener::getCompressionFlags(const StringPiece& str) {
-    if (mOptions.doNotCompressAnything) {
-        return 0;
-    }
+  if (mOptions.doNotCompressAnything) {
+    return 0;
+  }
 
-    for (const std::string& extension : mOptions.extensionsToNotCompress) {
-        if (util::stringEndsWith(str, extension)) {
-            return 0;
-        }
+  for (const std::string& extension : mOptions.extensionsToNotCompress) {
+    if (util::stringEndsWith(str, extension)) {
+      return 0;
     }
-    return ArchiveEntry::kCompress;
+  }
+  return ArchiveEntry::kCompress;
 }
 
-bool ResourceFileFlattener::linkAndVersionXmlFile(ResourceTable* table,
-                                                  FileOperation* fileOp,
-                                                  std::queue<FileOperation>* outFileOpQueue) {
-    xml::XmlResource* doc = fileOp->xmlToFlatten.get();
-    const Source& src = doc->file.source;
+bool ResourceFileFlattener::linkAndVersionXmlFile(
+    ResourceTable* table, FileOperation* fileOp,
+    std::queue<FileOperation>* outFileOpQueue) {
+  xml::XmlResource* doc = fileOp->xmlToFlatten.get();
+  const Source& src = doc->file.source;
 
-    if (mContext->verbose()) {
-        mContext->getDiagnostics()->note(DiagMessage() << "linking " << src.path);
+  if (mContext->verbose()) {
+    mContext->getDiagnostics()->note(DiagMessage() << "linking " << src.path);
+  }
+
+  XmlReferenceLinker xmlLinker;
+  if (!xmlLinker.consume(mContext, doc)) {
+    return false;
+  }
+
+  if (mOptions.updateProguardSpec &&
+      !proguard::collectProguardRules(src, doc, mKeepSet)) {
+    return false;
+  }
+
+  if (mOptions.noXmlNamespaces) {
+    XmlNamespaceRemover namespaceRemover;
+    if (!namespaceRemover.consume(mContext, doc)) {
+      return false;
     }
+  }
 
-    XmlReferenceLinker xmlLinker;
-    if (!xmlLinker.consume(mContext, doc)) {
-        return false;
-    }
-
-    if (mOptions.updateProguardSpec && !proguard::collectProguardRules(src, doc, mKeepSet)) {
-        return false;
-    }
-
-    if (mOptions.noXmlNamespaces) {
-        XmlNamespaceRemover namespaceRemover;
-        if (!namespaceRemover.consume(mContext, doc)) {
-            return false;
+  if (!mOptions.noAutoVersion) {
+    if (mOptions.noVersionVectors) {
+      // Skip this if it is a vector or animated-vector.
+      xml::Element* el = xml::findRootElement(doc);
+      if (el && el->namespaceUri.empty()) {
+        if (el->name == "vector" || el->name == "animated-vector") {
+          // We are NOT going to version this file.
+          fileOp->skipVersion = true;
+          return true;
         }
+      }
     }
 
-    if (!mOptions.noAutoVersion) {
-        if (mOptions.noVersionVectors) {
-            // Skip this if it is a vector or animated-vector.
-            xml::Element* el = xml::findRootElement(doc);
-            if (el && el->namespaceUri.empty()) {
-                if (el->name == "vector" || el->name == "animated-vector") {
-                    // We are NOT going to version this file.
-                    fileOp->skipVersion = true;
-                    return true;
-                }
-            }
+    const ConfigDescription& config = fileOp->config;
+
+    // Find the first SDK level used that is higher than this defined config and
+    // not superseded by a lower or equal SDK level resource.
+    const int minSdkVersion = mContext->getMinSdkVersion();
+    for (int sdkLevel : xmlLinker.getSdkLevels()) {
+      if (sdkLevel > minSdkVersion && sdkLevel > config.sdkVersion) {
+        if (!shouldGenerateVersionedResource(fileOp->entry, config, sdkLevel)) {
+          // If we shouldn't generate a versioned resource, stop checking.
+          break;
         }
 
-        const ConfigDescription& config = fileOp->config;
+        ResourceFile versionedFileDesc = doc->file;
+        versionedFileDesc.config.sdkVersion = (uint16_t)sdkLevel;
 
-        // Find the first SDK level used that is higher than this defined config and
-        // not superseded by a lower or equal SDK level resource.
-        const int minSdkVersion = mContext->getMinSdkVersion();
-        for (int sdkLevel : xmlLinker.getSdkLevels()) {
-            if (sdkLevel > minSdkVersion && sdkLevel > config.sdkVersion) {
-                if (!shouldGenerateVersionedResource(fileOp->entry, config, sdkLevel)) {
-                    // If we shouldn't generate a versioned resource, stop checking.
-                    break;
-                }
+        FileOperation newFileOp;
+        newFileOp.xmlToFlatten = util::make_unique<xml::XmlResource>(
+            versionedFileDesc, doc->root->clone());
+        newFileOp.config = versionedFileDesc.config;
+        newFileOp.entry = fileOp->entry;
+        newFileOp.dstPath = ResourceUtils::buildResourceFileName(
+            versionedFileDesc, mContext->getNameMangler());
 
-                ResourceFile versionedFileDesc = doc->file;
-                versionedFileDesc.config.sdkVersion = (uint16_t) sdkLevel;
-
-                FileOperation newFileOp;
-                newFileOp.xmlToFlatten = util::make_unique<xml::XmlResource>(
-                        versionedFileDesc, doc->root->clone());
-                newFileOp.config = versionedFileDesc.config;
-                newFileOp.entry = fileOp->entry;
-                newFileOp.dstPath = ResourceUtils::buildResourceFileName(
-                        versionedFileDesc, mContext->getNameMangler());
-
-                if (mContext->verbose()) {
-                    mContext->getDiagnostics()->note(DiagMessage(versionedFileDesc.source)
-                                                     << "auto-versioning resource from config '"
-                                                     << config
-                                                     << "' -> '"
-                                                     << versionedFileDesc.config << "'");
-                }
-
-                bool added = table->addFileReferenceAllowMangled(versionedFileDesc.name,
-                                                                 versionedFileDesc.config,
-                                                                 versionedFileDesc.source,
-                                                                 newFileOp.dstPath,
-                                                                 nullptr,
-                                                                 mContext->getDiagnostics());
-                if (!added) {
-                    return false;
-                }
-
-                outFileOpQueue->push(std::move(newFileOp));
-                break;
-            }
+        if (mContext->verbose()) {
+          mContext->getDiagnostics()->note(
+              DiagMessage(versionedFileDesc.source)
+              << "auto-versioning resource from config '" << config << "' -> '"
+              << versionedFileDesc.config << "'");
         }
+
+        bool added = table->addFileReferenceAllowMangled(
+            versionedFileDesc.name, versionedFileDesc.config,
+            versionedFileDesc.source, newFileOp.dstPath, nullptr,
+            mContext->getDiagnostics());
+        if (!added) {
+          return false;
+        }
+
+        outFileOpQueue->push(std::move(newFileOp));
+        break;
+      }
     }
-    return true;
+  }
+  return true;
 }
 
 /**
- * Do not insert or remove any resources while executing in this function. It will
+ * Do not insert or remove any resources while executing in this function. It
+ * will
  * corrupt the iteration order.
  */
-bool ResourceFileFlattener::flatten(ResourceTable* table, IArchiveWriter* archiveWriter) {
-    bool error = false;
-    std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> configSortedFiles;
+bool ResourceFileFlattener::flatten(ResourceTable* table,
+                                    IArchiveWriter* archiveWriter) {
+  bool error = false;
+  std::map<std::pair<ConfigDescription, StringPiece>, FileOperation>
+      configSortedFiles;
 
-    for (auto& pkg : table->packages) {
-        for (auto& type : pkg->types) {
-            // Sort by config and name, so that we get better locality in the zip file.
-            configSortedFiles.clear();
-            std::queue<FileOperation> fileOperations;
+  for (auto& pkg : table->packages) {
+    for (auto& type : pkg->types) {
+      // Sort by config and name, so that we get better locality in the zip
+      // file.
+      configSortedFiles.clear();
+      std::queue<FileOperation> fileOperations;
 
-            // Populate the queue with all files in the ResourceTable.
-            for (auto& entry : type->entries) {
-                for (auto& configValue : entry->values) {
-                    FileReference* fileRef = valueCast<FileReference>(configValue->value.get());
-                    if (!fileRef) {
-                        continue;
-                    }
-
-                    io::IFile* file = fileRef->file;
-                    if (!file) {
-                        mContext->getDiagnostics()->error(DiagMessage(fileRef->getSource())
-                                                          << "file not found");
-                        return false;
-                    }
-
-                    FileOperation fileOp;
-                    fileOp.entry = entry.get();
-                    fileOp.dstPath = *fileRef->path;
-                    fileOp.config = configValue->config;
-
-                    const StringPiece srcPath = file->getSource().path;
-                    if (type->type != ResourceType::kRaw &&
-                            (util::stringEndsWith(srcPath, ".xml.flat") ||
-                            util::stringEndsWith(srcPath, ".xml"))) {
-                        std::unique_ptr<io::IData> data = file->openAsData();
-                        if (!data) {
-                            mContext->getDiagnostics()->error(DiagMessage(file->getSource())
-                                                              << "failed to open file");
-                            return false;
-                        }
-
-                        fileOp.xmlToFlatten = xml::inflate(data->data(), data->size(),
-                                                           mContext->getDiagnostics(),
-                                                           file->getSource());
-
-                        if (!fileOp.xmlToFlatten) {
-                            return false;
-                        }
-
-                        fileOp.xmlToFlatten->file.config = configValue->config;
-                        fileOp.xmlToFlatten->file.source = fileRef->getSource();
-                        fileOp.xmlToFlatten->file.name =
-                                ResourceName(pkg->name, type->type, entry->name);
-
-                        // Enqueue the XML files to be processed.
-                        fileOperations.push(std::move(fileOp));
-                    } else {
-                        fileOp.fileToCopy = file;
-
-                        // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else
-                        // we end up copying the string in the std::make_pair() method, then
-                        // creating a StringPiece from the copy, which would cause us to end up
-                        // referencing garbage in the map.
-                        const StringPiece entryName(entry->name);
-                        configSortedFiles[std::make_pair(configValue->config, entryName)] =
-                                std::move(fileOp);
-                    }
-                }
-            }
-
-            // Now process the XML queue
-            for (; !fileOperations.empty(); fileOperations.pop()) {
-                FileOperation& fileOp = fileOperations.front();
-
-                if (!linkAndVersionXmlFile(table, &fileOp, &fileOperations)) {
-                    error = true;
-                    continue;
-                }
-
-                // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else
-                // we end up copying the string in the std::make_pair() method, then creating
-                // a StringPiece from the copy, which would cause us to end up referencing
-                // garbage in the map.
-                const StringPiece entryName(fileOp.entry->name);
-                configSortedFiles[std::make_pair(fileOp.config, entryName)] = std::move(fileOp);
-            }
-
-            if (error) {
-                return false;
-            }
-
-            // Now flatten the sorted values.
-            for (auto& mapEntry : configSortedFiles) {
-                const ConfigDescription& config = mapEntry.first.first;
-                const FileOperation& fileOp = mapEntry.second;
-
-                if (fileOp.xmlToFlatten) {
-                    Maybe<size_t> maxSdkLevel;
-                    if (!mOptions.noAutoVersion && !fileOp.skipVersion) {
-                        maxSdkLevel = std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u),
-                                                       mContext->getMinSdkVersion());
-                    }
-
-                    bool result = flattenXml(fileOp.xmlToFlatten.get(), fileOp.dstPath, maxSdkLevel,
-                                             mOptions.keepRawValues,
-                                             archiveWriter, mContext);
-                    if (!result) {
-                        error = true;
-                    }
-                } else {
-                    bool result = copyFileToArchive(fileOp.fileToCopy, fileOp.dstPath,
-                                                    getCompressionFlags(fileOp.dstPath),
-                                                    archiveWriter, mContext);
-                    if (!result) {
-                        error = true;
-                    }
-                }
-            }
-        }
-    }
-    return !error;
-}
-
-static bool writeStableIdMapToPath(IDiagnostics* diag,
-                                   const std::unordered_map<ResourceName, ResourceId>& idMap,
-                                   const std::string& idMapPath) {
-    std::ofstream fout(idMapPath, std::ofstream::binary);
-    if (!fout) {
-        diag->error(DiagMessage(idMapPath) << strerror(errno));
-        return false;
-    }
-
-    for (const auto& entry : idMap) {
-        const ResourceName& name = entry.first;
-        const ResourceId& id = entry.second;
-        fout << name << " = " << id << "\n";
-    }
-
-    if (!fout) {
-        diag->error(DiagMessage(idMapPath) << "failed writing to file: " << strerror(errno));
-        return false;
-    }
-
-    return true;
-}
-
-static bool loadStableIdMap(IDiagnostics* diag, const std::string& path,
-                            std::unordered_map<ResourceName, ResourceId>* outIdMap) {
-    std::string content;
-    if (!android::base::ReadFileToString(path, &content)) {
-        diag->error(DiagMessage(path) << "failed reading stable ID file");
-        return false;
-    }
-
-    outIdMap->clear();
-    size_t lineNo = 0;
-    for (StringPiece line : util::tokenize(content, '\n')) {
-        lineNo++;
-        line = util::trimWhitespace(line);
-        if (line.empty()) {
+      // Populate the queue with all files in the ResourceTable.
+      for (auto& entry : type->entries) {
+        for (auto& configValue : entry->values) {
+          FileReference* fileRef =
+              valueCast<FileReference>(configValue->value.get());
+          if (!fileRef) {
             continue;
-        }
+          }
 
-        auto iter = std::find(line.begin(), line.end(), '=');
-        if (iter == line.end()) {
-            diag->error(DiagMessage(Source(path, lineNo)) << "missing '='");
+          io::IFile* file = fileRef->file;
+          if (!file) {
+            mContext->getDiagnostics()->error(DiagMessage(fileRef->getSource())
+                                              << "file not found");
             return false;
+          }
+
+          FileOperation fileOp;
+          fileOp.entry = entry.get();
+          fileOp.dstPath = *fileRef->path;
+          fileOp.config = configValue->config;
+
+          const StringPiece srcPath = file->getSource().path;
+          if (type->type != ResourceType::kRaw &&
+              (util::stringEndsWith(srcPath, ".xml.flat") ||
+               util::stringEndsWith(srcPath, ".xml"))) {
+            std::unique_ptr<io::IData> data = file->openAsData();
+            if (!data) {
+              mContext->getDiagnostics()->error(DiagMessage(file->getSource())
+                                                << "failed to open file");
+              return false;
+            }
+
+            fileOp.xmlToFlatten =
+                xml::inflate(data->data(), data->size(),
+                             mContext->getDiagnostics(), file->getSource());
+
+            if (!fileOp.xmlToFlatten) {
+              return false;
+            }
+
+            fileOp.xmlToFlatten->file.config = configValue->config;
+            fileOp.xmlToFlatten->file.source = fileRef->getSource();
+            fileOp.xmlToFlatten->file.name =
+                ResourceName(pkg->name, type->type, entry->name);
+
+            // Enqueue the XML files to be processed.
+            fileOperations.push(std::move(fileOp));
+          } else {
+            fileOp.fileToCopy = file;
+
+            // NOTE(adamlesinski): Explicitly construct a StringPiece here, or
+            // else
+            // we end up copying the string in the std::make_pair() method, then
+            // creating a StringPiece from the copy, which would cause us to end
+            // up
+            // referencing garbage in the map.
+            const StringPiece entryName(entry->name);
+            configSortedFiles[std::make_pair(configValue->config, entryName)] =
+                std::move(fileOp);
+          }
+        }
+      }
+
+      // Now process the XML queue
+      for (; !fileOperations.empty(); fileOperations.pop()) {
+        FileOperation& fileOp = fileOperations.front();
+
+        if (!linkAndVersionXmlFile(table, &fileOp, &fileOperations)) {
+          error = true;
+          continue;
         }
 
-        ResourceNameRef name;
-        StringPiece resNameStr = util::trimWhitespace(
-                line.substr(0, std::distance(line.begin(), iter)));
-        if (!ResourceUtils::parseResourceName(resNameStr, &name)) {
-            diag->error(DiagMessage(Source(path, lineNo))
-                        << "invalid resource name '" << resNameStr << "'");
-            return false;
+        // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else
+        // we end up copying the string in the std::make_pair() method, then
+        // creating
+        // a StringPiece from the copy, which would cause us to end up
+        // referencing
+        // garbage in the map.
+        const StringPiece entryName(fileOp.entry->name);
+        configSortedFiles[std::make_pair(fileOp.config, entryName)] =
+            std::move(fileOp);
+      }
+
+      if (error) {
+        return false;
+      }
+
+      // Now flatten the sorted values.
+      for (auto& mapEntry : configSortedFiles) {
+        const ConfigDescription& config = mapEntry.first.first;
+        const FileOperation& fileOp = mapEntry.second;
+
+        if (fileOp.xmlToFlatten) {
+          Maybe<size_t> maxSdkLevel;
+          if (!mOptions.noAutoVersion && !fileOp.skipVersion) {
+            maxSdkLevel =
+                std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u),
+                                 mContext->getMinSdkVersion());
+          }
+
+          bool result =
+              flattenXml(fileOp.xmlToFlatten.get(), fileOp.dstPath, maxSdkLevel,
+                         mOptions.keepRawValues, archiveWriter, mContext);
+          if (!result) {
+            error = true;
+          }
+        } else {
+          bool result = copyFileToArchive(fileOp.fileToCopy, fileOp.dstPath,
+                                          getCompressionFlags(fileOp.dstPath),
+                                          archiveWriter, mContext);
+          if (!result) {
+            error = true;
+          }
         }
-
-        const size_t resIdStartIdx = std::distance(line.begin(), iter) + 1;
-        const size_t resIdStrLen = line.size() - resIdStartIdx;
-        StringPiece resIdStr = util::trimWhitespace(line.substr(resIdStartIdx, resIdStrLen));
-
-        Maybe<ResourceId> maybeId = ResourceUtils::parseResourceId(resIdStr);
-        if (!maybeId) {
-            diag->error(DiagMessage(Source(path, lineNo)) << "invalid resource ID '"
-                        << resIdStr << "'");
-            return false;
-        }
-
-        (*outIdMap)[name.toResourceName()] = maybeId.value();
+      }
     }
-    return true;
+  }
+  return !error;
+}
+
+static bool writeStableIdMapToPath(
+    IDiagnostics* diag,
+    const std::unordered_map<ResourceName, ResourceId>& idMap,
+    const std::string& idMapPath) {
+  std::ofstream fout(idMapPath, std::ofstream::binary);
+  if (!fout) {
+    diag->error(DiagMessage(idMapPath) << strerror(errno));
+    return false;
+  }
+
+  for (const auto& entry : idMap) {
+    const ResourceName& name = entry.first;
+    const ResourceId& id = entry.second;
+    fout << name << " = " << id << "\n";
+  }
+
+  if (!fout) {
+    diag->error(DiagMessage(idMapPath) << "failed writing to file: "
+                                       << strerror(errno));
+    return false;
+  }
+
+  return true;
+}
+
+static bool loadStableIdMap(
+    IDiagnostics* diag, const std::string& path,
+    std::unordered_map<ResourceName, ResourceId>* outIdMap) {
+  std::string content;
+  if (!android::base::ReadFileToString(path, &content)) {
+    diag->error(DiagMessage(path) << "failed reading stable ID file");
+    return false;
+  }
+
+  outIdMap->clear();
+  size_t lineNo = 0;
+  for (StringPiece line : util::tokenize(content, '\n')) {
+    lineNo++;
+    line = util::trimWhitespace(line);
+    if (line.empty()) {
+      continue;
+    }
+
+    auto iter = std::find(line.begin(), line.end(), '=');
+    if (iter == line.end()) {
+      diag->error(DiagMessage(Source(path, lineNo)) << "missing '='");
+      return false;
+    }
+
+    ResourceNameRef name;
+    StringPiece resNameStr =
+        util::trimWhitespace(line.substr(0, std::distance(line.begin(), iter)));
+    if (!ResourceUtils::parseResourceName(resNameStr, &name)) {
+      diag->error(DiagMessage(Source(path, lineNo)) << "invalid resource name '"
+                                                    << resNameStr << "'");
+      return false;
+    }
+
+    const size_t resIdStartIdx = std::distance(line.begin(), iter) + 1;
+    const size_t resIdStrLen = line.size() - resIdStartIdx;
+    StringPiece resIdStr =
+        util::trimWhitespace(line.substr(resIdStartIdx, resIdStrLen));
+
+    Maybe<ResourceId> maybeId = ResourceUtils::parseResourceId(resIdStr);
+    if (!maybeId) {
+      diag->error(DiagMessage(Source(path, lineNo)) << "invalid resource ID '"
+                                                    << resIdStr << "'");
+      return false;
+    }
+
+    (*outIdMap)[name.toResourceName()] = maybeId.value();
+  }
+  return true;
 }
 
 static bool parseSplitParameter(const StringPiece& arg, IDiagnostics* diag,
-                                std::string* outPath, SplitConstraints* outSplit) {
-    std::vector<std::string> parts = util::split(arg, ':');
-    if (parts.size() != 2) {
-        diag->error(DiagMessage() << "invalid split parameter '" << arg << "'");
-        diag->note(DiagMessage() << "should be --split path/to/output.apk:<config>[,<config>...]");
-        return false;
+                                std::string* outPath,
+                                SplitConstraints* outSplit) {
+  std::vector<std::string> parts = util::split(arg, ':');
+  if (parts.size() != 2) {
+    diag->error(DiagMessage() << "invalid split parameter '" << arg << "'");
+    diag->note(
+        DiagMessage()
+        << "should be --split path/to/output.apk:<config>[,<config>...]");
+    return false;
+  }
+  *outPath = parts[0];
+  std::vector<ConfigDescription> configs;
+  for (const StringPiece& configStr : util::tokenize(parts[1], ',')) {
+    configs.push_back({});
+    if (!ConfigDescription::parse(configStr, &configs.back())) {
+      diag->error(DiagMessage() << "invalid config '" << configStr
+                                << "' in split parameter '" << arg << "'");
+      return false;
     }
-    *outPath = parts[0];
-    std::vector<ConfigDescription> configs;
-    for (const StringPiece& configStr : util::tokenize(parts[1], ',')) {
-        configs.push_back({});
-        if (!ConfigDescription::parse(configStr, &configs.back())) {
-            diag->error(DiagMessage() << "invalid config '" << configStr
-                        << "' in split parameter '" << arg << "'");
-            return false;
-        }
-    }
-    outSplit->configs.insert(configs.begin(), configs.end());
-    return true;
+  }
+  outSplit->configs.insert(configs.begin(), configs.end());
+  return true;
 }
 
 class LinkCommand {
-public:
-    LinkCommand(LinkContext* context, const LinkOptions& options) :
-            mOptions(options), mContext(context), mFinalTable(),
-            mFileCollection(util::make_unique<io::FileCollection>()) {
-    }
+ public:
+  LinkCommand(LinkContext* context, const LinkOptions& options)
+      : mOptions(options),
+        mContext(context),
+        mFinalTable(),
+        mFileCollection(util::make_unique<io::FileCollection>()) {}
 
-    /**
-     * Creates a SymbolTable that loads symbols from the various APKs and caches the
-     * results for faster lookup.
-     */
-    bool loadSymbolsFromIncludePaths() {
-        std::unique_ptr<AssetManagerSymbolSource> assetSource =
-                util::make_unique<AssetManagerSymbolSource>();
-        for (const std::string& path : mOptions.includePaths) {
-            if (mContext->verbose()) {
-                mContext->getDiagnostics()->note(DiagMessage(path) << "loading include path");
-            }
+  /**
+   * Creates a SymbolTable that loads symbols from the various APKs and caches
+   * the
+   * results for faster lookup.
+   */
+  bool loadSymbolsFromIncludePaths() {
+    std::unique_ptr<AssetManagerSymbolSource> assetSource =
+        util::make_unique<AssetManagerSymbolSource>();
+    for (const std::string& path : mOptions.includePaths) {
+      if (mContext->verbose()) {
+        mContext->getDiagnostics()->note(DiagMessage(path)
+                                         << "loading include path");
+      }
 
-            // First try to load the file as a static lib.
-            std::string errorStr;
-            std::unique_ptr<ResourceTable> staticInclude = loadStaticLibrary(path, &errorStr);
-            if (staticInclude) {
-                if (!mOptions.staticLib) {
-                    // Can't include static libraries when not building a static library.
-                    mContext->getDiagnostics()->error(
-                            DiagMessage(path) << "can't include static library when building app");
-                    return false;
-                }
-
-                // If we are using --no-static-lib-packages, we need to rename the package of this
-                // table to our compilation package.
-                if (mOptions.noStaticLibPackages) {
-                    if (ResourceTablePackage* pkg = staticInclude->findPackageById(0x7f)) {
-                        pkg->name = mContext->getCompilationPackage();
-                    }
-                }
-
-                mContext->getExternalSymbols()->appendSource(
-                        util::make_unique<ResourceTableSymbolSource>(staticInclude.get()));
-
-                mStaticTableIncludes.push_back(std::move(staticInclude));
-
-            } else if (!errorStr.empty()) {
-                // We had an error with reading, so fail.
-                mContext->getDiagnostics()->error(DiagMessage(path) << errorStr);
-                return false;
-            }
-
-            if (!assetSource->addAssetPath(path)) {
-                mContext->getDiagnostics()->error(
-                        DiagMessage(path) << "failed to load include path");
-                return false;
-            }
-        }
-
-        mContext->getExternalSymbols()->appendSource(std::move(assetSource));
-        return true;
-    }
-
-    Maybe<AppInfo> extractAppInfoFromManifest(xml::XmlResource* xmlRes, IDiagnostics* diag) {
-        // Make sure the first element is <manifest> with package attribute.
-        if (xml::Element* manifestEl = xml::findRootElement(xmlRes->root.get())) {
-            AppInfo appInfo;
-
-            if (!manifestEl->namespaceUri.empty() || manifestEl->name != "manifest") {
-                diag->error(DiagMessage(xmlRes->file.source) << "root tag must be <manifest>");
-                return {};
-            }
-
-            xml::Attribute* packageAttr = manifestEl->findAttribute({}, "package");
-            if (!packageAttr) {
-                diag->error(DiagMessage(xmlRes->file.source)
-                            << "<manifest> must have a 'package' attribute");
-                return {};
-            }
-
-            appInfo.package = packageAttr->value;
-
-            if (xml::Attribute* versionCodeAttr =
-                    manifestEl->findAttribute(xml::kSchemaAndroid, "versionCode")) {
-                Maybe<uint32_t> maybeCode = ResourceUtils::parseInt(versionCodeAttr->value);
-                if (!maybeCode) {
-                    diag->error(DiagMessage(xmlRes->file.source.withLine(manifestEl->lineNumber))
-                                << "invalid android:versionCode '"
-                                << versionCodeAttr->value << "'");
-                    return {};
-                }
-                appInfo.versionCode = maybeCode.value();
-            }
-
-            if (xml::Attribute* revisionCodeAttr =
-                    manifestEl->findAttribute(xml::kSchemaAndroid, "revisionCode")) {
-                Maybe<uint32_t> maybeCode = ResourceUtils::parseInt(revisionCodeAttr->value);
-                if (!maybeCode) {
-                    diag->error(DiagMessage(xmlRes->file.source.withLine(manifestEl->lineNumber))
-                                << "invalid android:revisionCode '"
-                                << revisionCodeAttr->value << "'");
-                    return {};
-                }
-                appInfo.revisionCode = maybeCode.value();
-            }
-
-            if (xml::Element* usesSdkEl = manifestEl->findChild({}, "uses-sdk")) {
-                if (xml::Attribute* minSdk =
-                        usesSdkEl->findAttribute(xml::kSchemaAndroid, "minSdkVersion")) {
-                    appInfo.minSdkVersion = minSdk->value;
-                }
-            }
-
-            return appInfo;
-        }
-        return {};
-    }
-
-    /**
-     * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it linked.
-     * Postcondition: ResourceTable has only one package left. All others are stripped, or there
-     *                is an error and false is returned.
-     */
-    bool verifyNoExternalPackages() {
-        auto isExtPackageFunc = [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
-            return mContext->getCompilationPackage() != pkg->name ||
-                    !pkg->id ||
-                    pkg->id.value() != mContext->getPackageId();
-        };
-
-        bool error = false;
-        for (const auto& package : mFinalTable.packages) {
-            if (isExtPackageFunc(package)) {
-                // We have a package that is not related to the one we're building!
-                for (const auto& type : package->types) {
-                    for (const auto& entry : type->entries) {
-                        ResourceNameRef resName(package->name, type->type, entry->name);
-
-                        for (const auto& configValue : entry->values) {
-                            // 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 == "android") {
-                                mContext->getDiagnostics()->warn(
-                                        DiagMessage(configValue->value->getSource())
-                                        << "generated id '" << resName
-                                        << "' for external package '" << package->name
-                                        << "'");
-                            } else {
-                                mContext->getDiagnostics()->error(
-                                        DiagMessage(configValue->value->getSource())
-                                        << "defined resource '" << resName
-                                        << "' for external package '" << package->name
-                                        << "'");
-                                error = true;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-
-        auto newEndIter = std::remove_if(mFinalTable.packages.begin(), mFinalTable.packages.end(),
-                                         isExtPackageFunc);
-        mFinalTable.packages.erase(newEndIter, mFinalTable.packages.end());
-        return !error;
-    }
-
-    /**
-     * Returns true if no IDs have been set, false otherwise.
-     */
-    bool verifyNoIdsSet() {
-        for (const auto& package : mFinalTable.packages) {
-            for (const auto& type : package->types) {
-                if (type->id) {
-                    mContext->getDiagnostics()->error(DiagMessage() << "type " << type->type
-                                                      << " has ID " << std::hex
-                                                      << (int) type->id.value()
-                                                      << std::dec << " assigned");
-                    return false;
-                }
-
-                for (const auto& entry : type->entries) {
-                    if (entry->id) {
-                        ResourceNameRef resName(package->name, type->type, entry->name);
-                        mContext->getDiagnostics()->error(DiagMessage() << "entry " << resName
-                                                          << " has ID " << std::hex
-                                                          << (int) entry->id.value()
-                                                          << std::dec << " assigned");
-                        return false;
-                    }
-                }
-            }
-        }
-        return true;
-    }
-
-    std::unique_ptr<IArchiveWriter> makeArchiveWriter(const StringPiece& out) {
-        if (mOptions.outputToDirectory) {
-            return createDirectoryArchiveWriter(mContext->getDiagnostics(), out);
-        } else {
-            return createZipFileArchiveWriter(mContext->getDiagnostics(), out);
-        }
-    }
-
-    bool flattenTable(ResourceTable* table, IArchiveWriter* writer) {
-        BigBuffer buffer(1024);
-        TableFlattener flattener(&buffer);
-        if (!flattener.consume(mContext, table)) {
-            return false;
-        }
-
-        if (writer->startEntry("resources.arsc", ArchiveEntry::kAlign)) {
-            if (writer->writeEntry(buffer)) {
-                if (writer->finishEntry()) {
-                    return true;
-                }
-            }
-        }
-
-        mContext->getDiagnostics()->error(
-                DiagMessage() << "failed to write resources.arsc to archive");
-        return false;
-    }
-
-    bool flattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
-        // Create the file/zip entry.
-        if (!writer->startEntry("resources.arsc.flat", 0)) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed to open");
-            return false;
-        }
-
-        // Make sure CopyingOutputStreamAdaptor is deleted before we call writer->finishEntry().
-        {
-            // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream
-            // interface.
-            CopyingOutputStreamAdaptor adaptor(writer);
-
-            std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table);
-            if (!pbTable->SerializeToZeroCopyStream(&adaptor)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed to write");
-                return false;
-            }
-        }
-
-        if (!writer->finishEntry()) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed to finish entry");
-            return false;
-        }
-        return true;
-    }
-
-    bool writeJavaFile(ResourceTable* table, const StringPiece& packageNameToGenerate,
-                       const StringPiece& outPackage, const JavaClassGeneratorOptions& javaOptions) {
-        if (!mOptions.generateJavaClassPath) {
-            return true;
-        }
-
-        std::string outPath = mOptions.generateJavaClassPath.value();
-        file::appendPath(&outPath, file::packageToPath(outPackage));
-        if (!file::mkdirs(outPath)) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed to create directory '" << outPath << "'");
-            return false;
-        }
-
-        file::appendPath(&outPath, "R.java");
-
-        std::ofstream fout(outPath, std::ofstream::binary);
-        if (!fout) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
-            return false;
-        }
-
-        JavaClassGenerator generator(mContext, table, javaOptions);
-        if (!generator.generate(packageNameToGenerate, outPackage, &fout)) {
-            mContext->getDiagnostics()->error(DiagMessage(outPath) << generator.getError());
-            return false;
-        }
-
-        if (!fout) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
-        }
-        return true;
-    }
-
-    bool writeManifestJavaFile(xml::XmlResource* manifestXml) {
-        if (!mOptions.generateJavaClassPath) {
-            return true;
-        }
-
-        std::unique_ptr<ClassDefinition> manifestClass = generateManifestClass(
-                mContext->getDiagnostics(), manifestXml);
-
-        if (!manifestClass) {
-            // Something bad happened, but we already logged it, so exit.
-            return false;
-        }
-
-        if (manifestClass->empty()) {
-            // Empty Manifest class, no need to generate it.
-            return true;
-        }
-
-        // Add any JavaDoc annotations to the generated class.
-        for (const std::string& annotation : mOptions.javadocAnnotations) {
-            std::string properAnnotation = "@";
-            properAnnotation += annotation;
-            manifestClass->getCommentBuilder()->appendComment(properAnnotation);
-        }
-
-        const std::string& packageUtf8 = mContext->getCompilationPackage();
-
-        std::string outPath = mOptions.generateJavaClassPath.value();
-        file::appendPath(&outPath, file::packageToPath(packageUtf8));
-
-        if (!file::mkdirs(outPath)) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed to create directory '" << outPath << "'");
-            return false;
-        }
-
-        file::appendPath(&outPath, "Manifest.java");
-
-        std::ofstream fout(outPath, std::ofstream::binary);
-        if (!fout) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
-            return false;
-        }
-
-        if (!ClassDefinition::writeJavaFile(manifestClass.get(), packageUtf8, true, &fout)) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
-            return false;
-        }
-        return true;
-    }
-
-    bool writeProguardFile(const Maybe<std::string>& out, const proguard::KeepSet& keepSet) {
-        if (!out) {
-            return true;
-        }
-
-        const std::string& outPath = out.value();
-        std::ofstream fout(outPath, std::ofstream::binary);
-        if (!fout) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed to open '" << outPath << "': " << strerror(errno));
-            return false;
-        }
-
-        proguard::writeKeepSet(&fout, keepSet);
-        if (!fout) {
-            mContext->getDiagnostics()->error(
-                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
-            return false;
-        }
-        return true;
-    }
-
-    std::unique_ptr<ResourceTable> loadStaticLibrary(const std::string& input,
-                                                     std::string* outError) {
-        std::unique_ptr<io::ZipFileCollection> collection = io::ZipFileCollection::create(
-                input, outError);
-        if (!collection) {
-            return {};
-        }
-        return loadTablePbFromCollection(collection.get());
-    }
-
-    std::unique_ptr<ResourceTable> loadTablePbFromCollection(io::IFileCollection* collection) {
-        io::IFile* file = collection->findFile("resources.arsc.flat");
-        if (!file) {
-            return {};
-        }
-
-        std::unique_ptr<io::IData> data = file->openAsData();
-        return loadTableFromPb(file->getSource(), data->data(), data->size(),
-                               mContext->getDiagnostics());
-    }
-
-    bool mergeStaticLibrary(const std::string& input, bool override) {
-        if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(DiagMessage() << "merging static library " << input);
-        }
-
-        std::string errorStr;
-        std::unique_ptr<io::ZipFileCollection> collection =
-                io::ZipFileCollection::create(input, &errorStr);
-        if (!collection) {
-            mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
-            return false;
-        }
-
-        std::unique_ptr<ResourceTable> table = loadTablePbFromCollection(collection.get());
-        if (!table) {
-            mContext->getDiagnostics()->error(DiagMessage(input) << "invalid static library");
-            return false;
-        }
-
-        ResourceTablePackage* pkg = table->findPackageById(0x7f);
-        if (!pkg) {
-            mContext->getDiagnostics()->error(DiagMessage(input)
-                                              << "static library has no package");
-            return false;
-        }
-
-        bool result;
-        if (mOptions.noStaticLibPackages) {
-            // Merge all resources as if they were in the compilation package. This is the old
-            // behaviour of aapt.
-
-            // Add the package to the set of --extra-packages so we emit an R.java for each
-            // library package.
-            if (!pkg->name.empty()) {
-                mOptions.extraJavaPackages.insert(pkg->name);
-            }
-
-            pkg->name = "";
-            if (override) {
-                result = mTableMerger->mergeOverlay(Source(input), table.get(), collection.get());
-            } else {
-                result = mTableMerger->merge(Source(input), table.get(), collection.get());
-            }
-
-        } else {
-            // This is the proper way to merge libraries, where the package name is preserved
-            // and resource names are mangled.
-            result = mTableMerger->mergeAndMangle(Source(input), pkg->name, table.get(),
-                                                  collection.get());
-        }
-
-        if (!result) {
-            return false;
-        }
-
-        // Make sure to move the collection into the set of IFileCollections.
-        mCollections.push_back(std::move(collection));
-        return true;
-    }
-
-    bool mergeResourceTable(io::IFile* file, bool override) {
-        if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(DiagMessage() << "merging resource table "
-                                             << file->getSource());
-        }
-
-        std::unique_ptr<io::IData> data = file->openAsData();
-        if (!data) {
-            mContext->getDiagnostics()->error(DiagMessage(file->getSource())
-                                             << "failed to open file");
-            return false;
-        }
-
-        std::unique_ptr<ResourceTable> table = loadTableFromPb(file->getSource(),
-                                                               data->data(), data->size(),
-                                                               mContext->getDiagnostics());
-        if (!table) {
-            return false;
-        }
-
-        bool result = false;
-        if (override) {
-            result = mTableMerger->mergeOverlay(file->getSource(), table.get());
-        } else {
-            result = mTableMerger->merge(file->getSource(), table.get());
-        }
-        return result;
-    }
-
-    bool mergeCompiledFile(io::IFile* file, ResourceFile* fileDesc, bool override) {
-        if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(DiagMessage()
-                                             << "merging '" << fileDesc->name
-                                             << "' from compiled file "
-                                             << file->getSource());
-        }
-
-        bool result = false;
-        if (override) {
-            result = mTableMerger->mergeFileOverlay(*fileDesc, file);
-        } else {
-            result = mTableMerger->mergeFile(*fileDesc, file);
-        }
-
-        if (!result) {
-            return false;
-        }
-
-        // Add the exports of this file to the table.
-        for (SourcedResourceName& exportedSymbol : fileDesc->exportedSymbols) {
-            if (exportedSymbol.name.package.empty()) {
-                exportedSymbol.name.package = mContext->getCompilationPackage();
-            }
-
-            ResourceNameRef resName = exportedSymbol.name;
-
-            Maybe<ResourceName> mangledName = mContext->getNameMangler()->mangleName(
-                    exportedSymbol.name);
-            if (mangledName) {
-                resName = mangledName.value();
-            }
-
-            std::unique_ptr<Id> id = util::make_unique<Id>();
-            id->setSource(fileDesc->source.withLine(exportedSymbol.line));
-            bool result = mFinalTable.addResourceAllowMangled(
-                    resName, ConfigDescription::defaultConfig(), std::string(), std::move(id),
-                    mContext->getDiagnostics());
-            if (!result) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-    /**
-     * Takes a path to load as a ZIP file and merges the files within into the master ResourceTable.
-     * If override is true, conflicting resources are allowed to override each other, in order of
-     * last seen.
-     *
-     * An io::IFileCollection is created from the ZIP file and added to the set of
-     * io::IFileCollections that are open.
-     */
-    bool mergeArchive(const std::string& input, bool override) {
-        if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(DiagMessage() << "merging archive " << input);
-        }
-
-        std::string errorStr;
-        std::unique_ptr<io::ZipFileCollection> collection =
-                io::ZipFileCollection::create(input, &errorStr);
-        if (!collection) {
-            mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
-            return false;
-        }
-
-        bool error = false;
-        for (auto iter = collection->iterator(); iter->hasNext(); ) {
-            if (!mergeFile(iter->next(), override)) {
-                error = true;
-            }
-        }
-
-        // Make sure to move the collection into the set of IFileCollections.
-        mCollections.push_back(std::move(collection));
-        return !error;
-    }
-
-    /**
-     * Takes a path to load and merge into the master ResourceTable. If override is true,
-     * conflicting resources are allowed to override each other, in order of last seen.
-     *
-     * If the file path ends with .flata, .jar, .jack, or .zip the file is treated as ZIP archive
-     * and the files within are merged individually.
-     *
-     * Otherwise the files is processed on its own.
-     */
-    bool mergePath(const std::string& path, bool override) {
-        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(path, ".apk")) {
-            return mergeStaticLibrary(path, override);
-        }
-
-        io::IFile* file = mFileCollection->insertFile(path);
-        return mergeFile(file, override);
-    }
-
-    /**
-     * Takes a file to load and merge into the master ResourceTable. If override is true,
-     * conflicting resources are allowed to override each other, in order of last seen.
-     *
-     * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and merged into the
-     * master ResourceTable. If the file ends with .flat, then it is treated like a compiled file
-     * and the header data is read and merged into the final ResourceTable.
-     *
-     * All other file types are ignored. This is because these files could be coming from a zip,
-     * where we could have other files like classes.dex.
-     */
-    bool mergeFile(io::IFile* file, bool override) {
-        const Source& src = file->getSource();
-        if (util::stringEndsWith(src.path, ".arsc.flat")) {
-            return mergeResourceTable(file, override);
-
-        } 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) {
-                mContext->getDiagnostics()->error(DiagMessage(src) << "failed to open");
-                return false;
-            }
-
-            CompiledFileInputStream inputStream(data->data(), data->size());
-            uint32_t numFiles = 0;
-            if (!inputStream.ReadLittleEndian32(&numFiles)) {
-                mContext->getDiagnostics()->error(DiagMessage(src) << "failed read num files");
-                return false;
-            }
-
-            for (uint32_t i = 0; i < numFiles; i++) {
-                pb::CompiledFile compiledFile;
-                if (!inputStream.ReadCompiledFile(&compiledFile)) {
-                    mContext->getDiagnostics()->error(DiagMessage(src)
-                                                      << "failed to read compiled file header");
-                    return false;
-                }
-
-                uint64_t offset, len;
-                if (!inputStream.ReadDataMetaData(&offset, &len)) {
-                    mContext->getDiagnostics()->error(DiagMessage(src)
-                                                      << "failed to read data meta data");
-                    return false;
-                }
-
-                std::unique_ptr<ResourceFile> resourceFile = deserializeCompiledFileFromPb(
-                        compiledFile, file->getSource(), mContext->getDiagnostics());
-                if (!resourceFile) {
-                    return false;
-                }
-
-                if (!mergeCompiledFile(file->createFileSegment(offset, len), resourceFile.get(),
-                                       override)) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        // Ignore non .flat files. This could be classes.dex or something else that happens
-        // to be in an archive.
-        return true;
-    }
-
-    std::unique_ptr<xml::XmlResource> generateSplitManifest(const AppInfo& appInfo,
-                                                            const SplitConstraints& constraints) {
-        std::unique_ptr<xml::XmlResource> doc = util::make_unique<xml::XmlResource>();
-
-        std::unique_ptr<xml::Namespace> namespaceAndroid = util::make_unique<xml::Namespace>();
-        namespaceAndroid->namespaceUri = xml::kSchemaAndroid;
-        namespaceAndroid->namespacePrefix = "android";
-
-        std::unique_ptr<xml::Element> manifestEl = util::make_unique<xml::Element>();
-        manifestEl->name = "manifest";
-        manifestEl->attributes.push_back(
-                xml::Attribute{ "", "package", appInfo.package });
-
-        if (appInfo.versionCode) {
-            manifestEl->attributes.push_back(xml::Attribute{
-                    xml::kSchemaAndroid,
-                    "versionCode",
-                    std::to_string(appInfo.versionCode.value()) });
-        }
-
-        if (appInfo.revisionCode) {
-            manifestEl->attributes.push_back(xml::Attribute{
-                    xml::kSchemaAndroid,
-                    "revisionCode", std::to_string(appInfo.revisionCode.value()) });
-        }
-
-        std::stringstream splitName;
-        splitName << "config." << util::joiner(constraints.configs, "_");
-
-        manifestEl->attributes.push_back(
-                xml::Attribute{ "", "split", splitName.str() });
-
-        std::unique_ptr<xml::Element> applicationEl = util::make_unique<xml::Element>();
-        applicationEl->name = "application";
-        applicationEl->attributes.push_back(
-                xml::Attribute{ xml::kSchemaAndroid, "hasCode", "false" });
-
-        manifestEl->addChild(std::move(applicationEl));
-        namespaceAndroid->addChild(std::move(manifestEl));
-        doc->root = std::move(namespaceAndroid);
-        return doc;
-    }
-
-    /**
-     * Writes the AndroidManifest, ResourceTable, and all XML files referenced by the ResourceTable
-     * to the IArchiveWriter.
-     */
-    bool writeApk(IArchiveWriter* writer, proguard::KeepSet* keepSet, xml::XmlResource* manifest,
-                  ResourceTable* table) {
-        const bool keepRawValues = mOptions.staticLib;
-        bool result = flattenXml(manifest, "AndroidManifest.xml", {}, keepRawValues, writer,
-                                 mContext);
-        if (!result) {
-            return false;
-        }
-
-        ResourceFileFlattenerOptions fileFlattenerOptions;
-        fileFlattenerOptions.keepRawValues = keepRawValues;
-        fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
-        fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
-        fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
-        fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
-        fileFlattenerOptions.noXmlNamespaces = mOptions.noXmlNamespaces;
-        fileFlattenerOptions.updateProguardSpec =
-                static_cast<bool>(mOptions.generateProguardRulesPath);
-
-        ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, keepSet);
-
-        if (!fileFlattener.flatten(table, writer)) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
-            return false;
-        }
-
-        if (mOptions.staticLib) {
-            if (!flattenTableToPb(table, writer)) {
-                mContext->getDiagnostics()->error(DiagMessage()
-                                                  << "failed to write resources.arsc.flat");
-                return false;
-            }
-        } else {
-            if (!flattenTable(table, writer)) {
-                mContext->getDiagnostics()->error(DiagMessage()
-                                                  << "failed to write resources.arsc");
-                return false;
-            }
-        }
-        return true;
-    }
-
-    int run(const std::vector<std::string>& inputFiles) {
-        // Load the AndroidManifest.xml
-        std::unique_ptr<xml::XmlResource> manifestXml = loadXml(mOptions.manifestPath,
-                                                                mContext->getDiagnostics());
-        if (!manifestXml) {
-            return 1;
-        }
-
-        // First extract the Package name without modifying it (via --rename-manifest-package).
-        if (Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get(),
-                                                                     mContext->getDiagnostics())) {
-            const AppInfo& appInfo = maybeAppInfo.value();
-            mContext->setCompilationPackage(appInfo.package);
-        }
-
-        ManifestFixer manifestFixer(mOptions.manifestFixerOptions);
-        if (!manifestFixer.consume(mContext, manifestXml.get())) {
-            return 1;
-        }
-
-        Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get(),
-                                                                 mContext->getDiagnostics());
-        if (!maybeAppInfo) {
-            return 1;
-        }
-
-        const AppInfo& appInfo = maybeAppInfo.value();
-        if (appInfo.minSdkVersion) {
-            if (Maybe<int> maybeMinSdkVersion =
-                    ResourceUtils::parseSdkVersion(appInfo.minSdkVersion.value())) {
-                mContext->setMinSdkVersion(maybeMinSdkVersion.value());
-            }
-        }
-
-        mContext->setNameManglerPolicy(NameManglerPolicy{ mContext->getCompilationPackage() });
-        if (mContext->getCompilationPackage() == "android") {
-            mContext->setPackageId(0x01);
-        } else {
-            mContext->setPackageId(0x7f);
-        }
-
-        if (!loadSymbolsFromIncludePaths()) {
-            return 1;
-        }
-
-        TableMergerOptions tableMergerOptions;
-        tableMergerOptions.autoAddOverlay = mOptions.autoAddOverlay;
-        mTableMerger = util::make_unique<TableMerger>(mContext, &mFinalTable, tableMergerOptions);
-
-        if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(
-                    DiagMessage() << "linking package '" << mContext->getCompilationPackage()
-                                  << "' with package ID " << std::hex
-                                  << (int) mContext->getPackageId());
-        }
-
-
-        for (const std::string& input : inputFiles) {
-            if (!mergePath(input, false)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed parsing input");
-                return 1;
-            }
-        }
-
-        for (const std::string& input : mOptions.overlayFiles) {
-            if (!mergePath(input, true)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed parsing overlays");
-                return 1;
-            }
-        }
-
-        if (!verifyNoExternalPackages()) {
-            return 1;
-        }
-
+      // First try to load the file as a static lib.
+      std::string errorStr;
+      std::unique_ptr<ResourceTable> staticInclude =
+          loadStaticLibrary(path, &errorStr);
+      if (staticInclude) {
         if (!mOptions.staticLib) {
-            PrivateAttributeMover mover;
-            if (!mover.consume(mContext, &mFinalTable)) {
+          // Can't include static libraries when not building a static library.
+          mContext->getDiagnostics()->error(
+              DiagMessage(path)
+              << "can't include static library when building app");
+          return false;
+        }
+
+        // If we are using --no-static-lib-packages, we need to rename the
+        // package of this
+        // table to our compilation package.
+        if (mOptions.noStaticLibPackages) {
+          if (ResourceTablePackage* pkg =
+                  staticInclude->findPackageById(0x7f)) {
+            pkg->name = mContext->getCompilationPackage();
+          }
+        }
+
+        mContext->getExternalSymbols()->appendSource(
+            util::make_unique<ResourceTableSymbolSource>(staticInclude.get()));
+
+        mStaticTableIncludes.push_back(std::move(staticInclude));
+
+      } else if (!errorStr.empty()) {
+        // We had an error with reading, so fail.
+        mContext->getDiagnostics()->error(DiagMessage(path) << errorStr);
+        return false;
+      }
+
+      if (!assetSource->addAssetPath(path)) {
+        mContext->getDiagnostics()->error(DiagMessage(path)
+                                          << "failed to load include path");
+        return false;
+      }
+    }
+
+    mContext->getExternalSymbols()->appendSource(std::move(assetSource));
+    return true;
+  }
+
+  Maybe<AppInfo> extractAppInfoFromManifest(xml::XmlResource* xmlRes,
+                                            IDiagnostics* diag) {
+    // Make sure the first element is <manifest> with package attribute.
+    if (xml::Element* manifestEl = xml::findRootElement(xmlRes->root.get())) {
+      AppInfo appInfo;
+
+      if (!manifestEl->namespaceUri.empty() || manifestEl->name != "manifest") {
+        diag->error(DiagMessage(xmlRes->file.source)
+                    << "root tag must be <manifest>");
+        return {};
+      }
+
+      xml::Attribute* packageAttr = manifestEl->findAttribute({}, "package");
+      if (!packageAttr) {
+        diag->error(DiagMessage(xmlRes->file.source)
+                    << "<manifest> must have a 'package' attribute");
+        return {};
+      }
+
+      appInfo.package = packageAttr->value;
+
+      if (xml::Attribute* versionCodeAttr =
+              manifestEl->findAttribute(xml::kSchemaAndroid, "versionCode")) {
+        Maybe<uint32_t> maybeCode =
+            ResourceUtils::parseInt(versionCodeAttr->value);
+        if (!maybeCode) {
+          diag->error(
+              DiagMessage(xmlRes->file.source.withLine(manifestEl->lineNumber))
+              << "invalid android:versionCode '" << versionCodeAttr->value
+              << "'");
+          return {};
+        }
+        appInfo.versionCode = maybeCode.value();
+      }
+
+      if (xml::Attribute* revisionCodeAttr =
+              manifestEl->findAttribute(xml::kSchemaAndroid, "revisionCode")) {
+        Maybe<uint32_t> maybeCode =
+            ResourceUtils::parseInt(revisionCodeAttr->value);
+        if (!maybeCode) {
+          diag->error(
+              DiagMessage(xmlRes->file.source.withLine(manifestEl->lineNumber))
+              << "invalid android:revisionCode '" << revisionCodeAttr->value
+              << "'");
+          return {};
+        }
+        appInfo.revisionCode = maybeCode.value();
+      }
+
+      if (xml::Element* usesSdkEl = manifestEl->findChild({}, "uses-sdk")) {
+        if (xml::Attribute* minSdk = usesSdkEl->findAttribute(
+                xml::kSchemaAndroid, "minSdkVersion")) {
+          appInfo.minSdkVersion = minSdk->value;
+        }
+      }
+
+      return appInfo;
+    }
+    return {};
+  }
+
+  /**
+   * Precondition: ResourceTable doesn't have any IDs assigned yet, nor is it
+   * linked.
+   * Postcondition: ResourceTable has only one package left. All others are
+   * stripped, or there
+   *                is an error and false is returned.
+   */
+  bool verifyNoExternalPackages() {
+    auto isExtPackageFunc =
+        [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
+      return mContext->getCompilationPackage() != pkg->name || !pkg->id ||
+             pkg->id.value() != mContext->getPackageId();
+    };
+
+    bool error = false;
+    for (const auto& package : mFinalTable.packages) {
+      if (isExtPackageFunc(package)) {
+        // We have a package that is not related to the one we're building!
+        for (const auto& type : package->types) {
+          for (const auto& entry : type->entries) {
+            ResourceNameRef resName(package->name, type->type, entry->name);
+
+            for (const auto& configValue : entry->values) {
+              // 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 == "android") {
+                mContext->getDiagnostics()->warn(
+                    DiagMessage(configValue->value->getSource())
+                    << "generated id '" << resName << "' for external package '"
+                    << package->name << "'");
+              } else {
                 mContext->getDiagnostics()->error(
-                        DiagMessage() << "failed moving private attributes");
-                return 1;
-            }
-
-            // Assign IDs if we are building a regular app.
-            IdAssigner idAssigner(&mOptions.stableIdMap);
-            if (!idAssigner.consume(mContext, &mFinalTable)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed assigning IDs");
-                return 1;
-            }
-
-            // Now grab each ID and emit it as a file.
-            if (mOptions.resourceIdMapPath) {
-                for (auto& package : mFinalTable.packages) {
-                    for (auto& type : package->types) {
-                        for (auto& entry : type->entries) {
-                            ResourceName name(package->name, type->type, entry->name);
-                            // The IDs are guaranteed to exist.
-                            mOptions.stableIdMap[std::move(name)] = ResourceId(package->id.value(),
-                                                                               type->id.value(),
-                                                                               entry->id.value());
-                        }
-                    }
-                }
-
-                if (!writeStableIdMapToPath(mContext->getDiagnostics(),
-                                            mOptions.stableIdMap,
-                                            mOptions.resourceIdMapPath.value())) {
-                    return 1;
-                }
-            }
-        } else {
-            // Static libs are merged with other apps, and ID collisions are bad, so verify that
-            // no IDs have been set.
-            if (!verifyNoIdsSet()) {
-                return 1;
-            }
-        }
-
-        // Add the names to mangle based on our source merge earlier.
-        mContext->setNameManglerPolicy(NameManglerPolicy{
-                mContext->getCompilationPackage(), mTableMerger->getMergedPackages() });
-
-        // Add our table to the symbol table.
-        mContext->getExternalSymbols()->prependSource(
-                        util::make_unique<ResourceTableSymbolSource>(&mFinalTable));
-
-        ReferenceLinker linker;
-        if (!linker.consume(mContext, &mFinalTable)) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed linking references");
-            return 1;
-        }
-
-        if (mOptions.staticLib) {
-            if (!mOptions.products.empty()) {
-                mContext->getDiagnostics()->warn(
-                        DiagMessage() << "can't select products when building static library");
-            }
-        } else {
-            ProductFilter productFilter(mOptions.products);
-            if (!productFilter.consume(mContext, &mFinalTable)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
-                return 1;
-            }
-        }
-
-        if (!mOptions.noAutoVersion) {
-            AutoVersioner versioner;
-            if (!versioner.consume(mContext, &mFinalTable)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed versioning styles");
-                return 1;
-            }
-        }
-
-        if (!mOptions.staticLib && mContext->getMinSdkVersion() > 0) {
-            if (mContext->verbose()) {
-                mContext->getDiagnostics()->note(
-                        DiagMessage() << "collapsing resource versions for minimum SDK "
-                        << mContext->getMinSdkVersion());
-            }
-
-            VersionCollapser collapser;
-            if (!collapser.consume(mContext, &mFinalTable)) {
-                return 1;
-            }
-        }
-
-        if (!mOptions.noResourceDeduping) {
-            ResourceDeduper deduper;
-            if (!deduper.consume(mContext, &mFinalTable)) {
-                mContext->getDiagnostics()->error(DiagMessage() << "failed deduping resources");
-                return 1;
-            }
-        }
-
-        proguard::KeepSet proguardKeepSet;
-        proguard::KeepSet proguardMainDexKeepSet;
-
-        if (mOptions.staticLib) {
-            if (mOptions.tableSplitterOptions.configFilter != nullptr ||
-                    mOptions.tableSplitterOptions.preferredDensity) {
-                mContext->getDiagnostics()->warn(
-                        DiagMessage() << "can't strip resources when building static library");
-            }
-        } else {
-            // Adjust the SplitConstraints so that their SDK version is stripped if it is less
-            // than or equal to the minSdk. Otherwise the resources that have had their SDK version
-            // stripped due to minSdk won't ever match.
-            std::vector<SplitConstraints> adjustedConstraintsList;
-            adjustedConstraintsList.reserve(mOptions.splitConstraints.size());
-            for (const SplitConstraints& constraints : mOptions.splitConstraints) {
-                SplitConstraints adjustedConstraints;
-                for (const ConfigDescription& config : constraints.configs) {
-                    if (config.sdkVersion <= mContext->getMinSdkVersion()) {
-                        adjustedConstraints.configs.insert(config.copyWithoutSdkVersion());
-                    } else {
-                        adjustedConstraints.configs.insert(config);
-                    }
-                }
-                adjustedConstraintsList.push_back(std::move(adjustedConstraints));
-            }
-
-            TableSplitter tableSplitter(adjustedConstraintsList, mOptions.tableSplitterOptions);
-            if (!tableSplitter.verifySplitConstraints(mContext)) {
-                return 1;
-            }
-            tableSplitter.splitTable(&mFinalTable);
-
-            // Now we need to write out the Split APKs.
-            auto pathIter = mOptions.splitPaths.begin();
-            auto splitConstraintsIter = adjustedConstraintsList.begin();
-            for (std::unique_ptr<ResourceTable>& splitTable : tableSplitter.getSplits()) {
-                if (mContext->verbose()) {
-                    mContext->getDiagnostics()->note(
-                            DiagMessage(*pathIter) << "generating split with configurations '"
-                            << util::joiner(splitConstraintsIter->configs, ", ") << "'");
-                }
-
-                std::unique_ptr<IArchiveWriter> archiveWriter = makeArchiveWriter(*pathIter);
-                if (!archiveWriter) {
-                    mContext->getDiagnostics()->error(DiagMessage() << "failed to create archive");
-                    return 1;
-                }
-
-                // Generate an AndroidManifest.xml for each split.
-                std::unique_ptr<xml::XmlResource> splitManifest =
-                        generateSplitManifest(appInfo, *splitConstraintsIter);
-
-                XmlReferenceLinker linker;
-                if (!linker.consume(mContext, splitManifest.get())) {
-                    mContext->getDiagnostics()->error(
-                            DiagMessage() << "failed to create Split AndroidManifest.xml");
-                    return 1;
-                }
-
-                if (!writeApk(archiveWriter.get(), &proguardKeepSet, splitManifest.get(),
-                              splitTable.get())) {
-                    return 1;
-                }
-
-                ++pathIter;
-                ++splitConstraintsIter;
-            }
-        }
-
-        // Start writing the base APK.
-        std::unique_ptr<IArchiveWriter> archiveWriter = makeArchiveWriter(mOptions.outputPath);
-        if (!archiveWriter) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed to create archive");
-            return 1;
-        }
-
-        bool error = false;
-        {
-            // AndroidManifest.xml has no resource name, but the CallSite is built from the name
-            // (aka, which package the AndroidManifest.xml is coming from).
-            // So we give it a package name so it can see local resources.
-            manifestXml->file.name.package = mContext->getCompilationPackage();
-
-            XmlReferenceLinker manifestLinker;
-            if (manifestLinker.consume(mContext, manifestXml.get())) {
-                if (mOptions.generateProguardRulesPath &&
-                        !proguard::collectProguardRulesForManifest(Source(mOptions.manifestPath),
-                                                                   manifestXml.get(),
-                                                                   &proguardKeepSet)) {
-                    error = true;
-                }
-
-                if (mOptions.generateMainDexProguardRulesPath &&
-                        !proguard::collectProguardRulesForManifest(Source(mOptions.manifestPath),
-                                                                   manifestXml.get(),
-                                                                   &proguardMainDexKeepSet,
-                                                                   true)) {
-                    error = true;
-                }
-
-                if (mOptions.generateJavaClassPath) {
-                    if (!writeManifestJavaFile(manifestXml.get())) {
-                        error = true;
-                    }
-                }
-
-                if (mOptions.noXmlNamespaces) {
-                    // PackageParser will fail if URIs are removed from AndroidManifest.xml.
-                    XmlNamespaceRemover namespaceRemover(true /* keepUris */);
-                    if (!namespaceRemover.consume(mContext, manifestXml.get())) {
-                        error = true;
-                    }
-                }
-            } else {
+                    DiagMessage(configValue->value->getSource())
+                    << "defined resource '" << resName
+                    << "' for external package '" << package->name << "'");
                 error = true;
+              }
             }
+          }
+        }
+      }
+    }
+
+    auto newEndIter =
+        std::remove_if(mFinalTable.packages.begin(), mFinalTable.packages.end(),
+                       isExtPackageFunc);
+    mFinalTable.packages.erase(newEndIter, mFinalTable.packages.end());
+    return !error;
+  }
+
+  /**
+   * Returns true if no IDs have been set, false otherwise.
+   */
+  bool verifyNoIdsSet() {
+    for (const auto& package : mFinalTable.packages) {
+      for (const auto& type : package->types) {
+        if (type->id) {
+          mContext->getDiagnostics()->error(
+              DiagMessage() << "type " << type->type << " has ID " << std::hex
+                            << (int)type->id.value() << std::dec
+                            << " assigned");
+          return false;
         }
 
-        if (error) {
-            mContext->getDiagnostics()->error(DiagMessage() << "failed processing manifest");
-            return 1;
+        for (const auto& entry : type->entries) {
+          if (entry->id) {
+            ResourceNameRef resName(package->name, type->type, entry->name);
+            mContext->getDiagnostics()->error(
+                DiagMessage() << "entry " << resName << " has ID " << std::hex
+                              << (int)entry->id.value() << std::dec
+                              << " assigned");
+            return false;
+          }
+        }
+      }
+    }
+    return true;
+  }
+
+  std::unique_ptr<IArchiveWriter> makeArchiveWriter(const StringPiece& out) {
+    if (mOptions.outputToDirectory) {
+      return createDirectoryArchiveWriter(mContext->getDiagnostics(), out);
+    } else {
+      return createZipFileArchiveWriter(mContext->getDiagnostics(), out);
+    }
+  }
+
+  bool flattenTable(ResourceTable* table, IArchiveWriter* writer) {
+    BigBuffer buffer(1024);
+    TableFlattener flattener(&buffer);
+    if (!flattener.consume(mContext, table)) {
+      return false;
+    }
+
+    if (writer->startEntry("resources.arsc", ArchiveEntry::kAlign)) {
+      if (writer->writeEntry(buffer)) {
+        if (writer->finishEntry()) {
+          return true;
+        }
+      }
+    }
+
+    mContext->getDiagnostics()->error(
+        DiagMessage() << "failed to write resources.arsc to archive");
+    return false;
+  }
+
+  bool flattenTableToPb(ResourceTable* table, IArchiveWriter* writer) {
+    // Create the file/zip entry.
+    if (!writer->startEntry("resources.arsc.flat", 0)) {
+      mContext->getDiagnostics()->error(DiagMessage() << "failed to open");
+      return false;
+    }
+
+    // Make sure CopyingOutputStreamAdaptor is deleted before we call
+    // writer->finishEntry().
+    {
+      // Wrap our IArchiveWriter with an adaptor that implements the
+      // ZeroCopyOutputStream
+      // interface.
+      CopyingOutputStreamAdaptor adaptor(writer);
+
+      std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table);
+      if (!pbTable->SerializeToZeroCopyStream(&adaptor)) {
+        mContext->getDiagnostics()->error(DiagMessage() << "failed to write");
+        return false;
+      }
+    }
+
+    if (!writer->finishEntry()) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed to finish entry");
+      return false;
+    }
+    return true;
+  }
+
+  bool writeJavaFile(ResourceTable* table,
+                     const StringPiece& packageNameToGenerate,
+                     const StringPiece& outPackage,
+                     const JavaClassGeneratorOptions& javaOptions) {
+    if (!mOptions.generateJavaClassPath) {
+      return true;
+    }
+
+    std::string outPath = mOptions.generateJavaClassPath.value();
+    file::appendPath(&outPath, file::packageToPath(outPackage));
+    if (!file::mkdirs(outPath)) {
+      mContext->getDiagnostics()->error(
+          DiagMessage() << "failed to create directory '" << outPath << "'");
+      return false;
+    }
+
+    file::appendPath(&outPath, "R.java");
+
+    std::ofstream fout(outPath, std::ofstream::binary);
+    if (!fout) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed writing to '" << outPath
+                                        << "': " << strerror(errno));
+      return false;
+    }
+
+    JavaClassGenerator generator(mContext, table, javaOptions);
+    if (!generator.generate(packageNameToGenerate, outPackage, &fout)) {
+      mContext->getDiagnostics()->error(DiagMessage(outPath)
+                                        << generator.getError());
+      return false;
+    }
+
+    if (!fout) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed writing to '" << outPath
+                                        << "': " << strerror(errno));
+    }
+    return true;
+  }
+
+  bool writeManifestJavaFile(xml::XmlResource* manifestXml) {
+    if (!mOptions.generateJavaClassPath) {
+      return true;
+    }
+
+    std::unique_ptr<ClassDefinition> manifestClass =
+        generateManifestClass(mContext->getDiagnostics(), manifestXml);
+
+    if (!manifestClass) {
+      // Something bad happened, but we already logged it, so exit.
+      return false;
+    }
+
+    if (manifestClass->empty()) {
+      // Empty Manifest class, no need to generate it.
+      return true;
+    }
+
+    // Add any JavaDoc annotations to the generated class.
+    for (const std::string& annotation : mOptions.javadocAnnotations) {
+      std::string properAnnotation = "@";
+      properAnnotation += annotation;
+      manifestClass->getCommentBuilder()->appendComment(properAnnotation);
+    }
+
+    const std::string& packageUtf8 = mContext->getCompilationPackage();
+
+    std::string outPath = mOptions.generateJavaClassPath.value();
+    file::appendPath(&outPath, file::packageToPath(packageUtf8));
+
+    if (!file::mkdirs(outPath)) {
+      mContext->getDiagnostics()->error(
+          DiagMessage() << "failed to create directory '" << outPath << "'");
+      return false;
+    }
+
+    file::appendPath(&outPath, "Manifest.java");
+
+    std::ofstream fout(outPath, std::ofstream::binary);
+    if (!fout) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed writing to '" << outPath
+                                        << "': " << strerror(errno));
+      return false;
+    }
+
+    if (!ClassDefinition::writeJavaFile(manifestClass.get(), packageUtf8, true,
+                                        &fout)) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed writing to '" << outPath
+                                        << "': " << strerror(errno));
+      return false;
+    }
+    return true;
+  }
+
+  bool writeProguardFile(const Maybe<std::string>& out,
+                         const proguard::KeepSet& keepSet) {
+    if (!out) {
+      return true;
+    }
+
+    const std::string& outPath = out.value();
+    std::ofstream fout(outPath, std::ofstream::binary);
+    if (!fout) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed to open '" << outPath
+                                        << "': " << strerror(errno));
+      return false;
+    }
+
+    proguard::writeKeepSet(&fout, keepSet);
+    if (!fout) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed writing to '" << outPath
+                                        << "': " << strerror(errno));
+      return false;
+    }
+    return true;
+  }
+
+  std::unique_ptr<ResourceTable> loadStaticLibrary(const std::string& input,
+                                                   std::string* outError) {
+    std::unique_ptr<io::ZipFileCollection> collection =
+        io::ZipFileCollection::create(input, outError);
+    if (!collection) {
+      return {};
+    }
+    return loadTablePbFromCollection(collection.get());
+  }
+
+  std::unique_ptr<ResourceTable> loadTablePbFromCollection(
+      io::IFileCollection* collection) {
+    io::IFile* file = collection->findFile("resources.arsc.flat");
+    if (!file) {
+      return {};
+    }
+
+    std::unique_ptr<io::IData> data = file->openAsData();
+    return loadTableFromPb(file->getSource(), data->data(), data->size(),
+                           mContext->getDiagnostics());
+  }
+
+  bool mergeStaticLibrary(const std::string& input, bool override) {
+    if (mContext->verbose()) {
+      mContext->getDiagnostics()->note(DiagMessage()
+                                       << "merging static library " << input);
+    }
+
+    std::string errorStr;
+    std::unique_ptr<io::ZipFileCollection> collection =
+        io::ZipFileCollection::create(input, &errorStr);
+    if (!collection) {
+      mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
+      return false;
+    }
+
+    std::unique_ptr<ResourceTable> table =
+        loadTablePbFromCollection(collection.get());
+    if (!table) {
+      mContext->getDiagnostics()->error(DiagMessage(input)
+                                        << "invalid static library");
+      return false;
+    }
+
+    ResourceTablePackage* pkg = table->findPackageById(0x7f);
+    if (!pkg) {
+      mContext->getDiagnostics()->error(DiagMessage(input)
+                                        << "static library has no package");
+      return false;
+    }
+
+    bool result;
+    if (mOptions.noStaticLibPackages) {
+      // Merge all resources as if they were in the compilation package. This is
+      // the old
+      // behaviour of aapt.
+
+      // Add the package to the set of --extra-packages so we emit an R.java for
+      // each
+      // library package.
+      if (!pkg->name.empty()) {
+        mOptions.extraJavaPackages.insert(pkg->name);
+      }
+
+      pkg->name = "";
+      if (override) {
+        result = mTableMerger->mergeOverlay(Source(input), table.get(),
+                                            collection.get());
+      } else {
+        result =
+            mTableMerger->merge(Source(input), table.get(), collection.get());
+      }
+
+    } else {
+      // This is the proper way to merge libraries, where the package name is
+      // preserved
+      // and resource names are mangled.
+      result = mTableMerger->mergeAndMangle(Source(input), pkg->name,
+                                            table.get(), collection.get());
+    }
+
+    if (!result) {
+      return false;
+    }
+
+    // Make sure to move the collection into the set of IFileCollections.
+    mCollections.push_back(std::move(collection));
+    return true;
+  }
+
+  bool mergeResourceTable(io::IFile* file, bool override) {
+    if (mContext->verbose()) {
+      mContext->getDiagnostics()->note(
+          DiagMessage() << "merging resource table " << file->getSource());
+    }
+
+    std::unique_ptr<io::IData> data = file->openAsData();
+    if (!data) {
+      mContext->getDiagnostics()->error(DiagMessage(file->getSource())
+                                        << "failed to open file");
+      return false;
+    }
+
+    std::unique_ptr<ResourceTable> table =
+        loadTableFromPb(file->getSource(), data->data(), data->size(),
+                        mContext->getDiagnostics());
+    if (!table) {
+      return false;
+    }
+
+    bool result = false;
+    if (override) {
+      result = mTableMerger->mergeOverlay(file->getSource(), table.get());
+    } else {
+      result = mTableMerger->merge(file->getSource(), table.get());
+    }
+    return result;
+  }
+
+  bool mergeCompiledFile(io::IFile* file, ResourceFile* fileDesc,
+                         bool override) {
+    if (mContext->verbose()) {
+      mContext->getDiagnostics()->note(
+          DiagMessage() << "merging '" << fileDesc->name
+                        << "' from compiled file " << file->getSource());
+    }
+
+    bool result = false;
+    if (override) {
+      result = mTableMerger->mergeFileOverlay(*fileDesc, file);
+    } else {
+      result = mTableMerger->mergeFile(*fileDesc, file);
+    }
+
+    if (!result) {
+      return false;
+    }
+
+    // Add the exports of this file to the table.
+    for (SourcedResourceName& exportedSymbol : fileDesc->exportedSymbols) {
+      if (exportedSymbol.name.package.empty()) {
+        exportedSymbol.name.package = mContext->getCompilationPackage();
+      }
+
+      ResourceNameRef resName = exportedSymbol.name;
+
+      Maybe<ResourceName> mangledName =
+          mContext->getNameMangler()->mangleName(exportedSymbol.name);
+      if (mangledName) {
+        resName = mangledName.value();
+      }
+
+      std::unique_ptr<Id> id = util::make_unique<Id>();
+      id->setSource(fileDesc->source.withLine(exportedSymbol.line));
+      bool result = mFinalTable.addResourceAllowMangled(
+          resName, ConfigDescription::defaultConfig(), std::string(),
+          std::move(id), mContext->getDiagnostics());
+      if (!result) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  /**
+   * Takes a path to load as a ZIP file and merges the files within into the
+   * master ResourceTable.
+   * If override is true, conflicting resources are allowed to override each
+   * other, in order of
+   * last seen.
+   *
+   * An io::IFileCollection is created from the ZIP file and added to the set of
+   * io::IFileCollections that are open.
+   */
+  bool mergeArchive(const std::string& input, bool override) {
+    if (mContext->verbose()) {
+      mContext->getDiagnostics()->note(DiagMessage() << "merging archive "
+                                                     << input);
+    }
+
+    std::string errorStr;
+    std::unique_ptr<io::ZipFileCollection> collection =
+        io::ZipFileCollection::create(input, &errorStr);
+    if (!collection) {
+      mContext->getDiagnostics()->error(DiagMessage(input) << errorStr);
+      return false;
+    }
+
+    bool error = false;
+    for (auto iter = collection->iterator(); iter->hasNext();) {
+      if (!mergeFile(iter->next(), override)) {
+        error = true;
+      }
+    }
+
+    // Make sure to move the collection into the set of IFileCollections.
+    mCollections.push_back(std::move(collection));
+    return !error;
+  }
+
+  /**
+   * Takes a path to load and merge into the master ResourceTable. If override
+   * is true,
+   * conflicting resources are allowed to override each other, in order of last
+   * seen.
+   *
+   * If the file path ends with .flata, .jar, .jack, or .zip the file is treated
+   * as ZIP archive
+   * and the files within are merged individually.
+   *
+   * Otherwise the files is processed on its own.
+   */
+  bool mergePath(const std::string& path, bool override) {
+    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(path, ".apk")) {
+      return mergeStaticLibrary(path, override);
+    }
+
+    io::IFile* file = mFileCollection->insertFile(path);
+    return mergeFile(file, override);
+  }
+
+  /**
+   * Takes a file to load and merge into the master ResourceTable. If override
+   * is true,
+   * conflicting resources are allowed to override each other, in order of last
+   * seen.
+   *
+   * If the file ends with .arsc.flat, then it is loaded as a ResourceTable and
+   * merged into the
+   * master ResourceTable. If the file ends with .flat, then it is treated like
+   * a compiled file
+   * and the header data is read and merged into the final ResourceTable.
+   *
+   * All other file types are ignored. This is because these files could be
+   * coming from a zip,
+   * where we could have other files like classes.dex.
+   */
+  bool mergeFile(io::IFile* file, bool override) {
+    const Source& src = file->getSource();
+    if (util::stringEndsWith(src.path, ".arsc.flat")) {
+      return mergeResourceTable(file, override);
+
+    } 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) {
+        mContext->getDiagnostics()->error(DiagMessage(src) << "failed to open");
+        return false;
+      }
+
+      CompiledFileInputStream inputStream(data->data(), data->size());
+      uint32_t numFiles = 0;
+      if (!inputStream.ReadLittleEndian32(&numFiles)) {
+        mContext->getDiagnostics()->error(DiagMessage(src)
+                                          << "failed read num files");
+        return false;
+      }
+
+      for (uint32_t i = 0; i < numFiles; i++) {
+        pb::CompiledFile compiledFile;
+        if (!inputStream.ReadCompiledFile(&compiledFile)) {
+          mContext->getDiagnostics()->error(
+              DiagMessage(src) << "failed to read compiled file header");
+          return false;
         }
 
-        if (!writeApk(archiveWriter.get(), &proguardKeepSet, manifestXml.get(), &mFinalTable)) {
-            return 1;
+        uint64_t offset, len;
+        if (!inputStream.ReadDataMetaData(&offset, &len)) {
+          mContext->getDiagnostics()->error(DiagMessage(src)
+                                            << "failed to read data meta data");
+          return false;
+        }
+
+        std::unique_ptr<ResourceFile> resourceFile =
+            deserializeCompiledFileFromPb(compiledFile, file->getSource(),
+                                          mContext->getDiagnostics());
+        if (!resourceFile) {
+          return false;
+        }
+
+        if (!mergeCompiledFile(file->createFileSegment(offset, len),
+                               resourceFile.get(), override)) {
+          return false;
+        }
+      }
+      return true;
+    }
+
+    // Ignore non .flat files. This could be classes.dex or something else that
+    // happens
+    // to be in an archive.
+    return true;
+  }
+
+  std::unique_ptr<xml::XmlResource> generateSplitManifest(
+      const AppInfo& appInfo, const SplitConstraints& constraints) {
+    std::unique_ptr<xml::XmlResource> doc =
+        util::make_unique<xml::XmlResource>();
+
+    std::unique_ptr<xml::Namespace> namespaceAndroid =
+        util::make_unique<xml::Namespace>();
+    namespaceAndroid->namespaceUri = xml::kSchemaAndroid;
+    namespaceAndroid->namespacePrefix = "android";
+
+    std::unique_ptr<xml::Element> manifestEl =
+        util::make_unique<xml::Element>();
+    manifestEl->name = "manifest";
+    manifestEl->attributes.push_back(
+        xml::Attribute{"", "package", appInfo.package});
+
+    if (appInfo.versionCode) {
+      manifestEl->attributes.push_back(
+          xml::Attribute{xml::kSchemaAndroid, "versionCode",
+                         std::to_string(appInfo.versionCode.value())});
+    }
+
+    if (appInfo.revisionCode) {
+      manifestEl->attributes.push_back(
+          xml::Attribute{xml::kSchemaAndroid, "revisionCode",
+                         std::to_string(appInfo.revisionCode.value())});
+    }
+
+    std::stringstream splitName;
+    splitName << "config." << util::joiner(constraints.configs, "_");
+
+    manifestEl->attributes.push_back(
+        xml::Attribute{"", "split", splitName.str()});
+
+    std::unique_ptr<xml::Element> applicationEl =
+        util::make_unique<xml::Element>();
+    applicationEl->name = "application";
+    applicationEl->attributes.push_back(
+        xml::Attribute{xml::kSchemaAndroid, "hasCode", "false"});
+
+    manifestEl->addChild(std::move(applicationEl));
+    namespaceAndroid->addChild(std::move(manifestEl));
+    doc->root = std::move(namespaceAndroid);
+    return doc;
+  }
+
+  /**
+   * Writes the AndroidManifest, ResourceTable, and all XML files referenced by
+   * the ResourceTable
+   * to the IArchiveWriter.
+   */
+  bool writeApk(IArchiveWriter* writer, proguard::KeepSet* keepSet,
+                xml::XmlResource* manifest, ResourceTable* table) {
+    const bool keepRawValues = mOptions.staticLib;
+    bool result = flattenXml(manifest, "AndroidManifest.xml", {}, keepRawValues,
+                             writer, mContext);
+    if (!result) {
+      return false;
+    }
+
+    ResourceFileFlattenerOptions fileFlattenerOptions;
+    fileFlattenerOptions.keepRawValues = keepRawValues;
+    fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
+    fileFlattenerOptions.extensionsToNotCompress =
+        mOptions.extensionsToNotCompress;
+    fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
+    fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
+    fileFlattenerOptions.noXmlNamespaces = mOptions.noXmlNamespaces;
+    fileFlattenerOptions.updateProguardSpec =
+        static_cast<bool>(mOptions.generateProguardRulesPath);
+
+    ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext,
+                                        keepSet);
+
+    if (!fileFlattener.flatten(table, writer)) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed linking file resources");
+      return false;
+    }
+
+    if (mOptions.staticLib) {
+      if (!flattenTableToPb(table, writer)) {
+        mContext->getDiagnostics()->error(
+            DiagMessage() << "failed to write resources.arsc.flat");
+        return false;
+      }
+    } else {
+      if (!flattenTable(table, writer)) {
+        mContext->getDiagnostics()->error(DiagMessage()
+                                          << "failed to write resources.arsc");
+        return false;
+      }
+    }
+    return true;
+  }
+
+  int run(const std::vector<std::string>& inputFiles) {
+    // Load the AndroidManifest.xml
+    std::unique_ptr<xml::XmlResource> manifestXml =
+        loadXml(mOptions.manifestPath, mContext->getDiagnostics());
+    if (!manifestXml) {
+      return 1;
+    }
+
+    // First extract the Package name without modifying it (via
+    // --rename-manifest-package).
+    if (Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(
+            manifestXml.get(), mContext->getDiagnostics())) {
+      const AppInfo& appInfo = maybeAppInfo.value();
+      mContext->setCompilationPackage(appInfo.package);
+    }
+
+    ManifestFixer manifestFixer(mOptions.manifestFixerOptions);
+    if (!manifestFixer.consume(mContext, manifestXml.get())) {
+      return 1;
+    }
+
+    Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(
+        manifestXml.get(), mContext->getDiagnostics());
+    if (!maybeAppInfo) {
+      return 1;
+    }
+
+    const AppInfo& appInfo = maybeAppInfo.value();
+    if (appInfo.minSdkVersion) {
+      if (Maybe<int> maybeMinSdkVersion =
+              ResourceUtils::parseSdkVersion(appInfo.minSdkVersion.value())) {
+        mContext->setMinSdkVersion(maybeMinSdkVersion.value());
+      }
+    }
+
+    mContext->setNameManglerPolicy(
+        NameManglerPolicy{mContext->getCompilationPackage()});
+    if (mContext->getCompilationPackage() == "android") {
+      mContext->setPackageId(0x01);
+    } else {
+      mContext->setPackageId(0x7f);
+    }
+
+    if (!loadSymbolsFromIncludePaths()) {
+      return 1;
+    }
+
+    TableMergerOptions tableMergerOptions;
+    tableMergerOptions.autoAddOverlay = mOptions.autoAddOverlay;
+    mTableMerger = util::make_unique<TableMerger>(mContext, &mFinalTable,
+                                                  tableMergerOptions);
+
+    if (mContext->verbose()) {
+      mContext->getDiagnostics()->note(DiagMessage()
+                                       << "linking package '"
+                                       << mContext->getCompilationPackage()
+                                       << "' with package ID " << std::hex
+                                       << (int)mContext->getPackageId());
+    }
+
+    for (const std::string& input : inputFiles) {
+      if (!mergePath(input, false)) {
+        mContext->getDiagnostics()->error(DiagMessage()
+                                          << "failed parsing input");
+        return 1;
+      }
+    }
+
+    for (const std::string& input : mOptions.overlayFiles) {
+      if (!mergePath(input, true)) {
+        mContext->getDiagnostics()->error(DiagMessage()
+                                          << "failed parsing overlays");
+        return 1;
+      }
+    }
+
+    if (!verifyNoExternalPackages()) {
+      return 1;
+    }
+
+    if (!mOptions.staticLib) {
+      PrivateAttributeMover mover;
+      if (!mover.consume(mContext, &mFinalTable)) {
+        mContext->getDiagnostics()->error(
+            DiagMessage() << "failed moving private attributes");
+        return 1;
+      }
+
+      // Assign IDs if we are building a regular app.
+      IdAssigner idAssigner(&mOptions.stableIdMap);
+      if (!idAssigner.consume(mContext, &mFinalTable)) {
+        mContext->getDiagnostics()->error(DiagMessage()
+                                          << "failed assigning IDs");
+        return 1;
+      }
+
+      // Now grab each ID and emit it as a file.
+      if (mOptions.resourceIdMapPath) {
+        for (auto& package : mFinalTable.packages) {
+          for (auto& type : package->types) {
+            for (auto& entry : type->entries) {
+              ResourceName name(package->name, type->type, entry->name);
+              // The IDs are guaranteed to exist.
+              mOptions.stableIdMap[std::move(name)] = ResourceId(
+                  package->id.value(), type->id.value(), entry->id.value());
+            }
+          }
+        }
+
+        if (!writeStableIdMapToPath(mContext->getDiagnostics(),
+                                    mOptions.stableIdMap,
+                                    mOptions.resourceIdMapPath.value())) {
+          return 1;
+        }
+      }
+    } else {
+      // Static libs are merged with other apps, and ID collisions are bad, so
+      // verify that
+      // no IDs have been set.
+      if (!verifyNoIdsSet()) {
+        return 1;
+      }
+    }
+
+    // Add the names to mangle based on our source merge earlier.
+    mContext->setNameManglerPolicy(NameManglerPolicy{
+        mContext->getCompilationPackage(), mTableMerger->getMergedPackages()});
+
+    // Add our table to the symbol table.
+    mContext->getExternalSymbols()->prependSource(
+        util::make_unique<ResourceTableSymbolSource>(&mFinalTable));
+
+    ReferenceLinker linker;
+    if (!linker.consume(mContext, &mFinalTable)) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed linking references");
+      return 1;
+    }
+
+    if (mOptions.staticLib) {
+      if (!mOptions.products.empty()) {
+        mContext->getDiagnostics()
+            ->warn(DiagMessage()
+                   << "can't select products when building static library");
+      }
+    } else {
+      ProductFilter productFilter(mOptions.products);
+      if (!productFilter.consume(mContext, &mFinalTable)) {
+        mContext->getDiagnostics()->error(DiagMessage()
+                                          << "failed stripping products");
+        return 1;
+      }
+    }
+
+    if (!mOptions.noAutoVersion) {
+      AutoVersioner versioner;
+      if (!versioner.consume(mContext, &mFinalTable)) {
+        mContext->getDiagnostics()->error(DiagMessage()
+                                          << "failed versioning styles");
+        return 1;
+      }
+    }
+
+    if (!mOptions.staticLib && mContext->getMinSdkVersion() > 0) {
+      if (mContext->verbose()) {
+        mContext->getDiagnostics()->note(
+            DiagMessage() << "collapsing resource versions for minimum SDK "
+                          << mContext->getMinSdkVersion());
+      }
+
+      VersionCollapser collapser;
+      if (!collapser.consume(mContext, &mFinalTable)) {
+        return 1;
+      }
+    }
+
+    if (!mOptions.noResourceDeduping) {
+      ResourceDeduper deduper;
+      if (!deduper.consume(mContext, &mFinalTable)) {
+        mContext->getDiagnostics()->error(DiagMessage()
+                                          << "failed deduping resources");
+        return 1;
+      }
+    }
+
+    proguard::KeepSet proguardKeepSet;
+    proguard::KeepSet proguardMainDexKeepSet;
+
+    if (mOptions.staticLib) {
+      if (mOptions.tableSplitterOptions.configFilter != nullptr ||
+          mOptions.tableSplitterOptions.preferredDensity) {
+        mContext->getDiagnostics()
+            ->warn(DiagMessage()
+                   << "can't strip resources when building static library");
+      }
+    } else {
+      // Adjust the SplitConstraints so that their SDK version is stripped if it
+      // is less
+      // than or equal to the minSdk. Otherwise the resources that have had
+      // their SDK version
+      // stripped due to minSdk won't ever match.
+      std::vector<SplitConstraints> adjustedConstraintsList;
+      adjustedConstraintsList.reserve(mOptions.splitConstraints.size());
+      for (const SplitConstraints& constraints : mOptions.splitConstraints) {
+        SplitConstraints adjustedConstraints;
+        for (const ConfigDescription& config : constraints.configs) {
+          if (config.sdkVersion <= mContext->getMinSdkVersion()) {
+            adjustedConstraints.configs.insert(config.copyWithoutSdkVersion());
+          } else {
+            adjustedConstraints.configs.insert(config);
+          }
+        }
+        adjustedConstraintsList.push_back(std::move(adjustedConstraints));
+      }
+
+      TableSplitter tableSplitter(adjustedConstraintsList,
+                                  mOptions.tableSplitterOptions);
+      if (!tableSplitter.verifySplitConstraints(mContext)) {
+        return 1;
+      }
+      tableSplitter.splitTable(&mFinalTable);
+
+      // Now we need to write out the Split APKs.
+      auto pathIter = mOptions.splitPaths.begin();
+      auto splitConstraintsIter = adjustedConstraintsList.begin();
+      for (std::unique_ptr<ResourceTable>& splitTable :
+           tableSplitter.getSplits()) {
+        if (mContext->verbose()) {
+          mContext->getDiagnostics()->note(
+              DiagMessage(*pathIter)
+              << "generating split with configurations '"
+              << util::joiner(splitConstraintsIter->configs, ", ") << "'");
+        }
+
+        std::unique_ptr<IArchiveWriter> archiveWriter =
+            makeArchiveWriter(*pathIter);
+        if (!archiveWriter) {
+          mContext->getDiagnostics()->error(DiagMessage()
+                                            << "failed to create archive");
+          return 1;
+        }
+
+        // Generate an AndroidManifest.xml for each split.
+        std::unique_ptr<xml::XmlResource> splitManifest =
+            generateSplitManifest(appInfo, *splitConstraintsIter);
+
+        XmlReferenceLinker linker;
+        if (!linker.consume(mContext, splitManifest.get())) {
+          mContext->getDiagnostics()->error(
+              DiagMessage() << "failed to create Split AndroidManifest.xml");
+          return 1;
+        }
+
+        if (!writeApk(archiveWriter.get(), &proguardKeepSet,
+                      splitManifest.get(), splitTable.get())) {
+          return 1;
+        }
+
+        ++pathIter;
+        ++splitConstraintsIter;
+      }
+    }
+
+    // Start writing the base APK.
+    std::unique_ptr<IArchiveWriter> archiveWriter =
+        makeArchiveWriter(mOptions.outputPath);
+    if (!archiveWriter) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed to create archive");
+      return 1;
+    }
+
+    bool error = false;
+    {
+      // AndroidManifest.xml has no resource name, but the CallSite is built
+      // from the name
+      // (aka, which package the AndroidManifest.xml is coming from).
+      // So we give it a package name so it can see local resources.
+      manifestXml->file.name.package = mContext->getCompilationPackage();
+
+      XmlReferenceLinker manifestLinker;
+      if (manifestLinker.consume(mContext, manifestXml.get())) {
+        if (mOptions.generateProguardRulesPath &&
+            !proguard::collectProguardRulesForManifest(
+                Source(mOptions.manifestPath), manifestXml.get(),
+                &proguardKeepSet)) {
+          error = true;
+        }
+
+        if (mOptions.generateMainDexProguardRulesPath &&
+            !proguard::collectProguardRulesForManifest(
+                Source(mOptions.manifestPath), manifestXml.get(),
+                &proguardMainDexKeepSet, true)) {
+          error = true;
         }
 
         if (mOptions.generateJavaClassPath) {
-            JavaClassGeneratorOptions options;
-            options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
-            options.javadocAnnotations = mOptions.javadocAnnotations;
-
-            if (mOptions.staticLib || mOptions.generateNonFinalIds) {
-                options.useFinal = false;
-            }
-
-            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();
-            }
-
-            if (mOptions.privateSymbols) {
-                // If we defined a private symbols package, we only emit Public symbols
-                // to the original package, and private and public symbols to the private package.
-
-                options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
-                if (!writeJavaFile(&mFinalTable, mContext->getCompilationPackage(),
-                                   outputPackage, options)) {
-                    return 1;
-                }
-
-                options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
-                outputPackage = mOptions.privateSymbols.value();
-            }
-
-            if (!writeJavaFile(&mFinalTable, actualPackage, outputPackage, options)) {
-                return 1;
-            }
-
-            for (const std::string& extraPackage : mOptions.extraJavaPackages) {
-                if (!writeJavaFile(&mFinalTable, actualPackage, extraPackage, options)) {
-                    return 1;
-                }
-            }
+          if (!writeManifestJavaFile(manifestXml.get())) {
+            error = true;
+          }
         }
 
-        if (!writeProguardFile(mOptions.generateProguardRulesPath, proguardKeepSet)) {
-            return 1;
+        if (mOptions.noXmlNamespaces) {
+          // PackageParser will fail if URIs are removed from
+          // AndroidManifest.xml.
+          XmlNamespaceRemover namespaceRemover(true /* keepUris */);
+          if (!namespaceRemover.consume(mContext, manifestXml.get())) {
+            error = true;
+          }
         }
-
-        if (!writeProguardFile(mOptions.generateMainDexProguardRulesPath, proguardMainDexKeepSet)) {
-            return 1;
-        }
-
-        if (mContext->verbose()) {
-            DebugPrintTableOptions debugPrintTableOptions;
-            debugPrintTableOptions.showSources = true;
-            Debug::printTable(&mFinalTable, debugPrintTableOptions);
-        }
-        return 0;
+      } else {
+        error = true;
+      }
     }
 
-private:
-    LinkOptions mOptions;
-    LinkContext* mContext;
-    ResourceTable mFinalTable;
+    if (error) {
+      mContext->getDiagnostics()->error(DiagMessage()
+                                        << "failed processing manifest");
+      return 1;
+    }
 
-    std::unique_ptr<TableMerger> mTableMerger;
+    if (!writeApk(archiveWriter.get(), &proguardKeepSet, manifestXml.get(),
+                  &mFinalTable)) {
+      return 1;
+    }
 
-    // A pointer to the FileCollection representing the filesystem (not archives).
-    std::unique_ptr<io::FileCollection> mFileCollection;
+    if (mOptions.generateJavaClassPath) {
+      JavaClassGeneratorOptions options;
+      options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
+      options.javadocAnnotations = mOptions.javadocAnnotations;
 
-    // A vector of IFileCollections. This is mainly here to keep ownership of the collections.
-    std::vector<std::unique_ptr<io::IFileCollection>> mCollections;
+      if (mOptions.staticLib || mOptions.generateNonFinalIds) {
+        options.useFinal = false;
+      }
 
-    // A vector of ResourceTables. This is here to retain ownership, so that the SymbolTable
-    // can use these.
-    std::vector<std::unique_ptr<ResourceTable>> mStaticTableIncludes;
+      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();
+      }
+
+      if (mOptions.privateSymbols) {
+        // If we defined a private symbols package, we only emit Public symbols
+        // to the original package, and private and public symbols to the
+        // private package.
+
+        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
+        if (!writeJavaFile(&mFinalTable, mContext->getCompilationPackage(),
+                           outputPackage, options)) {
+          return 1;
+        }
+
+        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
+        outputPackage = mOptions.privateSymbols.value();
+      }
+
+      if (!writeJavaFile(&mFinalTable, actualPackage, outputPackage, options)) {
+        return 1;
+      }
+
+      for (const std::string& extraPackage : mOptions.extraJavaPackages) {
+        if (!writeJavaFile(&mFinalTable, actualPackage, extraPackage,
+                           options)) {
+          return 1;
+        }
+      }
+    }
+
+    if (!writeProguardFile(mOptions.generateProguardRulesPath,
+                           proguardKeepSet)) {
+      return 1;
+    }
+
+    if (!writeProguardFile(mOptions.generateMainDexProguardRulesPath,
+                           proguardMainDexKeepSet)) {
+      return 1;
+    }
+
+    if (mContext->verbose()) {
+      DebugPrintTableOptions debugPrintTableOptions;
+      debugPrintTableOptions.showSources = true;
+      Debug::printTable(&mFinalTable, debugPrintTableOptions);
+    }
+    return 0;
+  }
+
+ private:
+  LinkOptions mOptions;
+  LinkContext* mContext;
+  ResourceTable mFinalTable;
+
+  std::unique_ptr<TableMerger> mTableMerger;
+
+  // A pointer to the FileCollection representing the filesystem (not archives).
+  std::unique_ptr<io::FileCollection> mFileCollection;
+
+  // A vector of IFileCollections. This is mainly here to keep ownership of the
+  // collections.
+  std::vector<std::unique_ptr<io::IFileCollection>> mCollections;
+
+  // A vector of ResourceTables. This is here to retain ownership, so that the
+  // SymbolTable
+  // can use these.
+  std::vector<std::unique_ptr<ResourceTable>> mStaticTableIncludes;
 };
 
 int link(const std::vector<StringPiece>& args) {
-    LinkContext context;
-    LinkOptions options;
-    std::vector<std::string> overlayArgList;
-    std::vector<std::string> extraJavaPackages;
-    Maybe<std::string> configs;
-    Maybe<std::string> preferredDensity;
-    Maybe<std::string> productList;
-    bool legacyXFlag = false;
-    bool requireLocalization = false;
-    bool verbose = false;
-    Maybe<std::string> stableIdFilePath;
-    std::vector<std::string> splitArgs;
-    Flags flags = Flags()
-            .requiredFlag("-o", "Output path", &options.outputPath)
-            .requiredFlag("--manifest", "Path to the Android manifest to build",
-                          &options.manifestPath)
-            .optionalFlagList("-I", "Adds an Android APK to link against", &options.includePaths)
-            .optionalFlagList("-R", "Compilation unit to link, using `overlay` semantics.\n"
-                              "The last conflicting resource given takes precedence.",
-                              &overlayArgList)
-            .optionalFlag("--java", "Directory in which to generate R.java",
-                          &options.generateJavaClassPath)
-            .optionalFlag("--proguard", "Output file for generated Proguard rules",
-                          &options.generateProguardRulesPath)
-            .optionalFlag("--proguard-main-dex",
-                          "Output file for generated Proguard rules for the main dex",
-                          &options.generateMainDexProguardRulesPath)
-            .optionalSwitch("--no-auto-version",
-                            "Disables automatic style and layout SDK versioning",
-                            &options.noAutoVersion)
-            .optionalSwitch("--no-version-vectors",
-                            "Disables automatic versioning of vector drawables. Use this only\n"
-                            "when building with vector drawable support library",
-                            &options.noVersionVectors)
-            .optionalSwitch("--no-resource-deduping", "Disables automatic deduping of resources with\n"
-                            "identical values across compatible configurations.",
-                            &options.noResourceDeduping)
-            .optionalSwitch("-x", "Legacy flag that specifies to use the package identifier 0x01",
-                            &legacyXFlag)
-            .optionalSwitch("-z", "Require localization of strings marked 'suggested'",
-                            &requireLocalization)
-            .optionalFlag("-c", "Comma separated list of configurations to include. The default\n"
-                                "is all configurations", &configs)
-            .optionalFlag("--preferred-density",
-                          "Selects the closest matching density and strips out all others.",
-                          &preferredDensity)
-            .optionalFlag("--product", "Comma separated list of product names to keep",
-                          &productList)
-            .optionalSwitch("--output-to-dir", "Outputs the APK contents to a directory specified "
-                            "by -o",
-                            &options.outputToDirectory)
-            .optionalSwitch("--no-xml-namespaces", "Removes XML namespace prefix and URI "
-                            "information from AndroidManifest.xml\nand XML binaries in res/*.",
-                            &options.noXmlNamespaces)
-            .optionalFlag("--min-sdk-version", "Default minimum SDK version to use for "
-                          "AndroidManifest.xml",
-                          &options.manifestFixerOptions.minSdkVersionDefault)
-            .optionalFlag("--target-sdk-version", "Default target SDK version to use for "
-                          "AndroidManifest.xml",
-                          &options.manifestFixerOptions.targetSdkVersionDefault)
-            .optionalFlag("--version-code", "Version code (integer) to inject into the "
-                          "AndroidManifest.xml if none is present",
-                          &options.manifestFixerOptions.versionCodeDefault)
-            .optionalFlag("--version-name", "Version name to inject into the AndroidManifest.xml "
-                          "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)
-            .optionalSwitch("--non-final-ids", "Generates R.java without the final modifier.\n"
-                            "This is implied when --static-lib is specified.",
-                            &options.generateNonFinalIds)
-            .optionalFlag("--stable-ids", "File containing a list of name to ID mapping.",
-                          &stableIdFilePath)
-            .optionalFlag("--emit-ids", "Emit a file at the given path with a list of name to ID\n"
-                          "mappings, suitable for use with --stable-ids.",
-                          &options.resourceIdMapPath)
-            .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",
-                          &options.privateSymbols)
-            .optionalFlag("--custom-package", "Custom Java package under which to generate R.java",
-                          &options.customJavaPackage)
-            .optionalFlagList("--extra-packages", "Generate the same R.java but with different "
-                              "package names",
-                              &extraJavaPackages)
-            .optionalFlagList("--add-javadoc-annotation", "Adds a JavaDoc annotation to all "
+  LinkContext context;
+  LinkOptions options;
+  std::vector<std::string> overlayArgList;
+  std::vector<std::string> extraJavaPackages;
+  Maybe<std::string> configs;
+  Maybe<std::string> preferredDensity;
+  Maybe<std::string> productList;
+  bool legacyXFlag = false;
+  bool requireLocalization = false;
+  bool verbose = false;
+  Maybe<std::string> stableIdFilePath;
+  std::vector<std::string> splitArgs;
+  Flags flags =
+      Flags()
+          .requiredFlag("-o", "Output path", &options.outputPath)
+          .requiredFlag("--manifest", "Path to the Android manifest to build",
+                        &options.manifestPath)
+          .optionalFlagList("-I", "Adds an Android APK to link against",
+                            &options.includePaths)
+          .optionalFlagList(
+              "-R",
+              "Compilation unit to link, using `overlay` semantics.\n"
+              "The last conflicting resource given takes precedence.",
+              &overlayArgList)
+          .optionalFlag("--java", "Directory in which to generate R.java",
+                        &options.generateJavaClassPath)
+          .optionalFlag("--proguard",
+                        "Output file for generated Proguard rules",
+                        &options.generateProguardRulesPath)
+          .optionalFlag(
+              "--proguard-main-dex",
+              "Output file for generated Proguard rules for the main dex",
+              &options.generateMainDexProguardRulesPath)
+          .optionalSwitch("--no-auto-version",
+                          "Disables automatic style and layout SDK versioning",
+                          &options.noAutoVersion)
+          .optionalSwitch("--no-version-vectors",
+                          "Disables automatic versioning of vector drawables. "
+                          "Use this only\n"
+                          "when building with vector drawable support library",
+                          &options.noVersionVectors)
+          .optionalSwitch("--no-resource-deduping",
+                          "Disables automatic deduping of resources with\n"
+                          "identical values across compatible configurations.",
+                          &options.noResourceDeduping)
+          .optionalSwitch(
+              "-x",
+              "Legacy flag that specifies to use the package identifier 0x01",
+              &legacyXFlag)
+          .optionalSwitch("-z",
+                          "Require localization of strings marked 'suggested'",
+                          &requireLocalization)
+          .optionalFlag(
+              "-c",
+              "Comma separated list of configurations to include. The default\n"
+              "is all configurations",
+              &configs)
+          .optionalFlag(
+              "--preferred-density",
+              "Selects the closest matching density and strips out all others.",
+              &preferredDensity)
+          .optionalFlag("--product",
+                        "Comma separated list of product names to keep",
+                        &productList)
+          .optionalSwitch("--output-to-dir",
+                          "Outputs the APK contents to a directory specified "
+                          "by -o",
+                          &options.outputToDirectory)
+          .optionalSwitch("--no-xml-namespaces",
+                          "Removes XML namespace prefix and URI "
+                          "information from AndroidManifest.xml\nand XML "
+                          "binaries in res/*.",
+                          &options.noXmlNamespaces)
+          .optionalFlag("--min-sdk-version",
+                        "Default minimum SDK version to use for "
+                        "AndroidManifest.xml",
+                        &options.manifestFixerOptions.minSdkVersionDefault)
+          .optionalFlag("--target-sdk-version",
+                        "Default target SDK version to use for "
+                        "AndroidManifest.xml",
+                        &options.manifestFixerOptions.targetSdkVersionDefault)
+          .optionalFlag("--version-code",
+                        "Version code (integer) to inject into the "
+                        "AndroidManifest.xml if none is present",
+                        &options.manifestFixerOptions.versionCodeDefault)
+          .optionalFlag("--version-name",
+                        "Version name to inject into the AndroidManifest.xml "
+                        "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)
+          .optionalSwitch("--non-final-ids",
+                          "Generates R.java without the final modifier.\n"
+                          "This is implied when --static-lib is specified.",
+                          &options.generateNonFinalIds)
+          .optionalFlag("--stable-ids",
+                        "File containing a list of name to ID mapping.",
+                        &stableIdFilePath)
+          .optionalFlag(
+              "--emit-ids",
+              "Emit a file at the given path with a list of name to ID\n"
+              "mappings, suitable for use with --stable-ids.",
+              &options.resourceIdMapPath)
+          .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",
+                        &options.privateSymbols)
+          .optionalFlag("--custom-package",
+                        "Custom Java package under which to generate R.java",
+                        &options.customJavaPackage)
+          .optionalFlagList("--extra-packages",
+                            "Generate the same R.java but with different "
+                            "package names",
+                            &extraJavaPackages)
+          .optionalFlagList("--add-javadoc-annotation",
+                            "Adds a JavaDoc annotation to all "
                             "generated Java classes",
                             &options.javadocAnnotations)
-            .optionalSwitch("--auto-add-overlay", "Allows the addition of new resources in "
-                            "overlays without <add-resource> tags",
-                            &options.autoAddOverlay)
-            .optionalFlag("--rename-manifest-package", "Renames the package in AndroidManifest.xml",
-                          &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",
-                          &options.manifestFixerOptions.renameInstrumentationTargetPackage)
-            .optionalFlagList("-0", "File extensions not to compress",
-                              &options.extensionsToNotCompress)
-            .optionalFlagList("--split", "Split resources matching a set of configs out to a "
-                              "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]]",
-                              &splitArgs)
-            .optionalSwitch("-v", "Enables verbose logging",
-                            &verbose);
+          .optionalSwitch("--auto-add-overlay",
+                          "Allows the addition of new resources in "
+                          "overlays without <add-resource> tags",
+                          &options.autoAddOverlay)
+          .optionalFlag("--rename-manifest-package",
+                        "Renames the package in AndroidManifest.xml",
+                        &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",
+              &options.manifestFixerOptions.renameInstrumentationTargetPackage)
+          .optionalFlagList("-0", "File extensions not to compress",
+                            &options.extensionsToNotCompress)
+          .optionalFlagList(
+              "--split",
+              "Split resources matching a set of configs out to a "
+              "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]]",
+              &splitArgs)
+          .optionalSwitch("-v", "Enables verbose logging", &verbose);
 
-    if (!flags.parse("aapt2 link", args, &std::cerr)) {
+  if (!flags.parse("aapt2 link", args, &std::cerr)) {
+    return 1;
+  }
+
+  // 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(arg, "@")) {
+      const std::string path = arg.substr(1, arg.size() - 1);
+      std::string error;
+      if (!file::appendArgsFromFile(path, &argList, &error)) {
+        context.getDiagnostics()->error(DiagMessage(path) << error);
         return 1;
+      }
+    } else {
+      argList.push_back(arg);
+    }
+  }
+
+  // Expand all argument-files passed to -R.
+  for (const std::string& arg : overlayArgList) {
+    if (util::stringStartsWith(arg, "@")) {
+      const std::string path = arg.substr(1, arg.size() - 1);
+      std::string error;
+      if (!file::appendArgsFromFile(path, &options.overlayFiles, &error)) {
+        context.getDiagnostics()->error(DiagMessage(path) << error);
+        return 1;
+      }
+    } else {
+      options.overlayFiles.push_back(arg);
+    }
+  }
+
+  if (verbose) {
+    context.setVerbose(verbose);
+  }
+
+  // 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(package.toString());
+    }
+  }
+
+  if (productList) {
+    for (StringPiece product : util::tokenize(productList.value(), ',')) {
+      if (product != "" && product != "default") {
+        options.products.insert(product.toString());
+      }
+    }
+  }
+
+  AxisConfigFilter filter;
+  if (configs) {
+    for (const StringPiece& configStr : util::tokenize(configs.value(), ',')) {
+      ConfigDescription config;
+      LocaleValue lv;
+      if (lv.initFromFilterString(configStr)) {
+        lv.writeTo(&config);
+      } else if (!ConfigDescription::parse(configStr, &config)) {
+        context.getDiagnostics()->error(DiagMessage() << "invalid config '"
+                                                      << configStr
+                                                      << "' for -c option");
+        return 1;
+      }
+
+      if (config.density != 0) {
+        context.getDiagnostics()->warn(DiagMessage() << "ignoring density '"
+                                                     << config
+                                                     << "' for -c option");
+      } else {
+        filter.addConfig(config);
+      }
     }
 
-    // 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(arg, "@")) {
-            const std::string path = arg.substr(1, arg.size() - 1);
-            std::string error;
-            if (!file::appendArgsFromFile(path, &argList, &error)) {
-                context.getDiagnostics()->error(DiagMessage(path) << error);
-                return 1;
-            }
-        } else {
-            argList.push_back(arg);
-        }
+    options.tableSplitterOptions.configFilter = &filter;
+  }
+
+  if (preferredDensity) {
+    ConfigDescription preferredDensityConfig;
+    if (!ConfigDescription::parse(preferredDensity.value(),
+                                  &preferredDensityConfig)) {
+      context.getDiagnostics()->error(
+          DiagMessage() << "invalid density '" << preferredDensity.value()
+                        << "' for --preferred-density option");
+      return 1;
     }
 
-    // Expand all argument-files passed to -R.
-    for (const std::string& arg : overlayArgList) {
-        if (util::stringStartsWith(arg, "@")) {
-            const std::string path = arg.substr(1, arg.size() - 1);
-            std::string error;
-            if (!file::appendArgsFromFile(path, &options.overlayFiles, &error)) {
-                context.getDiagnostics()->error(DiagMessage(path) << error);
-                return 1;
-            }
-        } else {
-            options.overlayFiles.push_back(arg);
-        }
+    // Clear the version that can be automatically added.
+    preferredDensityConfig.sdkVersion = 0;
+
+    if (preferredDensityConfig.diff(ConfigDescription::defaultConfig()) !=
+        ConfigDescription::CONFIG_DENSITY) {
+      context.getDiagnostics()->error(
+          DiagMessage() << "invalid preferred density '"
+                        << preferredDensity.value() << "'. "
+                        << "Preferred density must only be a density value");
+      return 1;
     }
+    options.tableSplitterOptions.preferredDensity =
+        preferredDensityConfig.density;
+  }
 
-    if (verbose) {
-        context.setVerbose(verbose);
+  if (!options.staticLib && stableIdFilePath) {
+    if (!loadStableIdMap(context.getDiagnostics(), stableIdFilePath.value(),
+                         &options.stableIdMap)) {
+      return 1;
     }
+  }
 
-    // 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(package.toString());
-        }
+  // Populate some default no-compress extensions that are already compressed.
+  options.extensionsToNotCompress.insert(
+      {".jpg",   ".jpeg", ".png",  ".gif", ".wav",  ".mp2",  ".mp3",  ".ogg",
+       ".aac",   ".mpg",  ".mpeg", ".mid", ".midi", ".smf",  ".jet",  ".rtttl",
+       ".imy",   ".xmf",  ".mp4",  ".m4a", ".m4v",  ".3gp",  ".3gpp", ".3g2",
+       ".3gpp2", ".amr",  ".awb",  ".wma", ".wmv",  ".webm", ".mkv"});
+
+  // Parse the split parameters.
+  for (const std::string& splitArg : splitArgs) {
+    options.splitPaths.push_back({});
+    options.splitConstraints.push_back({});
+    if (!parseSplitParameter(splitArg, context.getDiagnostics(),
+                             &options.splitPaths.back(),
+                             &options.splitConstraints.back())) {
+      return 1;
     }
+  }
 
-    if (productList) {
-        for (StringPiece product : util::tokenize(productList.value(), ',')) {
-            if (product != "" && product != "default") {
-                options.products.insert(product.toString());
-            }
-        }
-    }
+  // Turn off auto versioning for static-libs.
+  if (options.staticLib) {
+    options.noAutoVersion = true;
+    options.noVersionVectors = true;
+  }
 
-    AxisConfigFilter filter;
-    if (configs) {
-        for (const StringPiece& configStr : util::tokenize(configs.value(), ',')) {
-            ConfigDescription config;
-            LocaleValue lv;
-            if (lv.initFromFilterString(configStr)) {
-                lv.writeTo(&config);
-            } else if (!ConfigDescription::parse(configStr, &config)) {
-                context.getDiagnostics()->error(
-                        DiagMessage() << "invalid config '" << configStr << "' for -c option");
-                return 1;
-            }
-
-            if (config.density != 0) {
-                context.getDiagnostics()->warn(
-                        DiagMessage() << "ignoring density '" << config << "' for -c option");
-            } else {
-                filter.addConfig(config);
-            }
-        }
-
-        options.tableSplitterOptions.configFilter = &filter;
-    }
-
-    if (preferredDensity) {
-        ConfigDescription preferredDensityConfig;
-        if (!ConfigDescription::parse(preferredDensity.value(), &preferredDensityConfig)) {
-            context.getDiagnostics()->error(DiagMessage() << "invalid density '"
-                                            << preferredDensity.value()
-                                            << "' for --preferred-density option");
-            return 1;
-        }
-
-        // Clear the version that can be automatically added.
-        preferredDensityConfig.sdkVersion = 0;
-
-        if (preferredDensityConfig.diff(ConfigDescription::defaultConfig())
-                != ConfigDescription::CONFIG_DENSITY) {
-            context.getDiagnostics()->error(DiagMessage() << "invalid preferred density '"
-                                            << preferredDensity.value() << "'. "
-                                            << "Preferred density must only be a density value");
-            return 1;
-        }
-        options.tableSplitterOptions.preferredDensity = preferredDensityConfig.density;
-    }
-
-    if (!options.staticLib && stableIdFilePath) {
-        if (!loadStableIdMap(context.getDiagnostics(), stableIdFilePath.value(),
-                             &options.stableIdMap)) {
-            return 1;
-        }
-    }
-
-    // Populate some default no-compress extensions that are already compressed.
-    options.extensionsToNotCompress.insert({
-            ".jpg", ".jpeg", ".png", ".gif",
-            ".wav", ".mp2", ".mp3", ".ogg", ".aac",
-            ".mpg", ".mpeg", ".mid", ".midi", ".smf", ".jet",
-            ".rtttl", ".imy", ".xmf", ".mp4", ".m4a",
-            ".m4v", ".3gp", ".3gpp", ".3g2", ".3gpp2",
-            ".amr", ".awb", ".wma", ".wmv", ".webm", ".mkv"});
-
-    // Parse the split parameters.
-    for (const std::string& splitArg : splitArgs) {
-        options.splitPaths.push_back({});
-        options.splitConstraints.push_back({});
-        if (!parseSplitParameter(splitArg, context.getDiagnostics(), &options.splitPaths.back(),
-                                 &options.splitConstraints.back())) {
-            return 1;
-        }
-    }
-
-    // Turn off auto versioning for static-libs.
-    if (options.staticLib) {
-        options.noAutoVersion = true;
-        options.noVersionVectors = true;
-    }
-
-    LinkCommand cmd(&context, options);
-    return cmd.run(argList);
+  LinkCommand cmd(&context, options);
+  return cmd.run(argList);
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/Linkers.h b/tools/aapt2/link/Linkers.h
index ce455da..f40c0e8 100644
--- a/tools/aapt2/link/Linkers.h
+++ b/tools/aapt2/link/Linkers.h
@@ -30,106 +30,121 @@
 struct ConfigDescription;
 
 /**
- * Defines the location in which a value exists. This determines visibility of other
+ * Defines the location in which a value exists. This determines visibility of
+ * other
  * package's private symbols.
  */
 struct CallSite {
-    ResourceNameRef resource;
+  ResourceNameRef resource;
 };
 
 /**
- * Determines whether a versioned resource should be created. If a versioned resource already
+ * Determines whether a versioned resource should be created. If a versioned
+ * resource already
  * exists, it takes precedence.
  */
-bool shouldGenerateVersionedResource(const ResourceEntry* entry, const ConfigDescription& config,
+bool shouldGenerateVersionedResource(const ResourceEntry* entry,
+                                     const ConfigDescription& config,
                                      const int sdkVersionToGenerate);
 
 class AutoVersioner : public IResourceTableConsumer {
-public:
-    bool consume(IAaptContext* context, ResourceTable* table) override;
+ public:
+  bool consume(IAaptContext* context, ResourceTable* table) override;
 };
 
 class XmlAutoVersioner : public IXmlResourceConsumer {
-public:
-    bool consume(IAaptContext* context, xml::XmlResource* resource) override;
+ public:
+  bool consume(IAaptContext* context, xml::XmlResource* resource) override;
 };
 
 class VersionCollapser : public IResourceTableConsumer {
-public:
-    bool consume(IAaptContext* context, ResourceTable* table) override;
+ public:
+  bool consume(IAaptContext* context, ResourceTable* table) override;
 };
 
 /**
  * Removes duplicated key-value entries from dominated resources.
  */
 class ResourceDeduper : public IResourceTableConsumer {
-public:
-    bool consume(IAaptContext* context, ResourceTable* table) override;
+ public:
+  bool consume(IAaptContext* context, ResourceTable* table) override;
 };
 
 /**
- * If any attribute resource values are defined as public, this consumer will move all private
- * attribute resource values to a private ^private-attr type, avoiding backwards compatibility
+ * If any attribute resource values are defined as public, this consumer will
+ * move all private
+ * attribute resource values to a private ^private-attr type, avoiding backwards
+ * compatibility
  * issues with new apps running on old platforms.
  *
- * The Android platform ignores resource attributes it doesn't recognize, so an app developer can
- * use new attributes in their layout XML files without worrying about versioning. This assumption
- * actually breaks on older platforms. OEMs may add private attributes that are used internally.
- * AAPT originally assigned all private attributes IDs immediately proceeding the public attributes'
+ * The Android platform ignores resource attributes it doesn't recognize, so an
+ * app developer can
+ * use new attributes in their layout XML files without worrying about
+ * versioning. This assumption
+ * actually breaks on older platforms. OEMs may add private attributes that are
+ * used internally.
+ * AAPT originally assigned all private attributes IDs immediately proceeding
+ * the public attributes'
  * IDs.
  *
- * This means that on a newer Android platform, an ID previously assigned to a private attribute
+ * This means that on a newer Android platform, an ID previously assigned to a
+ * private attribute
  * may end up assigned to a public attribute.
  *
- * App developers assume using the newer attribute is safe on older platforms because it will
- * be ignored. Instead, the platform thinks the new attribute is an older, private attribute and
- * will interpret it as such. This leads to unintended styling and exceptions thrown due to
+ * App developers assume using the newer attribute is safe on older platforms
+ * because it will
+ * be ignored. Instead, the platform thinks the new attribute is an older,
+ * private attribute and
+ * will interpret it as such. This leads to unintended styling and exceptions
+ * thrown due to
  * unexpected types.
  *
- * By moving the private attributes to a completely different type, this ID conflict will never
+ * By moving the private attributes to a completely different type, this ID
+ * conflict will never
  * occur.
  */
 struct PrivateAttributeMover : public IResourceTableConsumer {
-    bool consume(IAaptContext* context, ResourceTable* table) override;
+  bool consume(IAaptContext* context, ResourceTable* table) override;
 };
 
 /**
  * Removes namespace nodes and URI information from the XmlResource.
  *
- * Once an XmlResource is processed by this consumer, it is no longer able to have its attributes
- * parsed. As such, this XmlResource must have already been processed by XmlReferenceLinker.
+ * Once an XmlResource is processed by this consumer, it is no longer able to
+ * have its attributes
+ * parsed. As such, this XmlResource must have already been processed by
+ * XmlReferenceLinker.
  */
 class XmlNamespaceRemover : public IXmlResourceConsumer {
-private:
-    bool mKeepUris;
+ private:
+  bool mKeepUris;
 
-public:
-    XmlNamespaceRemover(bool keepUris = false) : mKeepUris(keepUris) {
-    };
+ public:
+  XmlNamespaceRemover(bool keepUris = false) : mKeepUris(keepUris){};
 
-    bool consume(IAaptContext* context, xml::XmlResource* resource) override;
+  bool consume(IAaptContext* context, xml::XmlResource* resource) override;
 };
 
 /**
- * Resolves attributes in the XmlResource and compiles string values to resource values.
+ * Resolves attributes in the XmlResource and compiles string values to resource
+ * values.
  * Once an XmlResource is processed by this linker, it is ready to be flattened.
  */
 class XmlReferenceLinker : public IXmlResourceConsumer {
-private:
-    std::set<int> mSdkLevelsFound;
+ private:
+  std::set<int> mSdkLevelsFound;
 
-public:
-    bool consume(IAaptContext* context, xml::XmlResource* resource) override;
+ public:
+  bool consume(IAaptContext* context, xml::XmlResource* resource) override;
 
-    /**
-     * Once the XmlResource has been consumed, this returns the various SDK levels in which
-     * framework attributes used within the XML document were defined.
-     */
-    inline const std::set<int>& getSdkLevels() const {
-        return mSdkLevelsFound;
-    }
+  /**
+   * Once the XmlResource has been consumed, this returns the various SDK levels
+   * in which
+   * framework attributes used within the XML document were defined.
+   */
+  inline const std::set<int>& getSdkLevels() const { return mSdkLevelsFound; }
 };
 
-} // namespace aapt
+}  // namespace aapt
 
 #endif /* AAPT_LINKER_LINKERS_H */
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 45f5acd..3c9298b 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "ResourceUtils.h"
 #include "link/ManifestFixer.h"
+#include "ResourceUtils.h"
 #include "util/Util.h"
 #include "xml/XmlActionExecutor.h"
 #include "xml/XmlDom.h"
@@ -25,295 +25,310 @@
 namespace aapt {
 
 /**
- * This is how PackageManager builds class names from AndroidManifest.xml entries.
+ * This is how PackageManager builds class names from AndroidManifest.xml
+ * entries.
  */
 static bool nameIsJavaClassName(xml::Element* el, xml::Attribute* attr,
                                 SourcePathDiagnostics* diag) {
-    // 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::string> fullyQualifiedClassName =
-            util::getFullyQualifiedClassName("a", attr->value);
+  // 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::string> fullyQualifiedClassName =
+      util::getFullyQualifiedClassName("a", attr->value);
 
-    StringPiece qualifiedClassName = fullyQualifiedClassName
-            ? fullyQualifiedClassName.value() : attr->value;
+  StringPiece qualifiedClassName =
+      fullyQualifiedClassName ? fullyQualifiedClassName.value() : attr->value;
 
-    if (!util::isJavaClassName(qualifiedClassName)) {
-        diag->error(DiagMessage(el->lineNumber)
-                    << "attribute 'android:name' in <"
-                    << el->name << "> tag must be a valid Java class name");
-        return false;
-    }
-    return true;
-}
-
-static bool optionalNameIsJavaClassName(xml::Element* el, SourcePathDiagnostics* diag) {
-    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, "name")) {
-        return nameIsJavaClassName(el, attr, diag);
-    }
+  if (!util::isJavaClassName(qualifiedClassName)) {
     diag->error(DiagMessage(el->lineNumber)
-                << "<" << el->name << "> is missing attribute 'android:name'");
+                << "attribute 'android:name' in <" << el->name
+                << "> tag must be a valid Java class name");
     return false;
+  }
+  return true;
+}
+
+static bool optionalNameIsJavaClassName(xml::Element* el,
+                                        SourcePathDiagnostics* diag) {
+  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, "name")) {
+    return nameIsJavaClassName(el, attr, diag);
+  }
+  diag->error(DiagMessage(el->lineNumber)
+              << "<" << el->name << "> is missing attribute 'android:name'");
+  return false;
 }
 
 static bool verifyManifest(xml::Element* el, SourcePathDiagnostics* diag) {
-    xml::Attribute* attr = el->findAttribute({}, "package");
-    if (!attr) {
-        diag->error(DiagMessage(el->lineNumber) << "<manifest> tag is missing 'package' attribute");
-        return false;
-    } else if (ResourceUtils::isReference(attr->value)) {
-        diag->error(DiagMessage(el->lineNumber)
-                    << "attribute 'package' in <manifest> tag must not be a reference");
-        return false;
-    } else if (!util::isJavaPackageName(attr->value)) {
-        diag->error(DiagMessage(el->lineNumber)
-                    << "attribute 'package' in <manifest> tag is not a valid Java package name: '"
-                    << attr->value << "'");
-        return false;
-    }
-    return true;
+  xml::Attribute* attr = el->findAttribute({}, "package");
+  if (!attr) {
+    diag->error(DiagMessage(el->lineNumber)
+                << "<manifest> tag is missing 'package' attribute");
+    return false;
+  } else if (ResourceUtils::isReference(attr->value)) {
+    diag->error(
+        DiagMessage(el->lineNumber)
+        << "attribute 'package' in <manifest> tag must not be a reference");
+    return false;
+  } else if (!util::isJavaPackageName(attr->value)) {
+    diag->error(DiagMessage(el->lineNumber)
+                << "attribute 'package' in <manifest> tag is not a valid Java "
+                   "package name: '"
+                << attr->value << "'");
+    return false;
+  }
+  return true;
 }
 
 /**
- * The coreApp attribute in <manifest> is not a regular AAPT attribute, so type checking on it
+ * The coreApp attribute in <manifest> is not a regular AAPT attribute, so type
+ * checking on it
  * is manual.
  */
 static bool fixCoreAppAttribute(xml::Element* el, SourcePathDiagnostics* diag) {
-    if (xml::Attribute* attr = el->findAttribute("", "coreApp")) {
-        std::unique_ptr<BinaryPrimitive> result = ResourceUtils::tryParseBool(attr->value);
-        if (!result) {
-            diag->error(DiagMessage(el->lineNumber) << "attribute coreApp must be a boolean");
-            return false;
-        }
-        attr->compiledValue = std::move(result);
+  if (xml::Attribute* attr = el->findAttribute("", "coreApp")) {
+    std::unique_ptr<BinaryPrimitive> result =
+        ResourceUtils::tryParseBool(attr->value);
+    if (!result) {
+      diag->error(DiagMessage(el->lineNumber)
+                  << "attribute coreApp must be a boolean");
+      return false;
     }
-    return true;
+    attr->compiledValue = std::move(result);
+  }
+  return true;
 }
 
-bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag) {
-    // First verify some options.
-    if (mOptions.renameManifestPackage) {
-        if (!util::isJavaPackageName(mOptions.renameManifestPackage.value())) {
-            diag->error(DiagMessage() << "invalid manifest package override '"
-                        << mOptions.renameManifestPackage.value() << "'");
-            return false;
-        }
+bool ManifestFixer::buildRules(xml::XmlActionExecutor* executor,
+                               IDiagnostics* diag) {
+  // First verify some options.
+  if (mOptions.renameManifestPackage) {
+    if (!util::isJavaPackageName(mOptions.renameManifestPackage.value())) {
+      diag->error(DiagMessage() << "invalid manifest package override '"
+                                << mOptions.renameManifestPackage.value()
+                                << "'");
+      return false;
+    }
+  }
+
+  if (mOptions.renameInstrumentationTargetPackage) {
+    if (!util::isJavaPackageName(
+            mOptions.renameInstrumentationTargetPackage.value())) {
+      diag->error(DiagMessage()
+                  << "invalid instrumentation target package override '"
+                  << mOptions.renameInstrumentationTargetPackage.value()
+                  << "'");
+      return false;
+    }
+  }
+
+  // Common intent-filter actions.
+  xml::XmlNodeAction intentFilterAction;
+  intentFilterAction["action"];
+  intentFilterAction["category"];
+  intentFilterAction["data"];
+
+  // Common meta-data actions.
+  xml::XmlNodeAction metaDataAction;
+
+  // Manifest actions.
+  xml::XmlNodeAction& manifestAction = (*executor)["manifest"];
+  manifestAction.action(verifyManifest);
+  manifestAction.action(fixCoreAppAttribute);
+  manifestAction.action([&](xml::Element* el) -> bool {
+    if (mOptions.versionNameDefault) {
+      if (el->findAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
+        el->attributes.push_back(
+            xml::Attribute{xml::kSchemaAndroid, "versionName",
+                           mOptions.versionNameDefault.value()});
+      }
     }
 
-    if (mOptions.renameInstrumentationTargetPackage) {
-        if (!util::isJavaPackageName(mOptions.renameInstrumentationTargetPackage.value())) {
-            diag->error(DiagMessage() << "invalid instrumentation target package override '"
-                        << mOptions.renameInstrumentationTargetPackage.value() << "'");
-            return false;
-        }
+    if (mOptions.versionCodeDefault) {
+      if (el->findAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
+        el->attributes.push_back(
+            xml::Attribute{xml::kSchemaAndroid, "versionCode",
+                           mOptions.versionCodeDefault.value()});
+      }
     }
-
-    // Common intent-filter actions.
-    xml::XmlNodeAction intentFilterAction;
-    intentFilterAction["action"];
-    intentFilterAction["category"];
-    intentFilterAction["data"];
-
-    // Common meta-data actions.
-    xml::XmlNodeAction metaDataAction;
-
-    // Manifest actions.
-    xml::XmlNodeAction& manifestAction = (*executor)["manifest"];
-    manifestAction.action(verifyManifest);
-    manifestAction.action(fixCoreAppAttribute);
-    manifestAction.action([&](xml::Element* el) -> bool {
-        if (mOptions.versionNameDefault) {
-            if (el->findAttribute(xml::kSchemaAndroid, "versionName") == nullptr) {
-                el->attributes.push_back(xml::Attribute{
-                        xml::kSchemaAndroid,
-                        "versionName",
-                        mOptions.versionNameDefault.value() });
-            }
-        }
-
-        if (mOptions.versionCodeDefault) {
-            if (el->findAttribute(xml::kSchemaAndroid, "versionCode") == nullptr) {
-                el->attributes.push_back(xml::Attribute{
-                        xml::kSchemaAndroid,
-                        "versionCode",
-                        mOptions.versionCodeDefault.value() });
-            }
-        }
-        return true;
-    });
-
-    // Meta tags.
-    manifestAction["eat-comment"];
-
-    // Uses-sdk actions.
-    manifestAction["uses-sdk"].action([&](xml::Element* el) -> bool {
-        if (mOptions.minSdkVersionDefault &&
-                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, "minSdkVersion",
-                    mOptions.minSdkVersionDefault.value() });
-        }
-
-        if (mOptions.targetSdkVersionDefault &&
-                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, "targetSdkVersion",
-                    mOptions.targetSdkVersionDefault.value() });
-        }
-        return true;
-    });
-
-    // Instrumentation actions.
-    manifestAction["instrumentation"].action([&](xml::Element* el) -> bool {
-        if (!mOptions.renameInstrumentationTargetPackage) {
-            return true;
-        }
-
-        if (xml::Attribute* attr = el->findAttribute(xml::kSchemaAndroid, "targetPackage")) {
-            attr->value = mOptions.renameInstrumentationTargetPackage.value();
-        }
-        return true;
-    });
-
-    manifestAction["original-package"];
-    manifestAction["protected-broadcast"];
-    manifestAction["uses-permission"];
-    manifestAction["permission"];
-    manifestAction["permission-tree"];
-    manifestAction["permission-group"];
-
-    manifestAction["uses-configuration"];
-    manifestAction["uses-feature"];
-    manifestAction["supports-screens"];
-
-    manifestAction["compatible-screens"];
-    manifestAction["compatible-screens"]["screen"];
-
-    manifestAction["supports-gl-texture"];
-
-    // Application actions.
-    xml::XmlNodeAction& applicationAction = manifestAction["application"];
-    applicationAction.action(optionalNameIsJavaClassName);
-
-    // Uses library actions.
-    applicationAction["uses-library"];
-
-    // Meta-data.
-    applicationAction["meta-data"] = metaDataAction;
-
-    // Activity actions.
-    applicationAction["activity"].action(requiredNameIsJavaClassName);
-    applicationAction["activity"]["intent-filter"] = intentFilterAction;
-    applicationAction["activity"]["meta-data"] = metaDataAction;
-
-    // Activity alias actions.
-    applicationAction["activity-alias"]["intent-filter"] = intentFilterAction;
-    applicationAction["activity-alias"]["meta-data"] = metaDataAction;
-
-    // Service actions.
-    applicationAction["service"].action(requiredNameIsJavaClassName);
-    applicationAction["service"]["intent-filter"] = intentFilterAction;
-    applicationAction["service"]["meta-data"] = metaDataAction;
-
-    // Receiver actions.
-    applicationAction["receiver"].action(requiredNameIsJavaClassName);
-    applicationAction["receiver"]["intent-filter"] = intentFilterAction;
-    applicationAction["receiver"]["meta-data"] = metaDataAction;
-
-    // Provider actions.
-    applicationAction["provider"].action(requiredNameIsJavaClassName);
-    applicationAction["provider"]["intent-filter"] = intentFilterAction;
-    applicationAction["provider"]["meta-data"] = metaDataAction;
-    applicationAction["provider"]["grant-uri-permissions"];
-    applicationAction["provider"]["path-permissions"];
-
     return true;
+  });
+
+  // Meta tags.
+  manifestAction["eat-comment"];
+
+  // Uses-sdk actions.
+  manifestAction["uses-sdk"].action([&](xml::Element* el) -> bool {
+    if (mOptions.minSdkVersionDefault &&
+        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, "minSdkVersion",
+                         mOptions.minSdkVersionDefault.value()});
+    }
+
+    if (mOptions.targetSdkVersionDefault &&
+        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, "targetSdkVersion",
+                         mOptions.targetSdkVersionDefault.value()});
+    }
+    return true;
+  });
+
+  // Instrumentation actions.
+  manifestAction["instrumentation"].action([&](xml::Element* el) -> bool {
+    if (!mOptions.renameInstrumentationTargetPackage) {
+      return true;
+    }
+
+    if (xml::Attribute* attr =
+            el->findAttribute(xml::kSchemaAndroid, "targetPackage")) {
+      attr->value = mOptions.renameInstrumentationTargetPackage.value();
+    }
+    return true;
+  });
+
+  manifestAction["original-package"];
+  manifestAction["protected-broadcast"];
+  manifestAction["uses-permission"];
+  manifestAction["permission"];
+  manifestAction["permission-tree"];
+  manifestAction["permission-group"];
+
+  manifestAction["uses-configuration"];
+  manifestAction["uses-feature"];
+  manifestAction["supports-screens"];
+
+  manifestAction["compatible-screens"];
+  manifestAction["compatible-screens"]["screen"];
+
+  manifestAction["supports-gl-texture"];
+
+  // Application actions.
+  xml::XmlNodeAction& applicationAction = manifestAction["application"];
+  applicationAction.action(optionalNameIsJavaClassName);
+
+  // Uses library actions.
+  applicationAction["uses-library"];
+
+  // Meta-data.
+  applicationAction["meta-data"] = metaDataAction;
+
+  // Activity actions.
+  applicationAction["activity"].action(requiredNameIsJavaClassName);
+  applicationAction["activity"]["intent-filter"] = intentFilterAction;
+  applicationAction["activity"]["meta-data"] = metaDataAction;
+
+  // Activity alias actions.
+  applicationAction["activity-alias"]["intent-filter"] = intentFilterAction;
+  applicationAction["activity-alias"]["meta-data"] = metaDataAction;
+
+  // Service actions.
+  applicationAction["service"].action(requiredNameIsJavaClassName);
+  applicationAction["service"]["intent-filter"] = intentFilterAction;
+  applicationAction["service"]["meta-data"] = metaDataAction;
+
+  // Receiver actions.
+  applicationAction["receiver"].action(requiredNameIsJavaClassName);
+  applicationAction["receiver"]["intent-filter"] = intentFilterAction;
+  applicationAction["receiver"]["meta-data"] = metaDataAction;
+
+  // Provider actions.
+  applicationAction["provider"].action(requiredNameIsJavaClassName);
+  applicationAction["provider"]["intent-filter"] = intentFilterAction;
+  applicationAction["provider"]["meta-data"] = metaDataAction;
+  applicationAction["provider"]["grant-uri-permissions"];
+  applicationAction["provider"]["path-permissions"];
+
+  return true;
 }
 
 class FullyQualifiedClassNameVisitor : public xml::Visitor {
-public:
-    using xml::Visitor::visit;
+ public:
+  using xml::Visitor::visit;
 
-    explicit FullyQualifiedClassNameVisitor(const StringPiece& 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::string> newValue =
-                        util::getFullyQualifiedClassName(mPackage, attr.value)) {
-                    attr.value = std::move(newValue.value());
-                }
-            }
+  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::string> newValue =
+                util::getFullyQualifiedClassName(mPackage, attr.value)) {
+          attr.value = std::move(newValue.value());
         }
-
-        // Super implementation to iterate over the children.
-        xml::Visitor::visit(el);
+      }
     }
 
-private:
-    StringPiece mPackage;
-    std::unordered_set<StringPiece> mClassAttributes = { "name" };
+    // Super implementation to iterate over the children.
+    xml::Visitor::visit(el);
+  }
+
+ private:
+  StringPiece mPackage;
+  std::unordered_set<StringPiece> mClassAttributes = {"name"};
 };
 
-static bool renameManifestPackage(const StringPiece& packageOverride, xml::Element* manifestEl) {
-    xml::Attribute* attr = manifestEl->findAttribute({}, "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);
+  // We've already verified that the manifest element is present, with a package
+  // name specified.
+  assert(attr);
 
-    std::string originalPackage = std::move(attr->value);
-    attr->value = packageOverride.toString();
+  std::string originalPackage = std::move(attr->value);
+  attr->value = packageOverride.toString();
 
-    FullyQualifiedClassNameVisitor visitor(originalPackage);
-    manifestEl->accept(&visitor);
-    return true;
+  FullyQualifiedClassNameVisitor visitor(originalPackage);
+  manifestEl->accept(&visitor);
+  return true;
 }
 
 bool ManifestFixer::consume(IAaptContext* context, xml::XmlResource* doc) {
-    xml::Element* root = xml::findRootElement(doc->root.get());
-    if (!root || !root->namespaceUri.empty() || root->name != "manifest") {
-        context->getDiagnostics()->error(DiagMessage(doc->file.source)
-                                         << "root tag must be <manifest>");
-        return false;
-    }
+  xml::Element* root = xml::findRootElement(doc->root.get());
+  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({}, "uses-sdk") == nullptr) {
-        // Auto insert a <uses-sdk> element.
-        std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>();
-        usesSdk->name = "uses-sdk";
-        root->addChild(std::move(usesSdk));
-    }
+  if ((mOptions.minSdkVersionDefault || mOptions.targetSdkVersionDefault) &&
+      root->findChild({}, "uses-sdk") == nullptr) {
+    // Auto insert a <uses-sdk> element.
+    std::unique_ptr<xml::Element> usesSdk = util::make_unique<xml::Element>();
+    usesSdk->name = "uses-sdk";
+    root->addChild(std::move(usesSdk));
+  }
 
-    xml::XmlActionExecutor executor;
-    if (!buildRules(&executor, context->getDiagnostics())) {
-        return false;
-    }
+  xml::XmlActionExecutor executor;
+  if (!buildRules(&executor, context->getDiagnostics())) {
+    return false;
+  }
 
-    if (!executor.execute(xml::XmlActionExecutorPolicy::Whitelist, context->getDiagnostics(),
-                          doc)) {
-        return false;
-    }
+  if (!executor.execute(xml::XmlActionExecutorPolicy::Whitelist,
+                        context->getDiagnostics(), doc)) {
+    return false;
+  }
 
-    if (mOptions.renameManifestPackage) {
-        // Rename manifest package outside of the XmlActionExecutor.
-        // We need to extract the old package name and FullyQualify all class names.
-        if (!renameManifestPackage(mOptions.renameManifestPackage.value(), root)) {
-            return false;
-        }
+  if (mOptions.renameManifestPackage) {
+    // Rename manifest package outside of the XmlActionExecutor.
+    // We need to extract the old package name and FullyQualify all class names.
+    if (!renameManifestPackage(mOptions.renameManifestPackage.value(), root)) {
+      return false;
     }
-    return true;
+  }
+  return true;
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/ManifestFixer.h b/tools/aapt2/link/ManifestFixer.h
index 2e81266..c3a114b 100644
--- a/tools/aapt2/link/ManifestFixer.h
+++ b/tools/aapt2/link/ManifestFixer.h
@@ -27,12 +27,12 @@
 namespace aapt {
 
 struct ManifestFixerOptions {
-    Maybe<std::string> minSdkVersionDefault;
-    Maybe<std::string> targetSdkVersionDefault;
-    Maybe<std::string> renameManifestPackage;
-    Maybe<std::string> renameInstrumentationTargetPackage;
-    Maybe<std::string> versionNameDefault;
-    Maybe<std::string> 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;
 };
 
 /**
@@ -40,18 +40,18 @@
  * where specified with ManifestFixerOptions.
  */
 class ManifestFixer : public IXmlResourceConsumer {
-public:
-    explicit ManifestFixer(const ManifestFixerOptions& options) : mOptions(options) {
-    }
+ public:
+  explicit ManifestFixer(const ManifestFixerOptions& options)
+      : mOptions(options) {}
 
-    bool consume(IAaptContext* context, xml::XmlResource* doc) override;
+  bool consume(IAaptContext* context, xml::XmlResource* doc) override;
 
-private:
-    bool buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag);
+ private:
+  bool buildRules(xml::XmlActionExecutor* executor, IDiagnostics* diag);
 
-    ManifestFixerOptions mOptions;
+  ManifestFixerOptions mOptions;
 };
 
-} // namespace aapt
+}  // namespace aapt
 
 #endif /* AAPT_LINK_MANIFESTFIXER_H */
diff --git a/tools/aapt2/link/ManifestFixer_test.cpp b/tools/aapt2/link/ManifestFixer_test.cpp
index 16ab9ab..dc78d98 100644
--- a/tools/aapt2/link/ManifestFixer_test.cpp
+++ b/tools/aapt2/link/ManifestFixer_test.cpp
@@ -23,254 +23,274 @@
 namespace aapt {
 
 struct ManifestFixerTest : public ::testing::Test {
-    std::unique_ptr<IAaptContext> mContext;
+  std::unique_ptr<IAaptContext> mContext;
 
-    void SetUp() override {
-        mContext = test::ContextBuilder()
-                .setCompilationPackage("android")
-                .setPackageId(0x01)
-                .setNameManglerPolicy(NameManglerPolicy{ "android" })
-                .addSymbolSource(test::StaticSymbolSourceBuilder()
-                        .addSymbol("android:attr/package", ResourceId(0x01010000),
-                                   test::AttributeBuilder()
-                                        .setTypeMask(android::ResTable_map::TYPE_STRING)
-                                        .build())
-                        .addSymbol("android:attr/minSdkVersion", ResourceId(0x01010001),
-                                   test::AttributeBuilder()
-                                        .setTypeMask(android::ResTable_map::TYPE_STRING |
-                                                     android::ResTable_map::TYPE_INTEGER)
-                                        .build())
-                        .addSymbol("android:attr/targetSdkVersion", ResourceId(0x01010002),
-                                   test::AttributeBuilder()
-                                        .setTypeMask(android::ResTable_map::TYPE_STRING |
-                                                     android::ResTable_map::TYPE_INTEGER)
-                                        .build())
-                        .addSymbol("android:string/str", ResourceId(0x01060000))
-                        .build())
-                .build();
-    }
+  void SetUp() override {
+    mContext =
+        test::ContextBuilder()
+            .setCompilationPackage("android")
+            .setPackageId(0x01)
+            .setNameManglerPolicy(NameManglerPolicy{"android"})
+            .addSymbolSource(
+                test::StaticSymbolSourceBuilder()
+                    .addSymbol(
+                        "android:attr/package", ResourceId(0x01010000),
+                        test::AttributeBuilder()
+                            .setTypeMask(android::ResTable_map::TYPE_STRING)
+                            .build())
+                    .addSymbol(
+                        "android:attr/minSdkVersion", ResourceId(0x01010001),
+                        test::AttributeBuilder()
+                            .setTypeMask(android::ResTable_map::TYPE_STRING |
+                                         android::ResTable_map::TYPE_INTEGER)
+                            .build())
+                    .addSymbol(
+                        "android:attr/targetSdkVersion", ResourceId(0x01010002),
+                        test::AttributeBuilder()
+                            .setTypeMask(android::ResTable_map::TYPE_STRING |
+                                         android::ResTable_map::TYPE_INTEGER)
+                            .build())
+                    .addSymbol("android:string/str", ResourceId(0x01060000))
+                    .build())
+            .build();
+  }
 
-    std::unique_ptr<xml::XmlResource> verify(const StringPiece& str) {
-        return verifyWithOptions(str, {});
-    }
+  std::unique_ptr<xml::XmlResource> verify(const StringPiece& str) {
+    return verifyWithOptions(str, {});
+  }
 
-    std::unique_ptr<xml::XmlResource> verifyWithOptions(const StringPiece& str,
-                                                        const ManifestFixerOptions& options) {
-        std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(str);
-        ManifestFixer fixer(options);
-        if (fixer.consume(mContext.get(), doc.get())) {
-            return doc;
-        }
-        return {};
+  std::unique_ptr<xml::XmlResource> verifyWithOptions(
+      const StringPiece& str, const ManifestFixerOptions& options) {
+    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDom(str);
+    ManifestFixer fixer(options);
+    if (fixer.consume(mContext.get(), doc.get())) {
+      return doc;
     }
+    return {};
+  }
 };
 
 TEST_F(ManifestFixerTest, EnsureManifestIsRootTag) {
-    EXPECT_EQ(nullptr, verify("<other-tag />"));
-    EXPECT_EQ(nullptr, verify("<ns:manifest xmlns:ns=\"com\" />"));
-    EXPECT_NE(nullptr, verify("<manifest package=\"android\"></manifest>"));
+  EXPECT_EQ(nullptr, verify("<other-tag />"));
+  EXPECT_EQ(nullptr, verify("<ns:manifest xmlns:ns=\"com\" />"));
+  EXPECT_NE(nullptr, verify("<manifest package=\"android\"></manifest>"));
 }
 
 TEST_F(ManifestFixerTest, EnsureManifestHasPackage) {
-    EXPECT_NE(nullptr, verify("<manifest package=\"android\" />"));
-    EXPECT_NE(nullptr, verify("<manifest package=\"com.android\" />"));
-    EXPECT_NE(nullptr, verify("<manifest package=\"com.android.google\" />"));
-    EXPECT_EQ(nullptr, verify("<manifest package=\"com.android.google.Class$1\" />"));
-    EXPECT_EQ(nullptr,
-              verify("<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\" "
-                     "android:package=\"com.android\" />"));
-    EXPECT_EQ(nullptr, verify("<manifest package=\"@string/str\" />"));
+  EXPECT_NE(nullptr, verify("<manifest package=\"android\" />"));
+  EXPECT_NE(nullptr, verify("<manifest package=\"com.android\" />"));
+  EXPECT_NE(nullptr, verify("<manifest package=\"com.android.google\" />"));
+  EXPECT_EQ(nullptr,
+            verify("<manifest package=\"com.android.google.Class$1\" />"));
+  EXPECT_EQ(nullptr, verify("<manifest "
+                            "xmlns:android=\"http://schemas.android.com/apk/"
+                            "res/android\" "
+                            "android:package=\"com.android\" />"));
+  EXPECT_EQ(nullptr, verify("<manifest package=\"@string/str\" />"));
 }
 
 TEST_F(ManifestFixerTest, UseDefaultSdkVersionsIfNonePresent) {
-    ManifestFixerOptions options = { std::string("8"), std::string("22") };
+  ManifestFixerOptions options = {std::string("8"), std::string("22")};
 
-    std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="android">
         <uses-sdk android:minSdkVersion="7" android:targetSdkVersion="21" />
-      </manifest>)EOF", options);
-    ASSERT_NE(nullptr, doc);
+      </manifest>)EOF",
+                                                            options);
+  ASSERT_NE(nullptr, doc);
 
-    xml::Element* el;
-    xml::Attribute* attr;
+  xml::Element* el;
+  xml::Attribute* attr;
 
-    el = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, el);
-    el = el->findChild({}, "uses-sdk");
-    ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("7", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("21", attr->value);
+  el = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, el);
+  el = el->findChild({}, "uses-sdk");
+  ASSERT_NE(nullptr, el);
+  attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("7", attr->value);
+  attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("21", attr->value);
 
-    doc = verifyWithOptions(R"EOF(
+  doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="android">
         <uses-sdk android:targetSdkVersion="21" />
-      </manifest>)EOF", options);
-    ASSERT_NE(nullptr, doc);
+      </manifest>)EOF",
+                          options);
+  ASSERT_NE(nullptr, doc);
 
-    el = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, el);
-    el = el->findChild({}, "uses-sdk");
-    ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("8", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("21", attr->value);
+  el = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, el);
+  el = el->findChild({}, "uses-sdk");
+  ASSERT_NE(nullptr, el);
+  attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("8", attr->value);
+  attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("21", attr->value);
 
-    doc = verifyWithOptions(R"EOF(
+  doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="android">
         <uses-sdk />
-      </manifest>)EOF", options);
-    ASSERT_NE(nullptr, doc);
+      </manifest>)EOF",
+                          options);
+  ASSERT_NE(nullptr, doc);
 
-    el = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, el);
-    el = el->findChild({}, "uses-sdk");
-    ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("8", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("22", attr->value);
+  el = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, el);
+  el = el->findChild({}, "uses-sdk");
+  ASSERT_NE(nullptr, el);
+  attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("8", attr->value);
+  attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("22", attr->value);
 
-    doc = verifyWithOptions(R"EOF(
+  doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-                package="android" />)EOF", options);
-    ASSERT_NE(nullptr, doc);
+                package="android" />)EOF",
+                          options);
+  ASSERT_NE(nullptr, doc);
 
-    el = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, el);
-    el = el->findChild({}, "uses-sdk");
-    ASSERT_NE(nullptr, el);
-    attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("8", attr->value);
-    attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ("22", attr->value);
+  el = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, el);
+  el = el->findChild({}, "uses-sdk");
+  ASSERT_NE(nullptr, el);
+  attr = el->findAttribute(xml::kSchemaAndroid, "minSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("8", attr->value);
+  attr = el->findAttribute(xml::kSchemaAndroid, "targetSdkVersion");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ("22", attr->value);
 }
 
 TEST_F(ManifestFixerTest, RenameManifestPackageAndFullyQualifyClasses) {
-    ManifestFixerOptions options;
-    options.renameManifestPackage = std::string("com.android");
+  ManifestFixerOptions options;
+  options.renameManifestPackage = std::string("com.android");
 
-    std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="android">
         <application android:name=".MainApplication" text="hello">
           <activity android:name=".activity.Start" />
           <receiver android:name="com.google.android.Receiver" />
         </application>
-      </manifest>)EOF", options);
-    ASSERT_NE(nullptr, doc);
+      </manifest>)EOF",
+                                                            options);
+  ASSERT_NE(nullptr, doc);
 
-    xml::Element* manifestEl = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, manifestEl);
+  xml::Element* manifestEl = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, manifestEl);
 
-    xml::Attribute* attr = nullptr;
+  xml::Attribute* attr = nullptr;
 
-    attr = manifestEl->findAttribute({},"package");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::string("com.android"), attr->value);
+  attr = manifestEl->findAttribute({}, "package");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ(std::string("com.android"), attr->value);
 
-    xml::Element* applicationEl = manifestEl->findChild({}, "application");
-    ASSERT_NE(nullptr, applicationEl);
+  xml::Element* applicationEl = manifestEl->findChild({}, "application");
+  ASSERT_NE(nullptr, applicationEl);
 
-    attr = applicationEl->findAttribute(xml::kSchemaAndroid, "name");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::string("android.MainApplication"), attr->value);
+  attr = applicationEl->findAttribute(xml::kSchemaAndroid, "name");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ(std::string("android.MainApplication"), attr->value);
 
-    attr = applicationEl->findAttribute({}, "text");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::string("hello"), attr->value);
+  attr = applicationEl->findAttribute({}, "text");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ(std::string("hello"), attr->value);
 
-    xml::Element* el;
-    el = applicationEl->findChild({}, "activity");
-    ASSERT_NE(nullptr, el);
+  xml::Element* el;
+  el = applicationEl->findChild({}, "activity");
+  ASSERT_NE(nullptr, el);
 
-    attr = el->findAttribute(xml::kSchemaAndroid, "name");
-    ASSERT_NE(nullptr, el);
-    EXPECT_EQ(std::string("android.activity.Start"), attr->value);
+  attr = el->findAttribute(xml::kSchemaAndroid, "name");
+  ASSERT_NE(nullptr, el);
+  EXPECT_EQ(std::string("android.activity.Start"), attr->value);
 
-    el = applicationEl->findChild({}, "receiver");
-    ASSERT_NE(nullptr, el);
+  el = applicationEl->findChild({}, "receiver");
+  ASSERT_NE(nullptr, el);
 
-    attr = el->findAttribute(xml::kSchemaAndroid, "name");
-    ASSERT_NE(nullptr, el);
-    EXPECT_EQ(std::string("com.google.android.Receiver"), attr->value);
+  attr = el->findAttribute(xml::kSchemaAndroid, "name");
+  ASSERT_NE(nullptr, el);
+  EXPECT_EQ(std::string("com.google.android.Receiver"), attr->value);
 }
 
-TEST_F(ManifestFixerTest, RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
-    ManifestFixerOptions options;
-    options.renameInstrumentationTargetPackage = std::string("com.android");
+TEST_F(ManifestFixerTest,
+       RenameManifestInstrumentationPackageAndFullyQualifyTarget) {
+  ManifestFixerOptions options;
+  options.renameInstrumentationTargetPackage = std::string("com.android");
 
-    std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
                 package="android">
         <instrumentation android:targetPackage="android" />
-      </manifest>)EOF", options);
-    ASSERT_NE(nullptr, doc);
+      </manifest>)EOF",
+                                                            options);
+  ASSERT_NE(nullptr, doc);
 
-    xml::Element* manifestEl = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, manifestEl);
+  xml::Element* manifestEl = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, manifestEl);
 
-    xml::Element* instrumentationEl = manifestEl->findChild({}, "instrumentation");
-    ASSERT_NE(nullptr, instrumentationEl);
+  xml::Element* instrumentationEl =
+      manifestEl->findChild({}, "instrumentation");
+  ASSERT_NE(nullptr, instrumentationEl);
 
-    xml::Attribute* attr = instrumentationEl->findAttribute(xml::kSchemaAndroid, "targetPackage");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::string("com.android"), attr->value);
+  xml::Attribute* attr =
+      instrumentationEl->findAttribute(xml::kSchemaAndroid, "targetPackage");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ(std::string("com.android"), attr->value);
 }
 
 TEST_F(ManifestFixerTest, UseDefaultVersionNameAndCode) {
-    ManifestFixerOptions options;
-    options.versionNameDefault = std::string("Beta");
-    options.versionCodeDefault = std::string("0x10000000");
+  ManifestFixerOptions options;
+  options.versionNameDefault = std::string("Beta");
+  options.versionCodeDefault = std::string("0x10000000");
 
-    std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
+  std::unique_ptr<xml::XmlResource> doc = verifyWithOptions(R"EOF(
       <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-                package="android" />)EOF", options);
-    ASSERT_NE(nullptr, doc);
+                package="android" />)EOF",
+                                                            options);
+  ASSERT_NE(nullptr, doc);
 
-    xml::Element* manifestEl = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, manifestEl);
+  xml::Element* manifestEl = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, manifestEl);
 
-    xml::Attribute* attr = manifestEl->findAttribute(xml::kSchemaAndroid, "versionName");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::string("Beta"), attr->value);
+  xml::Attribute* attr =
+      manifestEl->findAttribute(xml::kSchemaAndroid, "versionName");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ(std::string("Beta"), attr->value);
 
-    attr = manifestEl->findAttribute(xml::kSchemaAndroid, "versionCode");
-    ASSERT_NE(nullptr, attr);
-    EXPECT_EQ(std::string("0x10000000"), attr->value);
+  attr = manifestEl->findAttribute(xml::kSchemaAndroid, "versionCode");
+  ASSERT_NE(nullptr, attr);
+  EXPECT_EQ(std::string("0x10000000"), attr->value);
 }
 
 TEST_F(ManifestFixerTest, EnsureManifestAttributesAreTyped) {
-    EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"hello\" />"));
-    EXPECT_EQ(nullptr, verify("<manifest package=\"android\" coreApp=\"1dp\" />"));
+  EXPECT_EQ(nullptr,
+            verify("<manifest package=\"android\" coreApp=\"hello\" />"));
+  EXPECT_EQ(nullptr,
+            verify("<manifest package=\"android\" coreApp=\"1dp\" />"));
 
-    std::unique_ptr<xml::XmlResource> doc =
-            verify("<manifest package=\"android\" coreApp=\"true\" />");
-    ASSERT_NE(nullptr, doc);
+  std::unique_ptr<xml::XmlResource> doc =
+      verify("<manifest package=\"android\" coreApp=\"true\" />");
+  ASSERT_NE(nullptr, doc);
 
-    xml::Element* el = xml::findRootElement(doc.get());
-    ASSERT_NE(nullptr, el);
+  xml::Element* el = xml::findRootElement(doc.get());
+  ASSERT_NE(nullptr, el);
 
-    EXPECT_EQ("manifest", el->name);
+  EXPECT_EQ("manifest", el->name);
 
-    xml::Attribute* attr = el->findAttribute("", "coreApp");
-    ASSERT_NE(nullptr, attr);
+  xml::Attribute* attr = el->findAttribute("", "coreApp");
+  ASSERT_NE(nullptr, attr);
 
-    EXPECT_NE(nullptr, attr->compiledValue);
-    EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(attr->compiledValue.get()));
+  EXPECT_NE(nullptr, attr->compiledValue);
+  EXPECT_NE(nullptr, valueCast<BinaryPrimitive>(attr->compiledValue.get()));
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/PrivateAttributeMover.cpp b/tools/aapt2/link/PrivateAttributeMover.cpp
index 3c8af4f..174b41f 100644
--- a/tools/aapt2/link/PrivateAttributeMover.cpp
+++ b/tools/aapt2/link/PrivateAttributeMover.cpp
@@ -25,56 +25,61 @@
 template <typename InputContainer, typename OutputIterator, typename Predicate>
 OutputIterator moveIf(InputContainer& inputContainer, OutputIterator result,
                       Predicate pred) {
-    const auto last = inputContainer.end();
-    auto newEnd = std::find_if(inputContainer.begin(), inputContainer.end(), pred);
-    if (newEnd == last) {
-        return result;
-    }
-
-    *result = std::move(*newEnd);
-
-    auto first = newEnd;
-    ++first;
-
-    for (; first != last; ++first) {
-        if (bool(pred(*first))) {
-            // We want to move this guy
-            *result = std::move(*first);
-            ++result;
-        } else {
-            // We want to keep this guy, but we will need to move it up the list to replace
-            // missing items.
-            *newEnd = std::move(*first);
-            ++newEnd;
-        }
-    }
-
-    inputContainer.erase(newEnd, last);
+  const auto last = inputContainer.end();
+  auto newEnd =
+      std::find_if(inputContainer.begin(), inputContainer.end(), pred);
+  if (newEnd == last) {
     return result;
-}
+  }
 
-bool PrivateAttributeMover::consume(IAaptContext* context, ResourceTable* table) {
-    for (auto& package : table->packages) {
-        ResourceTableType* type = package->findType(ResourceType::kAttr);
-        if (!type) {
-            continue;
-        }
+  *result = std::move(*newEnd);
 
-        if (type->symbolStatus.state != SymbolState::kPublic) {
-            // No public attributes, so we can safely leave these private attributes where they are.
-            return true;
-        }
+  auto first = newEnd;
+  ++first;
 
-        ResourceTableType* privAttrType = package->findOrCreateType(ResourceType::kAttrPrivate);
-        assert(privAttrType->entries.empty());
-
-        moveIf(type->entries, std::back_inserter(privAttrType->entries),
-               [](const std::unique_ptr<ResourceEntry>& entry) -> bool {
-                   return entry->symbolStatus.state != SymbolState::kPublic;
-               });
-        break;
+  for (; first != last; ++first) {
+    if (bool(pred(*first))) {
+      // We want to move this guy
+      *result = std::move(*first);
+      ++result;
+    } else {
+      // We want to keep this guy, but we will need to move it up the list to
+      // replace
+      // missing items.
+      *newEnd = std::move(*first);
+      ++newEnd;
     }
-    return true;
+  }
+
+  inputContainer.erase(newEnd, last);
+  return result;
 }
 
-} // namespace aapt
+bool PrivateAttributeMover::consume(IAaptContext* context,
+                                    ResourceTable* table) {
+  for (auto& package : table->packages) {
+    ResourceTableType* type = package->findType(ResourceType::kAttr);
+    if (!type) {
+      continue;
+    }
+
+    if (type->symbolStatus.state != SymbolState::kPublic) {
+      // No public attributes, so we can safely leave these private attributes
+      // where they are.
+      return true;
+    }
+
+    ResourceTableType* privAttrType =
+        package->findOrCreateType(ResourceType::kAttrPrivate);
+    assert(privAttrType->entries.empty());
+
+    moveIf(type->entries, std::back_inserter(privAttrType->entries),
+           [](const std::unique_ptr<ResourceEntry>& entry) -> bool {
+             return entry->symbolStatus.state != SymbolState::kPublic;
+           });
+    break;
+  }
+  return true;
+}
+
+}  // namespace aapt
diff --git a/tools/aapt2/link/PrivateAttributeMover_test.cpp b/tools/aapt2/link/PrivateAttributeMover_test.cpp
index c9d1a08..a7a1013 100644
--- a/tools/aapt2/link/PrivateAttributeMover_test.cpp
+++ b/tools/aapt2/link/PrivateAttributeMover_test.cpp
@@ -20,56 +20,60 @@
 namespace aapt {
 
 TEST(PrivateAttributeMoverTest, MovePrivateAttributes) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .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();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .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()));
+  PrivateAttributeMover mover;
+  ASSERT_TRUE(mover.consume(context.get(), table.get()));
 
-    ResourceTablePackage* package = table->findPackage("android");
-    ASSERT_NE(package, nullptr);
+  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("publicA"), nullptr);
-    EXPECT_NE(type->findEntry("publicB"), nullptr);
+  ResourceTableType* type = package->findType(ResourceType::kAttr);
+  ASSERT_NE(type, nullptr);
+  ASSERT_EQ(type->entries.size(), 2u);
+  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("privateA"), nullptr);
-    EXPECT_NE(type->findEntry("privateB"), nullptr);
+  type = package->findType(ResourceType::kAttrPrivate);
+  ASSERT_NE(type, nullptr);
+  ASSERT_EQ(type->entries.size(), 2u);
+  EXPECT_NE(type->findEntry("privateA"), nullptr);
+  EXPECT_NE(type->findEntry("privateB"), nullptr);
 }
 
-TEST(PrivateAttributeMoverTest, LeavePrivateAttributesWhenNoPublicAttributesDefined) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+TEST(PrivateAttributeMoverTest,
+     LeavePrivateAttributesWhenNoPublicAttributesDefined) {
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addSimple("android:attr/privateA")
-            .addSimple("android:attr/privateB")
-            .build();
+  std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
+                                             .addSimple("android:attr/privateA")
+                                             .addSimple("android:attr/privateB")
+                                             .build();
 
-    PrivateAttributeMover mover;
-    ASSERT_TRUE(mover.consume(context.get(), table.get()));
+  PrivateAttributeMover mover;
+  ASSERT_TRUE(mover.consume(context.get(), table.get()));
 
-    ResourceTablePackage* package = table->findPackage("android");
-    ASSERT_NE(package, nullptr);
+  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);
+  ResourceTableType* type = package->findType(ResourceType::kAttr);
+  ASSERT_NE(type, nullptr);
+  ASSERT_EQ(type->entries.size(), 2u);
 
-    type = package->findType(ResourceType::kAttrPrivate);
-    ASSERT_EQ(type, nullptr);
+  type = package->findType(ResourceType::kAttrPrivate);
+  ASSERT_EQ(type, nullptr);
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/ProductFilter.cpp b/tools/aapt2/link/ProductFilter.cpp
index 8784e89..d59b682 100644
--- a/tools/aapt2/link/ProductFilter.cpp
+++ b/tools/aapt2/link/ProductFilter.cpp
@@ -18,101 +18,103 @@
 
 namespace aapt {
 
-ProductFilter::ResourceConfigValueIter
-ProductFilter::selectProductToKeep(const ResourceNameRef& name,
-                                   const ResourceConfigValueIter begin,
-                                   const ResourceConfigValueIter end,
-                                   IDiagnostics* diag) {
-    ResourceConfigValueIter defaultProductIter = end;
-    ResourceConfigValueIter selectedProductIter = end;
+ProductFilter::ResourceConfigValueIter ProductFilter::selectProductToKeep(
+    const ResourceNameRef& name, const ResourceConfigValueIter begin,
+    const ResourceConfigValueIter end, IDiagnostics* diag) {
+  ResourceConfigValueIter defaultProductIter = end;
+  ResourceConfigValueIter selectedProductIter = end;
 
-    for (ResourceConfigValueIter iter = begin; iter != end; ++iter) {
-        ResourceConfigValue* configValue = iter->get();
-        if (mProducts.find(configValue->product) != mProducts.end()) {
-            if (selectedProductIter != end) {
-                // We have two possible values for this product!
-                diag->error(DiagMessage(configValue->value->getSource())
-                            << "selection of product '" << configValue->product
-                            << "' for resource " << name << " is ambiguous");
+  for (ResourceConfigValueIter iter = begin; iter != end; ++iter) {
+    ResourceConfigValue* configValue = iter->get();
+    if (mProducts.find(configValue->product) != mProducts.end()) {
+      if (selectedProductIter != end) {
+        // We have two possible values for this product!
+        diag->error(DiagMessage(configValue->value->getSource())
+                    << "selection of product '" << configValue->product
+                    << "' for resource " << name << " is ambiguous");
 
-                ResourceConfigValue* previouslySelectedConfigValue = selectedProductIter->get();
-                diag->note(DiagMessage(previouslySelectedConfigValue->value->getSource())
-                           << "product '" << previouslySelectedConfigValue->product
-                           << "' is also a candidate");
-                return end;
-            }
-
-            // Select this product.
-            selectedProductIter = iter;
-        }
-
-        if (configValue->product.empty() || configValue->product == "default") {
-            if (defaultProductIter != end) {
-                // We have two possible default values.
-                diag->error(DiagMessage(configValue->value->getSource())
-                            << "multiple default products defined for resource " << name);
-
-                ResourceConfigValue* previouslyDefaultConfigValue = defaultProductIter->get();
-                diag->note(DiagMessage(previouslyDefaultConfigValue->value->getSource())
-                           << "default product also defined here");
-                return end;
-            }
-
-            // Mark the default.
-            defaultProductIter = iter;
-        }
-    }
-
-    if (defaultProductIter == end) {
-        diag->error(DiagMessage() << "no default product defined for resource " << name);
+        ResourceConfigValue* previouslySelectedConfigValue =
+            selectedProductIter->get();
+        diag->note(
+            DiagMessage(previouslySelectedConfigValue->value->getSource())
+            << "product '" << previouslySelectedConfigValue->product
+            << "' is also a candidate");
         return end;
+      }
+
+      // Select this product.
+      selectedProductIter = iter;
     }
 
-    if (selectedProductIter == end) {
-        selectedProductIter = defaultProductIter;
+    if (configValue->product.empty() || configValue->product == "default") {
+      if (defaultProductIter != end) {
+        // We have two possible default values.
+        diag->error(DiagMessage(configValue->value->getSource())
+                    << "multiple default products defined for resource "
+                    << name);
+
+        ResourceConfigValue* previouslyDefaultConfigValue =
+            defaultProductIter->get();
+        diag->note(DiagMessage(previouslyDefaultConfigValue->value->getSource())
+                   << "default product also defined here");
+        return end;
+      }
+
+      // Mark the default.
+      defaultProductIter = iter;
     }
-    return selectedProductIter;
+  }
+
+  if (defaultProductIter == end) {
+    diag->error(DiagMessage() << "no default product defined for resource "
+                              << name);
+    return end;
+  }
+
+  if (selectedProductIter == end) {
+    selectedProductIter = defaultProductIter;
+  }
+  return selectedProductIter;
 }
 
 bool ProductFilter::consume(IAaptContext* context, ResourceTable* table) {
-    bool error = false;
-    for (auto& pkg : table->packages) {
-        for (auto& type : pkg->types) {
-            for (auto& entry : type->entries) {
-                std::vector<std::unique_ptr<ResourceConfigValue>> newValues;
+  bool error = false;
+  for (auto& pkg : table->packages) {
+    for (auto& type : pkg->types) {
+      for (auto& entry : type->entries) {
+        std::vector<std::unique_ptr<ResourceConfigValue>> newValues;
 
-                ResourceConfigValueIter iter = entry->values.begin();
-                ResourceConfigValueIter startRangeIter = iter;
-                while (iter != entry->values.end()) {
-                    ++iter;
-                    if (iter == entry->values.end() ||
-                            (*iter)->config != (*startRangeIter)->config) {
-
-                        // End of the array, or we saw a different config,
-                        // so this must be the end of a range of products.
-                        // Select the product to keep from the set of products defined.
-                        ResourceNameRef name(pkg->name, type->type, entry->name);
-                        auto valueToKeep = selectProductToKeep(name, startRangeIter, iter,
-                                                               context->getDiagnostics());
-                        if (valueToKeep == iter) {
-                            // An error occurred, we could not pick a product.
-                            error = true;
-                        } else {
-                            // We selected a product to keep. Move it to the new array.
-                            newValues.push_back(std::move(*valueToKeep));
-                        }
-
-                        // Start the next range of products.
-                        startRangeIter = iter;
-                    }
-                }
-
-                // Now move the new values in to place.
-                entry->values = std::move(newValues);
+        ResourceConfigValueIter iter = entry->values.begin();
+        ResourceConfigValueIter startRangeIter = iter;
+        while (iter != entry->values.end()) {
+          ++iter;
+          if (iter == entry->values.end() ||
+              (*iter)->config != (*startRangeIter)->config) {
+            // End of the array, or we saw a different config,
+            // so this must be the end of a range of products.
+            // Select the product to keep from the set of products defined.
+            ResourceNameRef name(pkg->name, type->type, entry->name);
+            auto valueToKeep = selectProductToKeep(name, startRangeIter, iter,
+                                                   context->getDiagnostics());
+            if (valueToKeep == iter) {
+              // An error occurred, we could not pick a product.
+              error = true;
+            } else {
+              // We selected a product to keep. Move it to the new array.
+              newValues.push_back(std::move(*valueToKeep));
             }
+
+            // Start the next range of products.
+            startRangeIter = iter;
+          }
         }
+
+        // Now move the new values in to place.
+        entry->values = std::move(newValues);
+      }
     }
-    return !error;
+  }
+  return !error;
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/ProductFilter.h b/tools/aapt2/link/ProductFilter.h
index 7724e14..cc8b8c2 100644
--- a/tools/aapt2/link/ProductFilter.h
+++ b/tools/aapt2/link/ProductFilter.h
@@ -26,24 +26,25 @@
 namespace aapt {
 
 class ProductFilter {
-public:
-    using ResourceConfigValueIter = std::vector<std::unique_ptr<ResourceConfigValue>>::iterator;
+ public:
+  using ResourceConfigValueIter =
+      std::vector<std::unique_ptr<ResourceConfigValue>>::iterator;
 
-    explicit ProductFilter(std::unordered_set<std::string> products) : mProducts(products) { }
+  explicit ProductFilter(std::unordered_set<std::string> products)
+      : mProducts(products) {}
 
-    ResourceConfigValueIter selectProductToKeep(const ResourceNameRef& name,
-                                                const ResourceConfigValueIter begin,
-                                                const ResourceConfigValueIter end,
-                                                IDiagnostics* diag);
+  ResourceConfigValueIter selectProductToKeep(
+      const ResourceNameRef& name, const ResourceConfigValueIter begin,
+      const ResourceConfigValueIter end, IDiagnostics* diag);
 
-    bool consume(IAaptContext* context, ResourceTable* table);
+  bool consume(IAaptContext* context, ResourceTable* table);
 
-private:
-    std::unordered_set<std::string> mProducts;
+ private:
+  std::unordered_set<std::string> mProducts;
 
-    DISALLOW_COPY_AND_ASSIGN(ProductFilter);
+  DISALLOW_COPY_AND_ASSIGN(ProductFilter);
 };
 
-} // namespace aapt
+}  // namespace aapt
 
 #endif /* AAPT_LINK_PRODUCTFILTER_H */
diff --git a/tools/aapt2/link/ProductFilter_test.cpp b/tools/aapt2/link/ProductFilter_test.cpp
index a3376ac..7f78f8b 100644
--- a/tools/aapt2/link/ProductFilter_test.cpp
+++ b/tools/aapt2/link/ProductFilter_test.cpp
@@ -20,114 +20,110 @@
 namespace aapt {
 
 TEST(ProductFilterTest, SelectTwoProducts) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
-    const ConfigDescription land = test::parseConfigOrDie("land");
-    const ConfigDescription port = test::parseConfigOrDie("port");
+  const ConfigDescription land = test::parseConfigOrDie("land");
+  const ConfigDescription port = test::parseConfigOrDie("port");
 
-    ResourceTable table;
-    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("android:string/one"),
-                                  land, "tablet",
-                                  test::ValueBuilder<Id>()
-                                          .setSource(Source("land/tablet.xml")).build(),
-                                  context->getDiagnostics()));
+  ResourceTable table;
+  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("android:string/one"), land, "tablet",
+      test::ValueBuilder<Id>().setSource(Source("land/tablet.xml")).build(),
+      context->getDiagnostics()));
 
-    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("android:string/one"),
-                                  port, "tablet",
-                                  test::ValueBuilder<Id>()
-                                          .setSource(Source("port/tablet.xml")).build(),
-                                  context->getDiagnostics()));
+  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("android:string/one"), port, "tablet",
+      test::ValueBuilder<Id>().setSource(Source("port/tablet.xml")).build(),
+      context->getDiagnostics()));
 
-    ProductFilter filter({ "tablet" });
-    ASSERT_TRUE(filter.consume(context.get(), &table));
+  ProductFilter filter({"tablet"});
+  ASSERT_TRUE(filter.consume(context.get(), &table));
 
-    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, "android:string/one",
-                                                             land, ""));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "android:string/one",
-                                                             land, "tablet"));
-    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, "android:string/one",
-                                                             port, ""));
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "android:string/one",
-                                                             port, "tablet"));
+  EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(
+                         &table, "android:string/one", land, ""));
+  EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(
+                         &table, "android:string/one", land, "tablet"));
+  EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(
+                         &table, "android:string/one", port, ""));
+  EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(
+                         &table, "android:string/one", port, "tablet"));
 }
 
 TEST(ProductFilterTest, SelectDefaultProduct) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
-    ResourceTable table;
-    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("android:string/one"),
-                                  ConfigDescription::defaultConfig(), "tablet",
-                                  test::ValueBuilder<Id>()
-                                          .setSource(Source("tablet.xml")).build(),
-                                  context->getDiagnostics()));
+  ResourceTable table;
+  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("android:string/one"),
+      ConfigDescription::defaultConfig(), "tablet",
+      test::ValueBuilder<Id>().setSource(Source("tablet.xml")).build(),
+      context->getDiagnostics()));
 
-    ProductFilter filter({});
-    ASSERT_TRUE(filter.consume(context.get(), &table));
+  ProductFilter filter({});
+  ASSERT_TRUE(filter.consume(context.get(), &table));
 
-    EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(&table, "android:string/one",
-                                                             ConfigDescription::defaultConfig(),
-                                                             ""));
-    EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(&table, "android:string/one",
-                                                             ConfigDescription::defaultConfig(),
-                                                             "tablet"));
+  EXPECT_NE(nullptr, test::getValueForConfigAndProduct<Id>(
+                         &table, "android:string/one",
+                         ConfigDescription::defaultConfig(), ""));
+  EXPECT_EQ(nullptr, test::getValueForConfigAndProduct<Id>(
+                         &table, "android:string/one",
+                         ConfigDescription::defaultConfig(), "tablet"));
 }
 
 TEST(ProductFilterTest, FailOnAmbiguousProduct) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
-    ResourceTable table;
-    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("android:string/one"),
-                                  ConfigDescription::defaultConfig(), "tablet",
-                                  test::ValueBuilder<Id>()
-                                          .setSource(Source("tablet.xml")).build(),
-                                  context->getDiagnostics()));
-    ASSERT_TRUE(table.addResource(test::parseNameOrDie("android:string/one"),
-                                  ConfigDescription::defaultConfig(), "no-sdcard",
-                                  test::ValueBuilder<Id>()
-                                          .setSource(Source("no-sdcard.xml")).build(),
-                                  context->getDiagnostics()));
+  ResourceTable table;
+  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("android:string/one"),
+      ConfigDescription::defaultConfig(), "tablet",
+      test::ValueBuilder<Id>().setSource(Source("tablet.xml")).build(),
+      context->getDiagnostics()));
+  ASSERT_TRUE(table.addResource(
+      test::parseNameOrDie("android:string/one"),
+      ConfigDescription::defaultConfig(), "no-sdcard",
+      test::ValueBuilder<Id>().setSource(Source("no-sdcard.xml")).build(),
+      context->getDiagnostics()));
 
-    ProductFilter filter({ "tablet", "no-sdcard" });
-    ASSERT_FALSE(filter.consume(context.get(), &table));
+  ProductFilter filter({"tablet", "no-sdcard"});
+  ASSERT_FALSE(filter.consume(context.get(), &table));
 }
 
 TEST(ProductFilterTest, FailOnMultipleDefaults) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
 
-    ResourceTable table;
-    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("android:string/one"),
-                                  ConfigDescription::defaultConfig(), "default",
-                                  test::ValueBuilder<Id>()
-                                          .setSource(Source("default.xml")).build(),
-                                  context->getDiagnostics()));
+  ResourceTable table;
+  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("android:string/one"),
+      ConfigDescription::defaultConfig(), "default",
+      test::ValueBuilder<Id>().setSource(Source("default.xml")).build(),
+      context->getDiagnostics()));
 
-    ProductFilter filter({});
-    ASSERT_FALSE(filter.consume(context.get(), &table));
+  ProductFilter filter({});
+  ASSERT_FALSE(filter.consume(context.get(), &table));
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/ReferenceLinker.cpp b/tools/aapt2/link/ReferenceLinker.cpp
index be7aca3..7fe0956 100644
--- a/tools/aapt2/link/ReferenceLinker.cpp
+++ b/tools/aapt2/link/ReferenceLinker.cpp
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#include "Diagnostics.h"
 #include "ReferenceLinker.h"
+#include "Diagnostics.h"
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
@@ -34,302 +34,335 @@
 namespace {
 
 /**
- * The ReferenceLinkerVisitor will follow all references and make sure they point
- * to resources that actually exist, either in the local resource table, or as external
- * symbols. Once the target resource has been found, the ID of the resource will be assigned
+ * The ReferenceLinkerVisitor will follow all references and make sure they
+ * point
+ * to resources that actually exist, either in the local resource table, or as
+ * external
+ * symbols. Once the target resource has been found, the ID of the resource will
+ * be assigned
  * to the reference object.
  *
  * NOTE: All of the entries in the ResourceTable must be assigned IDs.
  */
 class ReferenceLinkerVisitor : public ValueVisitor {
-public:
-    using ValueVisitor::visit;
+ public:
+  using ValueVisitor::visit;
 
-    ReferenceLinkerVisitor(IAaptContext* context, SymbolTable* symbols, StringPool* stringPool,
-                           xml::IPackageDeclStack* decl,CallSite* callSite) :
-            mContext(context), mSymbols(symbols), mPackageDecls(decl), mStringPool(stringPool),
-            mCallSite(callSite) {
+  ReferenceLinkerVisitor(IAaptContext* context, SymbolTable* symbols,
+                         StringPool* stringPool, xml::IPackageDeclStack* decl,
+                         CallSite* callSite)
+      : mContext(context),
+        mSymbols(symbols),
+        mPackageDecls(decl),
+        mStringPool(stringPool),
+        mCallSite(callSite) {}
+
+  void visit(Reference* ref) override {
+    if (!ReferenceLinker::linkReference(ref, mContext, mSymbols, mPackageDecls,
+                                        mCallSite)) {
+      mError = true;
+    }
+  }
+
+  /**
+   * We visit the Style specially because during this phase, values of
+   * attributes are
+   * all RawString values. Now that we are expected to resolve all symbols, we
+   * can
+   * lookup the attributes to find out which types are allowed for the
+   * attributes' values.
+   */
+  void visit(Style* style) override {
+    if (style->parent) {
+      visit(&style->parent.value());
     }
 
-    void visit(Reference* ref) override {
-        if (!ReferenceLinker::linkReference(ref, mContext, mSymbols, mPackageDecls, mCallSite)) {
-            mError = true;
-        }
-    }
+    for (Style::Entry& entry : style->entries) {
+      std::string errStr;
 
-    /**
-     * We visit the Style specially because during this phase, values of attributes are
-     * all RawString values. Now that we are expected to resolve all symbols, we can
-     * lookup the attributes to find out which types are allowed for the attributes' values.
-     */
-    void visit(Style* style) override {
-        if (style->parent) {
-            visit(&style->parent.value());
+      // Transform the attribute reference so that it is using the fully
+      // qualified package
+      // name. This will also mark the reference as being able to see private
+      // resources if
+      // there was a '*' in the reference or if the package came from the
+      // private namespace.
+      Reference transformedReference = entry.key;
+      transformReferenceFromNamespace(mPackageDecls,
+                                      mContext->getCompilationPackage(),
+                                      &transformedReference);
+
+      // Find the attribute in the symbol table and check if it is visible from
+      // this callsite.
+      const SymbolTable::Symbol* symbol =
+          ReferenceLinker::resolveAttributeCheckVisibility(
+              transformedReference, mContext->getNameMangler(), mSymbols,
+              mCallSite, &errStr);
+      if (symbol) {
+        // Assign our style key the correct ID.
+        // The ID may not exist.
+        entry.key.id = symbol->id;
+
+        // Try to convert the value to a more specific, typed value based on the
+        // attribute it is set to.
+        entry.value = parseValueWithAttribute(std::move(entry.value),
+                                              symbol->attribute.get());
+
+        // Link/resolve the final value (mostly if it's a reference).
+        entry.value->accept(this);
+
+        // Now verify that the type of this item is compatible with the
+        // attribute it
+        // is defined for. We pass `nullptr` as the DiagMessage so that this
+        // check is
+        // fast and we avoid creating a DiagMessage when the match is
+        // successful.
+        if (!symbol->attribute->matches(entry.value.get(), nullptr)) {
+          // The actual type of this item is incompatible with the attribute.
+          DiagMessage msg(entry.key.getSource());
+
+          // Call the matches method again, this time with a DiagMessage so we
+          // fill
+          // in the actual error message.
+          symbol->attribute->matches(entry.value.get(), &msg);
+          mContext->getDiagnostics()->error(msg);
+          mError = true;
         }
 
-        for (Style::Entry& entry : style->entries) {
-            std::string errStr;
+      } else {
+        DiagMessage msg(entry.key.getSource());
+        msg << "style attribute '";
+        ReferenceLinker::writeResourceName(&msg, entry.key,
+                                           transformedReference);
+        msg << "' " << errStr;
+        mContext->getDiagnostics()->error(msg);
+        mError = true;
+      }
+    }
+  }
 
-            // Transform the attribute reference so that it is using the fully qualified package
-            // name. This will also mark the reference as being able to see private resources if
-            // there was a '*' in the reference or if the package came from the private namespace.
-            Reference transformedReference = entry.key;
-            transformReferenceFromNamespace(mPackageDecls, mContext->getCompilationPackage(),
-                                            &transformedReference);
+  bool hasError() { return mError; }
 
-            // Find the attribute in the symbol table and check if it is visible from this callsite.
-            const SymbolTable::Symbol* symbol = ReferenceLinker::resolveAttributeCheckVisibility(
-                    transformedReference, mContext->getNameMangler(), mSymbols, mCallSite, &errStr);
-            if (symbol) {
-                // Assign our style key the correct ID.
-                // The ID may not exist.
-                entry.key.id = symbol->id;
+ private:
+  IAaptContext* mContext;
+  SymbolTable* mSymbols;
+  xml::IPackageDeclStack* mPackageDecls;
+  StringPool* mStringPool;
+  CallSite* mCallSite;
+  bool mError = false;
 
-                // Try to convert the value to a more specific, typed value based on the
-                // attribute it is set to.
-                entry.value = parseValueWithAttribute(std::move(entry.value),
-                                                      symbol->attribute.get());
+  /**
+   * Transform a RawString value into a more specific, appropriate value, based
+   * on the
+   * Attribute. If a non RawString value is passed in, this is an identity
+   * transform.
+   */
+  std::unique_ptr<Item> parseValueWithAttribute(std::unique_ptr<Item> value,
+                                                const Attribute* attr) {
+    if (RawString* rawString = valueCast<RawString>(value.get())) {
+      std::unique_ptr<Item> transformed =
+          ResourceUtils::tryParseItemForAttribute(*rawString->value, attr);
 
-                // Link/resolve the final value (mostly if it's a reference).
-                entry.value->accept(this);
-
-                // Now verify that the type of this item is compatible with the attribute it
-                // is defined for. We pass `nullptr` as the DiagMessage so that this check is
-                // fast and we avoid creating a DiagMessage when the match is successful.
-                if (!symbol->attribute->matches(entry.value.get(), nullptr)) {
-                    // The actual type of this item is incompatible with the attribute.
-                    DiagMessage msg(entry.key.getSource());
-
-                    // Call the matches method again, this time with a DiagMessage so we fill
-                    // in the actual error message.
-                    symbol->attribute->matches(entry.value.get(), &msg);
-                    mContext->getDiagnostics()->error(msg);
-                    mError = true;
-                }
-
-            } else {
-                DiagMessage msg(entry.key.getSource());
-                msg << "style attribute '";
-                ReferenceLinker::writeResourceName(&msg, entry.key, transformedReference);
-                msg << "' " << errStr;
-                mContext->getDiagnostics()->error(msg);
-                mError = true;
-            }
+      // If we could not parse as any specific type, try a basic STRING.
+      if (!transformed &&
+          (attr->typeMask & android::ResTable_map::TYPE_STRING)) {
+        util::StringBuilder stringBuilder;
+        stringBuilder.append(*rawString->value);
+        if (stringBuilder) {
+          transformed = util::make_unique<String>(
+              mStringPool->makeRef(stringBuilder.str()));
         }
-    }
+      }
 
-    bool hasError() {
-        return mError;
-    }
-
-private:
-    IAaptContext* mContext;
-    SymbolTable* mSymbols;
-    xml::IPackageDeclStack* mPackageDecls;
-    StringPool* mStringPool;
-    CallSite* mCallSite;
-    bool mError = false;
-
-    /**
-     * Transform a RawString value into a more specific, appropriate value, based on the
-     * Attribute. If a non RawString value is passed in, this is an identity transform.
-     */
-    std::unique_ptr<Item> parseValueWithAttribute(std::unique_ptr<Item> value,
-                                                  const Attribute* attr) {
-        if (RawString* rawString = valueCast<RawString>(value.get())) {
-            std::unique_ptr<Item> transformed =
-                    ResourceUtils::tryParseItemForAttribute(*rawString->value, attr);
-
-            // If we could not parse as any specific type, try a basic STRING.
-            if (!transformed && (attr->typeMask & android::ResTable_map::TYPE_STRING)) {
-                util::StringBuilder stringBuilder;
-                stringBuilder.append(*rawString->value);
-                if (stringBuilder) {
-                    transformed = util::make_unique<String>(
-                            mStringPool->makeRef(stringBuilder.str()));
-                }
-            }
-
-            if (transformed) {
-                return transformed;
-            }
-        };
-        return value;
-    }
+      if (transformed) {
+        return transformed;
+      }
+    };
+    return value;
+  }
 };
 
-} // namespace
+}  // namespace
 
 /**
- * The symbol is visible if it is public, or if the reference to it is requesting private access
+ * The symbol is visible if it is public, or if the reference to it is
+ * requesting private access
  * or if the callsite comes from the same package.
  */
-bool ReferenceLinker::isSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
+bool ReferenceLinker::isSymbolVisible(const SymbolTable::Symbol& symbol,
+                                      const Reference& ref,
                                       const CallSite& callSite) {
-    if (!symbol.isPublic && !ref.privateReference) {
-        if (ref.name) {
-            return callSite.resource.package == ref.name.value().package;
-        } else if (ref.id && symbol.id) {
-            return ref.id.value().packageId() == symbol.id.value().packageId();
-        } else {
-            return false;
-        }
+  if (!symbol.isPublic && !ref.privateReference) {
+    if (ref.name) {
+      return callSite.resource.package == ref.name.value().package;
+    } else if (ref.id && symbol.id) {
+      return ref.id.value().packageId() == symbol.id.value().packageId();
+    } else {
+      return false;
     }
-    return true;
+  }
+  return true;
 }
 
-const SymbolTable::Symbol* ReferenceLinker::resolveSymbol(const Reference& reference,
-                                                          NameMangler* mangler,
-                                                          SymbolTable* symbols) {
-    if (reference.name) {
-        Maybe<ResourceName> mangled = mangler->mangleName(reference.name.value());
-        return symbols->findByName(mangled ? mangled.value() : reference.name.value());
-    } else if (reference.id) {
-        return symbols->findById(reference.id.value());
-    } else {
-        return nullptr;
-    }
+const SymbolTable::Symbol* ReferenceLinker::resolveSymbol(
+    const Reference& reference, NameMangler* mangler, SymbolTable* symbols) {
+  if (reference.name) {
+    Maybe<ResourceName> mangled = mangler->mangleName(reference.name.value());
+    return symbols->findByName(mangled ? mangled.value()
+                                       : reference.name.value());
+  } else if (reference.id) {
+    return symbols->findById(reference.id.value());
+  } else {
+    return nullptr;
+  }
 }
 
 const SymbolTable::Symbol* ReferenceLinker::resolveSymbolCheckVisibility(
-        const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
-        CallSite* callSite, std::string* outError) {
-    const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
-    if (!symbol) {
-        if (outError) *outError = "not found";
-        return nullptr;
-    }
+    const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
+    CallSite* callSite, std::string* outError) {
+  const SymbolTable::Symbol* symbol =
+      resolveSymbol(reference, nameMangler, symbols);
+  if (!symbol) {
+    if (outError) *outError = "not found";
+    return nullptr;
+  }
 
-    if (!isSymbolVisible(*symbol, reference, *callSite)) {
-        if (outError) *outError = "is private";
-        return nullptr;
-    }
-    return symbol;
+  if (!isSymbolVisible(*symbol, reference, *callSite)) {
+    if (outError) *outError = "is private";
+    return nullptr;
+  }
+  return symbol;
 }
 
 const SymbolTable::Symbol* ReferenceLinker::resolveAttributeCheckVisibility(
-        const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
-        CallSite* callSite, std::string* outError) {
-    const SymbolTable::Symbol* symbol = resolveSymbolCheckVisibility(reference, nameMangler,
-                                                                     symbols, callSite,
-                                                                     outError);
-    if (!symbol) {
-        return nullptr;
-    }
+    const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
+    CallSite* callSite, std::string* outError) {
+  const SymbolTable::Symbol* symbol = resolveSymbolCheckVisibility(
+      reference, nameMangler, symbols, callSite, outError);
+  if (!symbol) {
+    return nullptr;
+  }
 
-    if (!symbol->attribute) {
-        if (outError) *outError = "is not an attribute";
-        return nullptr;
-    }
-    return symbol;
+  if (!symbol->attribute) {
+    if (outError) *outError = "is not an attribute";
+    return nullptr;
+  }
+  return symbol;
 }
 
-Maybe<xml::AaptAttribute> ReferenceLinker::compileXmlAttribute(const Reference& reference,
-                                                               NameMangler* nameMangler,
-                                                               SymbolTable* symbols,
-                                                               CallSite* callSite,
-                                                               std::string* outError) {
-    const SymbolTable::Symbol* symbol = resolveSymbol(reference, nameMangler, symbols);
-    if (!symbol) {
-        if (outError) *outError = "not found";
-        return {};
-    }
+Maybe<xml::AaptAttribute> ReferenceLinker::compileXmlAttribute(
+    const Reference& reference, NameMangler* nameMangler, SymbolTable* symbols,
+    CallSite* callSite, std::string* outError) {
+  const SymbolTable::Symbol* symbol =
+      resolveSymbol(reference, nameMangler, symbols);
+  if (!symbol) {
+    if (outError) *outError = "not found";
+    return {};
+  }
 
-    if (!symbol->attribute) {
-        if (outError) *outError = "is not an attribute";
-        return {};
-    }
-    return xml::AaptAttribute{ symbol->id, *symbol->attribute };
+  if (!symbol->attribute) {
+    if (outError) *outError = "is not an attribute";
+    return {};
+  }
+  return xml::AaptAttribute{symbol->id, *symbol->attribute};
 }
 
-void ReferenceLinker::writeResourceName(DiagMessage* outMsg, const Reference& orig,
+void ReferenceLinker::writeResourceName(DiagMessage* outMsg,
+                                        const Reference& orig,
                                         const Reference& transformed) {
-    assert(outMsg);
+  assert(outMsg);
 
-    if (orig.name) {
-        *outMsg << orig.name.value();
-        if (transformed.name.value() != orig.name.value()) {
-            *outMsg << " (aka " << transformed.name.value() << ")";
-        }
-    } else {
-        *outMsg << orig.id.value();
+  if (orig.name) {
+    *outMsg << orig.name.value();
+    if (transformed.name.value() != orig.name.value()) {
+      *outMsg << " (aka " << transformed.name.value() << ")";
     }
+  } else {
+    *outMsg << orig.id.value();
+  }
 }
 
 bool ReferenceLinker::linkReference(Reference* reference, IAaptContext* context,
-                                    SymbolTable* symbols, xml::IPackageDeclStack* decls,
+                                    SymbolTable* symbols,
+                                    xml::IPackageDeclStack* decls,
                                     CallSite* callSite) {
-    assert(reference);
-    assert(reference->name || reference->id);
+  assert(reference);
+  assert(reference->name || reference->id);
 
-    Reference transformedReference = *reference;
-    transformReferenceFromNamespace(decls, context->getCompilationPackage(),
-                                    &transformedReference);
+  Reference transformedReference = *reference;
+  transformReferenceFromNamespace(decls, context->getCompilationPackage(),
+                                  &transformedReference);
 
-    std::string errStr;
-    const SymbolTable::Symbol* s = resolveSymbolCheckVisibility(
-            transformedReference, context->getNameMangler(), symbols, callSite, &errStr);
-    if (s) {
-        // The ID may not exist. This is fine because of the possibility of building against
-        // libraries without assigned IDs.
-        // Ex: Linking against own resources when building a static library.
-        reference->id = s->id;
-        return true;
-    }
+  std::string errStr;
+  const SymbolTable::Symbol* s = resolveSymbolCheckVisibility(
+      transformedReference, context->getNameMangler(), symbols, callSite,
+      &errStr);
+  if (s) {
+    // The ID may not exist. This is fine because of the possibility of building
+    // against
+    // libraries without assigned IDs.
+    // Ex: Linking against own resources when building a static library.
+    reference->id = s->id;
+    return true;
+  }
 
-    DiagMessage errorMsg(reference->getSource());
-    errorMsg << "resource ";
-    writeResourceName(&errorMsg, *reference, transformedReference);
-    errorMsg << " " << errStr;
-    context->getDiagnostics()->error(errorMsg);
-    return false;
+  DiagMessage errorMsg(reference->getSource());
+  errorMsg << "resource ";
+  writeResourceName(&errorMsg, *reference, transformedReference);
+  errorMsg << " " << errStr;
+  context->getDiagnostics()->error(errorMsg);
+  return false;
 }
 
 namespace {
 
 struct EmptyDeclStack : public xml::IPackageDeclStack {
-    Maybe<xml::ExtractedPackage> transformPackageAlias(
-            const StringPiece& alias, const StringPiece& localPackage) const override {
-        if (alias.empty()) {
-            return xml::ExtractedPackage{ localPackage.toString(), true /* private */ };
-        }
-        return {};
+  Maybe<xml::ExtractedPackage> transformPackageAlias(
+      const StringPiece& alias,
+      const StringPiece& localPackage) const override {
+    if (alias.empty()) {
+      return xml::ExtractedPackage{localPackage.toString(), true /* private */};
     }
+    return {};
+  }
 };
 
-} // namespace
+}  // namespace
 
 bool ReferenceLinker::consume(IAaptContext* context, ResourceTable* table) {
-    EmptyDeclStack declStack;
-    bool error = false;
-    for (auto& package : table->packages) {
-        for (auto& type : package->types) {
-            for (auto& entry : type->entries) {
-                // Symbol state information may be lost if there is no value for the resource.
-                if (entry->symbolStatus.state != SymbolState::kUndefined && entry->values.empty()) {
-                    context->getDiagnostics()->error(
-                            DiagMessage(entry->symbolStatus.source)
-                            << "no definition for declared symbol '"
-                            << ResourceNameRef(package->name, type->type, entry->name)
-                            << "'");
-                    error = true;
-                }
-
-                CallSite callSite = { ResourceNameRef(package->name, type->type, entry->name) };
-                ReferenceLinkerVisitor visitor(context, context->getExternalSymbols(),
-                                               &table->stringPool, &declStack, &callSite);
-
-                for (auto& configValue : entry->values) {
-                    configValue->value->accept(&visitor);
-                }
-
-                if (visitor.hasError()) {
-                    error = true;
-                }
-            }
+  EmptyDeclStack declStack;
+  bool error = false;
+  for (auto& package : table->packages) {
+    for (auto& type : package->types) {
+      for (auto& entry : type->entries) {
+        // Symbol state information may be lost if there is no value for the
+        // resource.
+        if (entry->symbolStatus.state != SymbolState::kUndefined &&
+            entry->values.empty()) {
+          context->getDiagnostics()->error(
+              DiagMessage(entry->symbolStatus.source)
+              << "no definition for declared symbol '"
+              << ResourceNameRef(package->name, type->type, entry->name)
+              << "'");
+          error = true;
         }
+
+        CallSite callSite = {
+            ResourceNameRef(package->name, type->type, entry->name)};
+        ReferenceLinkerVisitor visitor(context, context->getExternalSymbols(),
+                                       &table->stringPool, &declStack,
+                                       &callSite);
+
+        for (auto& configValue : entry->values) {
+          configValue->value->accept(&visitor);
+        }
+
+        if (visitor.hasError()) {
+          error = true;
+        }
+      }
     }
-    return !error;
+  }
+  return !error;
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/ReferenceLinker.h b/tools/aapt2/link/ReferenceLinker.h
index 7993aaf..8f6604f 100644
--- a/tools/aapt2/link/ReferenceLinker.h
+++ b/tools/aapt2/link/ReferenceLinker.h
@@ -30,77 +30,86 @@
 namespace aapt {
 
 /**
- * Resolves all references to resources in the ResourceTable and assigns them IDs.
+ * Resolves all references to resources in the ResourceTable and assigns them
+ * IDs.
  * The ResourceTable must already have IDs assigned to each resource.
- * Once the ResourceTable is processed by this linker, it is ready to be flattened.
+ * Once the ResourceTable is processed by this linker, it is ready to be
+ * flattened.
  */
 struct ReferenceLinker : public IResourceTableConsumer {
-    /**
-     * Returns true if the symbol is visible by the reference and from the callsite.
-     */
-    static bool isSymbolVisible(const SymbolTable::Symbol& symbol, const Reference& ref,
-                                const CallSite& callSite);
+  /**
+   * Returns true if the symbol is visible by the reference and from the
+   * callsite.
+   */
+  static bool isSymbolVisible(const SymbolTable::Symbol& symbol,
+                              const Reference& ref, const CallSite& callSite);
 
-    /**
-     * Performs name mangling and looks up the resource in the symbol table. Returns nullptr
-     * if the symbol was not found.
-     */
-    static const SymbolTable::Symbol* resolveSymbol(const Reference& reference,
-                                                    NameMangler* mangler, SymbolTable* symbols);
+  /**
+   * Performs name mangling and looks up the resource in the symbol table.
+   * Returns nullptr
+   * if the symbol was not found.
+   */
+  static const SymbolTable::Symbol* resolveSymbol(const Reference& reference,
+                                                  NameMangler* mangler,
+                                                  SymbolTable* symbols);
 
-    /**
-     * Performs name mangling and looks up the resource in the symbol table. If the symbol is
-     * not visible by the reference at the callsite, nullptr is returned. outError holds
-     * the error message.
-     */
-    static const SymbolTable::Symbol* resolveSymbolCheckVisibility(const Reference& reference,
-                                                                   NameMangler* nameMangler,
-                                                                   SymbolTable* symbols,
-                                                                   CallSite* callSite,
-                                                                   std::string* outError);
+  /**
+   * Performs name mangling and looks up the resource in the symbol table. If
+   * the symbol is
+   * not visible by the reference at the callsite, nullptr is returned. outError
+   * holds
+   * the error message.
+   */
+  static const SymbolTable::Symbol* resolveSymbolCheckVisibility(
+      const Reference& reference, NameMangler* nameMangler,
+      SymbolTable* symbols, CallSite* callSite, std::string* outError);
 
-    /**
-     * Same as resolveSymbolCheckVisibility(), but also makes sure the symbol is an attribute.
-     * That is, the return value will have a non-null value for ISymbolTable::Symbol::attribute.
-     */
-    static const SymbolTable::Symbol* resolveAttributeCheckVisibility(const Reference& reference,
-                                                                      NameMangler* nameMangler,
-                                                                      SymbolTable* symbols,
-                                                                      CallSite* callSite,
-                                                                      std::string* outError);
+  /**
+   * Same as resolveSymbolCheckVisibility(), but also makes sure the symbol is
+   * an attribute.
+   * That is, the return value will have a non-null value for
+   * ISymbolTable::Symbol::attribute.
+   */
+  static const SymbolTable::Symbol* resolveAttributeCheckVisibility(
+      const Reference& reference, NameMangler* nameMangler,
+      SymbolTable* symbols, CallSite* callSite, std::string* outError);
 
-    /**
-     * Resolves the attribute reference and returns an xml::AaptAttribute if successful.
-     * If resolution fails, outError holds the error message.
-     */
-    static Maybe<xml::AaptAttribute> compileXmlAttribute(const Reference& reference,
-                                                         NameMangler* nameMangler,
-                                                         SymbolTable* symbols,
-                                                         CallSite* callSite,
-                                                         std::string* outError);
+  /**
+   * Resolves the attribute reference and returns an xml::AaptAttribute if
+   * successful.
+   * If resolution fails, outError holds the error message.
+   */
+  static Maybe<xml::AaptAttribute> compileXmlAttribute(
+      const Reference& reference, NameMangler* nameMangler,
+      SymbolTable* symbols, CallSite* callSite, std::string* outError);
 
-    /**
-     * Writes the resource name to the DiagMessage, using the "orig_name (aka <transformed_name>)"
-     * syntax.
-     */
-    static void writeResourceName(DiagMessage* outMsg, const Reference& orig,
-                                  const Reference& transformed);
+  /**
+   * Writes the resource name to the DiagMessage, using the "orig_name (aka
+   * <transformed_name>)"
+   * syntax.
+   */
+  static void writeResourceName(DiagMessage* outMsg, const Reference& orig,
+                                const Reference& transformed);
 
-    /**
-     * Transforms the package name of the reference to the fully qualified package name using
-     * the xml::IPackageDeclStack, then mangles and looks up the symbol. If the symbol is visible
-     * to the reference at the callsite, the reference is updated with an ID.
-     * Returns false on failure, and an error message is logged to the IDiagnostics in the context.
-     */
-    static bool linkReference(Reference* reference, IAaptContext* context, SymbolTable* symbols,
-                              xml::IPackageDeclStack* decls, CallSite* callSite);
+  /**
+   * Transforms the package name of the reference to the fully qualified package
+   * name using
+   * the xml::IPackageDeclStack, then mangles and looks up the symbol. If the
+   * symbol is visible
+   * to the reference at the callsite, the reference is updated with an ID.
+   * Returns false on failure, and an error message is logged to the
+   * IDiagnostics in the context.
+   */
+  static bool linkReference(Reference* reference, IAaptContext* context,
+                            SymbolTable* symbols, xml::IPackageDeclStack* decls,
+                            CallSite* callSite);
 
-    /**
-     * Links all references in the ResourceTable.
-     */
-    bool consume(IAaptContext* context, ResourceTable* table) override;
+  /**
+   * Links all references in the ResourceTable.
+   */
+  bool consume(IAaptContext* context, ResourceTable* table) override;
 };
 
-} // namespace aapt
+}  // namespace aapt
 
 #endif /* AAPT_LINKER_REFERENCELINKER_H */
diff --git a/tools/aapt2/link/ReferenceLinker_test.cpp b/tools/aapt2/link/ReferenceLinker_test.cpp
index 5c1511f..8aa3616 100644
--- a/tools/aapt2/link/ReferenceLinker_test.cpp
+++ b/tools/aapt2/link/ReferenceLinker_test.cpp
@@ -22,206 +22,238 @@
 namespace aapt {
 
 TEST(ReferenceLinkerTest, LinkSimpleReferences) {
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId("com.app.test", 0x7f)
-            .addReference("com.app.test:string/foo", ResourceId(0x7f020000),
-                          "com.app.test:string/bar")
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .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("com.app.test:string/bar", ResourceId(0x7f020001), "string/baz")
+          // Test use of local reference (w/o package name).
+          .addReference("com.app.test:string/bar", ResourceId(0x7f020001),
+                        "string/baz")
 
-            .addReference("com.app.test:string/baz", ResourceId(0x7f020002),
-                          "android:string/ok")
-            .build();
+          .addReference("com.app.test:string/baz", ResourceId(0x7f020002),
+                        "android:string/ok")
+          .build();
 
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage("com.app.test")
-            .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
-            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addPublicSymbol("android:string/ok", ResourceId(0x01040034))
-                                     .build())
-            .build();
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder()
+          .setCompilationPackage("com.app.test")
+          .setPackageId(0x7f)
+          .setNameManglerPolicy(NameManglerPolicy{"com.app.test"})
+          .addSymbolSource(
+              util::make_unique<ResourceTableSymbolSource>(table.get()))
+          .addSymbolSource(
+              test::StaticSymbolSourceBuilder()
+                  .addPublicSymbol("android:string/ok", ResourceId(0x01040034))
+                  .build())
+          .build();
 
-    ReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(context.get(), table.get()));
+  ReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(context.get(), table.get()));
 
-    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));
+  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(), "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(), "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(), "com.app.test:string/baz");
-    ASSERT_NE(ref, nullptr);
-    AAPT_ASSERT_TRUE(ref->id);
-    EXPECT_EQ(ref->id.value(), ResourceId(0x01040034));
+  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));
 }
 
 TEST(ReferenceLinkerTest, LinkStyleAttributes) {
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .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();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .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(), "com.app.test:style/Theme");
-        ASSERT_NE(style, nullptr);
-        style->entries.back().value = util::make_unique<RawString>(
-                table->stringPool.makeRef("one|two"));
-    }
-
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage("com.app.test")
-            .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
-            .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addPublicSymbol("android:style/Theme.Material",
-                                                      ResourceId(0x01060000))
-                                     .addPublicSymbol("android:attr/foo", ResourceId(0x01010001),
-                                                      test::AttributeBuilder()
-                                                              .setTypeMask(ResTable_map::TYPE_COLOR)
-                                                              .build())
-                                     .addPublicSymbol("android:attr/bar", ResourceId(0x01010002),
-                                                      test::AttributeBuilder()
-                                                              .setTypeMask(ResTable_map::TYPE_FLAGS)
-                                                              .addItem("one", 0x01)
-                                                              .addItem("two", 0x02)
-                                                              .build())
-                                     .build())
-            .build();
-
-    ReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(context.get(), table.get()));
-
-    Style* style = test::getValue<Style>(table.get(), "com.app.test:style/Theme");
+  {
+    // 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(), "com.app.test:style/Theme");
     ASSERT_NE(style, nullptr);
-    AAPT_ASSERT_TRUE(style->parent);
-    AAPT_ASSERT_TRUE(style->parent.value().id);
-    EXPECT_EQ(style->parent.value().id.value(), ResourceId(0x01060000));
+    style->entries.back().value =
+        util::make_unique<RawString>(table->stringPool.makeRef("one|two"));
+  }
 
-    ASSERT_EQ(2u, style->entries.size());
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder()
+          .setCompilationPackage("com.app.test")
+          .setPackageId(0x7f)
+          .setNameManglerPolicy(NameManglerPolicy{"com.app.test"})
+          .addSymbolSource(
+              test::StaticSymbolSourceBuilder()
+                  .addPublicSymbol("android:style/Theme.Material",
+                                   ResourceId(0x01060000))
+                  .addPublicSymbol("android:attr/foo", ResourceId(0x01010001),
+                                   test::AttributeBuilder()
+                                       .setTypeMask(ResTable_map::TYPE_COLOR)
+                                       .build())
+                  .addPublicSymbol("android:attr/bar", ResourceId(0x01010002),
+                                   test::AttributeBuilder()
+                                       .setTypeMask(ResTable_map::TYPE_FLAGS)
+                                       .addItem("one", 0x01)
+                                       .addItem("two", 0x02)
+                                       .build())
+                  .build())
+          .build();
 
-    AAPT_ASSERT_TRUE(style->entries[0].key.id);
-    EXPECT_EQ(style->entries[0].key.id.value(), ResourceId(0x01010001));
-    ASSERT_NE(valueCast<BinaryPrimitive>(style->entries[0].value.get()), nullptr);
+  ReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(context.get(), table.get()));
 
-    AAPT_ASSERT_TRUE(style->entries[1].key.id);
-    EXPECT_EQ(style->entries[1].key.id.value(), ResourceId(0x01010002));
-    ASSERT_NE(valueCast<BinaryPrimitive>(style->entries[1].value.get()), nullptr);
+  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);
+  EXPECT_EQ(style->parent.value().id.value(), ResourceId(0x01060000));
+
+  ASSERT_EQ(2u, style->entries.size());
+
+  AAPT_ASSERT_TRUE(style->entries[0].key.id);
+  EXPECT_EQ(style->entries[0].key.id.value(), ResourceId(0x01010001));
+  ASSERT_NE(valueCast<BinaryPrimitive>(style->entries[0].value.get()), nullptr);
+
+  AAPT_ASSERT_TRUE(style->entries[1].key.id);
+  EXPECT_EQ(style->entries[1].key.id.value(), ResourceId(0x01010002));
+  ASSERT_NE(valueCast<BinaryPrimitive>(style->entries[1].value.get()), nullptr);
 }
 
 TEST(ReferenceLinkerTest, LinkMangledReferencesAndAttributes) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder()
-            .setCompilationPackage("com.app.test")
-            .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test", { "com.android.support" } })
-            .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addPublicSymbol("com.app.test:attr/com.android.support$foo",
-                                                      ResourceId(0x7f010000),
-                                                      test::AttributeBuilder()
-                                                              .setTypeMask(ResTable_map::TYPE_COLOR)
-                                                              .build())
-                                     .build())
-            .build();
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder()
+          .setCompilationPackage("com.app.test")
+          .setPackageId(0x7f)
+          .setNameManglerPolicy(
+              NameManglerPolicy{"com.app.test", {"com.android.support"}})
+          .addSymbolSource(
+              test::StaticSymbolSourceBuilder()
+                  .addPublicSymbol("com.app.test:attr/com.android.support$foo",
+                                   ResourceId(0x7f010000),
+                                   test::AttributeBuilder()
+                                       .setTypeMask(ResTable_map::TYPE_COLOR)
+                                       .build())
+                  .build())
+          .build();
 
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .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();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .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()));
+  ReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(context.get(), table.get()));
 
-    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);
-    EXPECT_EQ(style->entries.front().key.id.value(), ResourceId(0x7f010000));
+  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);
+  EXPECT_EQ(style->entries.front().key.id.value(), ResourceId(0x7f010000));
 }
 
 TEST(ReferenceLinkerTest, FailToLinkPrivateSymbols) {
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId("com.app.test", 0x7f)
-            .addReference("com.app.test:string/foo", ResourceId(0x7f020000),
-                          "android:string/hidden")
-            .build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .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("com.app.test")
-            .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
-            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addSymbol("android:string/hidden", ResourceId(0x01040034))
-                                     .build())
-            .build();
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder()
+          .setCompilationPackage("com.app.test")
+          .setPackageId(0x7f)
+          .setNameManglerPolicy(NameManglerPolicy{"com.app.test"})
+          .addSymbolSource(
+              util::make_unique<ResourceTableSymbolSource>(table.get()))
+          .addSymbolSource(
+              test::StaticSymbolSourceBuilder()
+                  .addSymbol("android:string/hidden", ResourceId(0x01040034))
+                  .build())
+          .build();
 
-    ReferenceLinker linker;
-    ASSERT_FALSE(linker.consume(context.get(), table.get()));
+  ReferenceLinker linker;
+  ASSERT_FALSE(linker.consume(context.get(), table.get()));
 }
 
 TEST(ReferenceLinkerTest, FailToLinkPrivateMangledSymbols) {
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .setPackageId("com.app.test", 0x7f)
-            .addReference("com.app.test:string/foo", ResourceId(0x7f020000),
-                          "com.app.lib:string/hidden")
-            .build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .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("com.app.test")
-            .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test", { "com.app.lib" } })
-            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addSymbol("com.app.test:string/com.app.lib$hidden",
-                                                ResourceId(0x7f040034))
-                                     .build())
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder()
+          .setCompilationPackage("com.app.test")
+          .setPackageId(0x7f)
+          .setNameManglerPolicy(
+              NameManglerPolicy{"com.app.test", {"com.app.lib"}})
+          .addSymbolSource(
+              util::make_unique<ResourceTableSymbolSource>(table.get()))
+          .addSymbolSource(
+              test::StaticSymbolSourceBuilder()
+                  .addSymbol("com.app.test:string/com.app.lib$hidden",
+                             ResourceId(0x7f040034))
+                  .build())
 
-            .build();
+          .build();
 
-    ReferenceLinker linker;
-    ASSERT_FALSE(linker.consume(context.get(), table.get()));
+  ReferenceLinker linker;
+  ASSERT_FALSE(linker.consume(context.get(), table.get()));
 }
 
 TEST(ReferenceLinkerTest, FailToLinkPrivateStyleAttributes) {
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .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<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .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("com.app.test")
-            .setPackageId(0x7f)
-            .setNameManglerPolicy(NameManglerPolicy{ "com.app.test" })
-            .addSymbolSource(util::make_unique<ResourceTableSymbolSource>(table.get()))
-            .addSymbolSource(test::StaticSymbolSourceBuilder()
-                                     .addSymbol("android:attr/hidden", ResourceId(0x01010001),
-                                                test::AttributeBuilder()
-                                                        .setTypeMask(
-                                                                android::ResTable_map::TYPE_COLOR)
-                                                        .build())
-                                     .build())
-            .build();
+  std::unique_ptr<IAaptContext> context =
+      test::ContextBuilder()
+          .setCompilationPackage("com.app.test")
+          .setPackageId(0x7f)
+          .setNameManglerPolicy(NameManglerPolicy{"com.app.test"})
+          .addSymbolSource(
+              util::make_unique<ResourceTableSymbolSource>(table.get()))
+          .addSymbolSource(
+              test::StaticSymbolSourceBuilder()
+                  .addSymbol("android:attr/hidden", ResourceId(0x01010001),
+                             test::AttributeBuilder()
+                                 .setTypeMask(android::ResTable_map::TYPE_COLOR)
+                                 .build())
+                  .build())
+          .build();
 
-    ReferenceLinker linker;
-    ASSERT_FALSE(linker.consume(context.get(), table.get()));
+  ReferenceLinker linker;
+  ASSERT_FALSE(linker.consume(context.get(), table.get()));
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/ResourceDeduper.cpp b/tools/aapt2/link/ResourceDeduper.cpp
index 0276261..f565359 100644
--- a/tools/aapt2/link/ResourceDeduper.cpp
+++ b/tools/aapt2/link/ResourceDeduper.cpp
@@ -36,79 +36,81 @@
  *    an equivalent entry value.
  */
 class DominatedKeyValueRemover : public DominatorTree::BottomUpVisitor {
-public:
-    using Node = DominatorTree::Node;
+ public:
+  using Node = DominatorTree::Node;
 
-    explicit DominatedKeyValueRemover(IAaptContext* context, ResourceEntry* entry) :
-            mContext(context), mEntry(entry) {
+  explicit DominatedKeyValueRemover(IAaptContext* context, ResourceEntry* entry)
+      : mContext(context), mEntry(entry) {}
+
+  void visitConfig(Node* node) {
+    Node* parent = node->parent();
+    if (!parent) {
+      return;
+    }
+    ResourceConfigValue* nodeValue = node->value();
+    ResourceConfigValue* parentValue = parent->value();
+    if (!nodeValue || !parentValue) {
+      return;
+    }
+    if (!nodeValue->value->equals(parentValue->value.get())) {
+      return;
     }
 
-    void visitConfig(Node* node) {
-        Node* parent = node->parent();
-        if (!parent) {
-            return;
-        }
-        ResourceConfigValue* nodeValue = node->value();
-        ResourceConfigValue* parentValue = parent->value();
-        if (!nodeValue || !parentValue) {
-            return;
-        }
-        if (!nodeValue->value->equals(parentValue->value.get())) {
-            return;
-        }
-
-        // Compare compatible configs for this entry and ensure the values are
-        // equivalent.
-        const ConfigDescription& nodeConfiguration = nodeValue->config;
-        for (const auto& sibling : mEntry->values) {
-            if (!sibling->value) {
-                // Sibling was already removed.
-                continue;
-            }
-            if (nodeConfiguration.isCompatibleWith(sibling->config)
-                    && !nodeValue->value->equals(sibling->value.get())) {
-                // The configurations are compatible, but the value is
-                // different, so we can't remove this value.
-                return;
-            }
-        }
-        if (mContext->verbose()) {
-            mContext->getDiagnostics()->note(
-                    DiagMessage(nodeValue->value->getSource())
-                            << "removing dominated duplicate resource with name \""
-                            << mEntry->name << "\"");
-        }
-        nodeValue->value = {};
+    // Compare compatible configs for this entry and ensure the values are
+    // equivalent.
+    const ConfigDescription& nodeConfiguration = nodeValue->config;
+    for (const auto& sibling : mEntry->values) {
+      if (!sibling->value) {
+        // Sibling was already removed.
+        continue;
+      }
+      if (nodeConfiguration.isCompatibleWith(sibling->config) &&
+          !nodeValue->value->equals(sibling->value.get())) {
+        // The configurations are compatible, but the value is
+        // different, so we can't remove this value.
+        return;
+      }
     }
+    if (mContext->verbose()) {
+      mContext->getDiagnostics()->note(
+          DiagMessage(nodeValue->value->getSource())
+          << "removing dominated duplicate resource with name \""
+          << mEntry->name << "\"");
+    }
+    nodeValue->value = {};
+  }
 
-private:
-    IAaptContext* mContext;
-    ResourceEntry* mEntry;
+ private:
+  IAaptContext* mContext;
+  ResourceEntry* mEntry;
 };
 
 static void dedupeEntry(IAaptContext* context, ResourceEntry* entry) {
-    DominatorTree tree(entry->values);
-    DominatedKeyValueRemover remover(context, entry);
-    tree.accept(&remover);
+  DominatorTree tree(entry->values);
+  DominatedKeyValueRemover remover(context, entry);
+  tree.accept(&remover);
 
-    // Erase the values that were removed.
-    entry->values.erase(std::remove_if(entry->values.begin(), entry->values.end(),
-            [](const std::unique_ptr<ResourceConfigValue>& val) -> bool {
-        return val == nullptr || val->value == nullptr;
-    }), entry->values.end());
+  // Erase the values that were removed.
+  entry->values.erase(
+      std::remove_if(
+          entry->values.begin(), entry->values.end(),
+          [](const std::unique_ptr<ResourceConfigValue>& val) -> bool {
+            return val == nullptr || val->value == nullptr;
+          }),
+      entry->values.end());
 }
 
-} // namespace
+}  // namespace
 
 bool ResourceDeduper::consume(IAaptContext* context, ResourceTable* table) {
-    for (auto& package : table->packages) {
-        for (auto& type : package->types) {
-            for (auto& entry : type->entries) {
-                dedupeEntry(context, entry.get());
-            }
-        }
+  for (auto& package : table->packages) {
+    for (auto& type : package->types) {
+      for (auto& entry : type->entries) {
+        dedupeEntry(context, entry.get());
+      }
     }
-    return true;
+  }
+  return true;
 }
 
-} // aapt
+}  // aapt
diff --git a/tools/aapt2/link/ResourceDeduper_test.cpp b/tools/aapt2/link/ResourceDeduper_test.cpp
index 47071a51..7e2d476 100644
--- a/tools/aapt2/link/ResourceDeduper_test.cpp
+++ b/tools/aapt2/link/ResourceDeduper_test.cpp
@@ -21,63 +21,63 @@
 namespace aapt {
 
 TEST(ResourceDeduperTest, SameValuesAreDeduped) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
-    const ConfigDescription defaultConfig = {};
-    const ConfigDescription enConfig = test::parseConfigOrDie("en");
-    const ConfigDescription enV21Config = test::parseConfigOrDie("en-v21");
-    // Chosen because this configuration is compatible with en.
-    const ConfigDescription landConfig = test::parseConfigOrDie("land");
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+  const ConfigDescription defaultConfig = {};
+  const ConfigDescription enConfig = test::parseConfigOrDie("en");
+  const ConfigDescription enV21Config = test::parseConfigOrDie("en-v21");
+  // Chosen because this configuration is compatible with en.
+  const ConfigDescription landConfig = test::parseConfigOrDie("land");
 
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addString("android:string/dedupe", ResourceId{}, defaultConfig, "dedupe")
-            .addString("android:string/dedupe", ResourceId{}, enConfig, "dedupe")
-            .addString("android:string/dedupe", ResourceId{}, landConfig, "dedupe")
-            .addString("android:string/dedupe2", ResourceId{}, defaultConfig, "dedupe")
-            .addString("android:string/dedupe2", ResourceId{}, enConfig, "dedupe")
-            .addString("android:string/dedupe2", ResourceId{}, enV21Config, "keep")
-            .addString("android:string/dedupe2", ResourceId{}, landConfig, "dedupe")
-            .build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .addString("android:string/dedupe", ResourceId{}, defaultConfig,
+                     "dedupe")
+          .addString("android:string/dedupe", ResourceId{}, enConfig, "dedupe")
+          .addString("android:string/dedupe", ResourceId{}, landConfig,
+                     "dedupe")
+          .addString("android:string/dedupe2", ResourceId{}, defaultConfig,
+                     "dedupe")
+          .addString("android:string/dedupe2", ResourceId{}, enConfig, "dedupe")
+          .addString("android:string/dedupe2", ResourceId{}, enV21Config,
+                     "keep")
+          .addString("android:string/dedupe2", ResourceId{}, landConfig,
+                     "dedupe")
+          .build();
 
-    ASSERT_TRUE(ResourceDeduper().consume(context.get(), table.get()));
-    EXPECT_EQ(
-            nullptr,
-            test::getValueForConfig<String>(table.get(), "android:string/dedupe", enConfig));
-    EXPECT_EQ(
-            nullptr,
-            test::getValueForConfig<String>(table.get(), "android:string/dedupe", landConfig));
-    EXPECT_EQ(
-            nullptr,
-            test::getValueForConfig<String>(table.get(), "android:string/dedupe2", enConfig));
-    EXPECT_NE(
-            nullptr,
-            test::getValueForConfig<String>(table.get(), "android:string/dedupe2", enV21Config));
+  ASSERT_TRUE(ResourceDeduper().consume(context.get(), table.get()));
+  EXPECT_EQ(nullptr, test::getValueForConfig<String>(
+                         table.get(), "android:string/dedupe", enConfig));
+  EXPECT_EQ(nullptr, test::getValueForConfig<String>(
+                         table.get(), "android:string/dedupe", landConfig));
+  EXPECT_EQ(nullptr, test::getValueForConfig<String>(
+                         table.get(), "android:string/dedupe2", enConfig));
+  EXPECT_NE(nullptr, test::getValueForConfig<String>(
+                         table.get(), "android:string/dedupe2", enV21Config));
 }
 
 TEST(ResourceDeduperTest, DifferentValuesAreKept) {
-    std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
-    const ConfigDescription defaultConfig = {};
-    const ConfigDescription enConfig = test::parseConfigOrDie("en");
-    const ConfigDescription enV21Config = test::parseConfigOrDie("en-v21");
-    // Chosen because this configuration is compatible with en.
-    const ConfigDescription landConfig = test::parseConfigOrDie("land");
+  std::unique_ptr<IAaptContext> context = test::ContextBuilder().build();
+  const ConfigDescription defaultConfig = {};
+  const ConfigDescription enConfig = test::parseConfigOrDie("en");
+  const ConfigDescription enV21Config = test::parseConfigOrDie("en-v21");
+  // Chosen because this configuration is compatible with en.
+  const ConfigDescription landConfig = test::parseConfigOrDie("land");
 
-    std::unique_ptr<ResourceTable> table = test::ResourceTableBuilder()
-            .addString("android:string/keep", ResourceId{}, defaultConfig, "keep")
-            .addString("android:string/keep", ResourceId{}, enConfig, "keep")
-            .addString("android:string/keep", ResourceId{}, enV21Config, "keep2")
-            .addString("android:string/keep", ResourceId{}, landConfig, "keep2")
-            .build();
+  std::unique_ptr<ResourceTable> table =
+      test::ResourceTableBuilder()
+          .addString("android:string/keep", ResourceId{}, defaultConfig, "keep")
+          .addString("android:string/keep", ResourceId{}, enConfig, "keep")
+          .addString("android:string/keep", ResourceId{}, enV21Config, "keep2")
+          .addString("android:string/keep", ResourceId{}, landConfig, "keep2")
+          .build();
 
-    ASSERT_TRUE(ResourceDeduper().consume(context.get(), table.get()));
-    EXPECT_NE(
-            nullptr,
-            test::getValueForConfig<String>(table.get(), "android:string/keep", enConfig));
-    EXPECT_NE(
-            nullptr,
-            test::getValueForConfig<String>(table.get(), "android:string/keep", enV21Config));
-    EXPECT_NE(
-            nullptr,
-            test::getValueForConfig<String>(table.get(), "android:string/keep", landConfig));
+  ASSERT_TRUE(ResourceDeduper().consume(context.get(), table.get()));
+  EXPECT_NE(nullptr, test::getValueForConfig<String>(
+                         table.get(), "android:string/keep", enConfig));
+  EXPECT_NE(nullptr, test::getValueForConfig<String>(
+                         table.get(), "android:string/keep", enV21Config));
+  EXPECT_NE(nullptr, test::getValueForConfig<String>(
+                         table.get(), "android:string/keep", landConfig));
 }
 
 }  // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.cpp b/tools/aapt2/link/TableMerger.cpp
index eea4306..adf83a4 100644
--- a/tools/aapt2/link/TableMerger.cpp
+++ b/tools/aapt2/link/TableMerger.cpp
@@ -14,11 +14,11 @@
  * limitations under the License.
  */
 
+#include "link/TableMerger.h"
 #include "ResourceTable.h"
 #include "ResourceUtils.h"
 #include "ResourceValues.h"
 #include "ValueVisitor.h"
-#include "link/TableMerger.h"
 #include "util/Util.h"
 
 #include <cassert>
@@ -26,348 +26,365 @@
 namespace aapt {
 
 TableMerger::TableMerger(IAaptContext* context, ResourceTable* outTable,
-                         const TableMergerOptions& options) :
-        mContext(context), mMasterTable(outTable), mOptions(options) {
-    // Create the desired package that all tables will be merged into.
-    mMasterPackage = mMasterTable->createPackage(
-            mContext->getCompilationPackage(), mContext->getPackageId());
-    assert(mMasterPackage && "package name or ID already taken");
+                         const TableMergerOptions& options)
+    : mContext(context), mMasterTable(outTable), mOptions(options) {
+  // Create the desired package that all tables will be merged into.
+  mMasterPackage = mMasterTable->createPackage(
+      mContext->getCompilationPackage(), mContext->getPackageId());
+  assert(mMasterPackage && "package name or ID already taken");
 }
 
 bool TableMerger::merge(const Source& src, ResourceTable* table,
                         io::IFileCollection* collection) {
-    return mergeImpl(src, table, collection, false /* overlay */, true /* allow new */);
+  return mergeImpl(src, table, collection, false /* overlay */,
+                   true /* allow new */);
 }
 
 bool TableMerger::mergeOverlay(const Source& src, ResourceTable* table,
                                io::IFileCollection* collection) {
-    return mergeImpl(src, table, collection, true /* overlay */, mOptions.autoAddOverlay);
+  return mergeImpl(src, table, collection, true /* overlay */,
+                   mOptions.autoAddOverlay);
 }
 
 /**
  * This will merge packages with the same package name (or no package name).
  */
 bool TableMerger::mergeImpl(const Source& src, ResourceTable* table,
-                            io::IFileCollection* collection,
-                            bool overlay, bool allowNew) {
-    const uint8_t desiredPackageId = mContext->getPackageId();
+                            io::IFileCollection* collection, bool overlay,
+                            bool allowNew) {
+  const uint8_t desiredPackageId = mContext->getPackageId();
 
-    bool error = false;
-    for (auto& package : table->packages) {
-        // Warn of packages with an unrelated ID.
-        const Maybe<ResourceId>& id = package->id;
-        if (id && id.value() != 0x0 && id.value() != desiredPackageId) {
-            mContext->getDiagnostics()->warn(DiagMessage(src)
-                                             << "ignoring package " << package->name);
-            continue;
-        }
-
-        // Only merge an empty package or the package we're building.
-        // Other packages may exist, which likely contain attribute definitions.
-        // This is because at compile time it is unknown if the attributes are simply
-        // uses of the attribute or definitions.
-        if (package->name.empty() || mContext->getCompilationPackage() == package->name) {
-            FileMergeCallback callback;
-            if (collection) {
-                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(*oldFile->path);
-                    if (!f) {
-                        mContext->getDiagnostics()->error(DiagMessage(src) << "file '"
-                                                          << *oldFile->path
-                                                          << "' not found");
-                        return false;
-                    }
-
-                    newFile->file = f;
-                    return true;
-                };
-            }
-
-            // Merge here. Once the entries are merged and mangled, any references to
-            // them are still valid. This is because un-mangled references are
-            // mangled, then looked up at resolution time.
-            // Also, when linking, we convert references with no package name to use
-            // the compilation package name.
-            error |= !doMerge(src, table, package.get(), false /* mangle */, overlay, allowNew,
-                              callback);
-        }
+  bool error = false;
+  for (auto& package : table->packages) {
+    // Warn of packages with an unrelated ID.
+    const Maybe<ResourceId>& id = package->id;
+    if (id && id.value() != 0x0 && id.value() != desiredPackageId) {
+      mContext->getDiagnostics()->warn(DiagMessage(src) << "ignoring package "
+                                                        << package->name);
+      continue;
     }
-    return !error;
+
+    // Only merge an empty package or the package we're building.
+    // Other packages may exist, which likely contain attribute definitions.
+    // This is because at compile time it is unknown if the attributes are
+    // simply
+    // uses of the attribute or definitions.
+    if (package->name.empty() ||
+        mContext->getCompilationPackage() == package->name) {
+      FileMergeCallback callback;
+      if (collection) {
+        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(*oldFile->path);
+          if (!f) {
+            mContext->getDiagnostics()->error(DiagMessage(src)
+                                              << "file '" << *oldFile->path
+                                              << "' not found");
+            return false;
+          }
+
+          newFile->file = f;
+          return true;
+        };
+      }
+
+      // Merge here. Once the entries are merged and mangled, any references to
+      // them are still valid. This is because un-mangled references are
+      // mangled, then looked up at resolution time.
+      // Also, when linking, we convert references with no package name to use
+      // the compilation package name.
+      error |= !doMerge(src, table, package.get(), false /* mangle */, overlay,
+                        allowNew, callback);
+    }
+  }
+  return !error;
 }
 
 /**
  * This will merge and mangle resources from a static library.
  */
-bool TableMerger::mergeAndMangle(const Source& src, const StringPiece& packageName,
-                                 ResourceTable* table, io::IFileCollection* collection) {
-    bool error = false;
-    for (auto& package : table->packages) {
-        // Warn of packages with an unrelated ID.
-        if (packageName != package->name) {
-            mContext->getDiagnostics()->warn(DiagMessage(src)
-                                             << "ignoring package " << package->name);
-            continue;
-        }
-
-        bool mangle = packageName != mContext->getCompilationPackage();
-        mMergedPackages.insert(package->name);
-
-        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(*oldFile->path);
-            if (!f) {
-                mContext->getDiagnostics()->error(DiagMessage(src) << "file '" << *oldFile->path
-                                                  << "' not found");
-                return false;
-            }
-
-            newFile->file = f;
-            return true;
-        };
-
-        error |= !doMerge(src, table, package.get(),
-                          mangle, false /* overlay */, true /* allow new */, callback);
+bool TableMerger::mergeAndMangle(const Source& src,
+                                 const StringPiece& packageName,
+                                 ResourceTable* table,
+                                 io::IFileCollection* collection) {
+  bool error = false;
+  for (auto& package : table->packages) {
+    // Warn of packages with an unrelated ID.
+    if (packageName != package->name) {
+      mContext->getDiagnostics()->warn(DiagMessage(src) << "ignoring package "
+                                                        << package->name);
+      continue;
     }
-    return !error;
+
+    bool mangle = packageName != mContext->getCompilationPackage();
+    mMergedPackages.insert(package->name);
+
+    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(*oldFile->path);
+      if (!f) {
+        mContext->getDiagnostics()->error(
+            DiagMessage(src) << "file '" << *oldFile->path << "' not found");
+        return false;
+      }
+
+      newFile->file = f;
+      return true;
+    };
+
+    error |= !doMerge(src, table, package.get(), mangle, false /* overlay */,
+                      true /* allow new */, callback);
+  }
+  return !error;
 }
 
-static bool mergeType(IAaptContext* context, const Source& src, ResourceTableType* dstType,
-                      ResourceTableType* srcType) {
-    if (dstType->symbolStatus.state < srcType->symbolStatus.state) {
-        // The incoming type's visibility is stronger, so we should override
-        // the visibility.
-        if (srcType->symbolStatus.state == SymbolState::kPublic) {
-            // Only copy the ID if the source is public, or else the ID is meaningless.
-            dstType->id = srcType->id;
-        }
-        dstType->symbolStatus = std::move(srcType->symbolStatus);
-    } else if (dstType->symbolStatus.state == SymbolState::kPublic
-            && srcType->symbolStatus.state == SymbolState::kPublic
-            && dstType->id && srcType->id
-            && dstType->id.value() != srcType->id.value()) {
-        // Both types are public and have different IDs.
-        context->getDiagnostics()->error(DiagMessage(src)
-                                         << "cannot merge type '" << srcType->type
-                                         << "': conflicting public IDs");
-        return false;
+static bool mergeType(IAaptContext* context, const Source& src,
+                      ResourceTableType* dstType, ResourceTableType* srcType) {
+  if (dstType->symbolStatus.state < srcType->symbolStatus.state) {
+    // The incoming type's visibility is stronger, so we should override
+    // the visibility.
+    if (srcType->symbolStatus.state == SymbolState::kPublic) {
+      // Only copy the ID if the source is public, or else the ID is
+      // meaningless.
+      dstType->id = srcType->id;
     }
-    return true;
+    dstType->symbolStatus = std::move(srcType->symbolStatus);
+  } else if (dstType->symbolStatus.state == SymbolState::kPublic &&
+             srcType->symbolStatus.state == SymbolState::kPublic &&
+             dstType->id && srcType->id &&
+             dstType->id.value() != srcType->id.value()) {
+    // Both types are public and have different IDs.
+    context->getDiagnostics()->error(DiagMessage(src)
+                                     << "cannot merge type '" << srcType->type
+                                     << "': conflicting public IDs");
+    return false;
+  }
+  return true;
 }
 
-static bool mergeEntry(IAaptContext* context, const Source& src, ResourceEntry* dstEntry,
-                       ResourceEntry* srcEntry) {
-    if (dstEntry->symbolStatus.state < srcEntry->symbolStatus.state) {
-        // The incoming type's visibility is stronger, so we should override
-        // the visibility.
-        if (srcEntry->symbolStatus.state == SymbolState::kPublic) {
-            // Only copy the ID if the source is public, or else the ID is meaningless.
-            dstEntry->id = srcEntry->id;
-        }
-        dstEntry->symbolStatus = std::move(srcEntry->symbolStatus);
-    } else if (srcEntry->symbolStatus.state == SymbolState::kPublic
-            && dstEntry->symbolStatus.state == SymbolState::kPublic
-            && dstEntry->id && srcEntry->id
-            && dstEntry->id.value() != srcEntry->id.value()) {
-        // Both entries are public and have different IDs.
-        context->getDiagnostics()->error(DiagMessage(src)
-                                         << "cannot merge entry '" << srcEntry->name
-                                         << "': conflicting public IDs");
-        return false;
+static bool mergeEntry(IAaptContext* context, const Source& src,
+                       ResourceEntry* dstEntry, ResourceEntry* srcEntry) {
+  if (dstEntry->symbolStatus.state < srcEntry->symbolStatus.state) {
+    // The incoming type's visibility is stronger, so we should override
+    // the visibility.
+    if (srcEntry->symbolStatus.state == SymbolState::kPublic) {
+      // Only copy the ID if the source is public, or else the ID is
+      // meaningless.
+      dstEntry->id = srcEntry->id;
     }
-    return true;
+    dstEntry->symbolStatus = std::move(srcEntry->symbolStatus);
+  } else if (srcEntry->symbolStatus.state == SymbolState::kPublic &&
+             dstEntry->symbolStatus.state == SymbolState::kPublic &&
+             dstEntry->id && srcEntry->id &&
+             dstEntry->id.value() != srcEntry->id.value()) {
+    // Both entries are public and have different IDs.
+    context->getDiagnostics()->error(DiagMessage(src)
+                                     << "cannot merge entry '" << srcEntry->name
+                                     << "': conflicting public IDs");
+    return false;
+  }
+  return true;
 }
 
 /**
  * Modified CollisionResolver which will merge Styleables. Used with overlays.
  *
  * Styleables are not actual resources, but they are treated as such during the
- * compilation phase. Styleables don't simply overlay each other, their definitions merge
- * and accumulate. If both values are Styleables, we just merge them into the existing value.
+ * compilation phase. Styleables don't simply overlay each other, their
+ * definitions merge
+ * and accumulate. If both values are Styleables, we just merge them into the
+ * existing value.
  */
-static ResourceTable::CollisionResult resolveMergeCollision(Value* existing, Value* incoming) {
-    if (Styleable* existingStyleable = valueCast<Styleable>(existing)) {
-        if (Styleable* incomingStyleable = valueCast<Styleable>(incoming)) {
-            // Styleables get merged.
-            existingStyleable->mergeWith(incomingStyleable);
-            return ResourceTable::CollisionResult::kKeepOriginal;
-        }
+static ResourceTable::CollisionResult resolveMergeCollision(Value* existing,
+                                                            Value* incoming) {
+  if (Styleable* existingStyleable = valueCast<Styleable>(existing)) {
+    if (Styleable* incomingStyleable = valueCast<Styleable>(incoming)) {
+      // Styleables get merged.
+      existingStyleable->mergeWith(incomingStyleable);
+      return ResourceTable::CollisionResult::kKeepOriginal;
     }
-    // Delegate to the default handler.
-    return ResourceTable::resolveValueCollision(existing, incoming);
+  }
+  // Delegate to the default handler.
+  return ResourceTable::resolveValueCollision(existing, incoming);
 }
 
-static ResourceTable::CollisionResult mergeConfigValue(IAaptContext* context,
-                                                       const ResourceNameRef& resName,
-                                                       const bool overlay,
-                                                       ResourceConfigValue* dstConfigValue,
-                                                       ResourceConfigValue* srcConfigValue) {
-    using CollisionResult = ResourceTable::CollisionResult;
+static ResourceTable::CollisionResult mergeConfigValue(
+    IAaptContext* context, const ResourceNameRef& resName, const bool overlay,
+    ResourceConfigValue* dstConfigValue, ResourceConfigValue* srcConfigValue) {
+  using CollisionResult = ResourceTable::CollisionResult;
 
-    Value* dstValue = dstConfigValue->value.get();
-    Value* srcValue = srcConfigValue->value.get();
+  Value* dstValue = dstConfigValue->value.get();
+  Value* srcValue = srcConfigValue->value.get();
 
-    CollisionResult collisionResult;
+  CollisionResult collisionResult;
+  if (overlay) {
+    collisionResult = resolveMergeCollision(dstValue, srcValue);
+  } else {
+    collisionResult = ResourceTable::resolveValueCollision(dstValue, srcValue);
+  }
+
+  if (collisionResult == CollisionResult::kConflict) {
     if (overlay) {
-        collisionResult = resolveMergeCollision(dstValue, srcValue);
-    } else {
-        collisionResult = ResourceTable::resolveValueCollision(dstValue, srcValue);
+      return CollisionResult::kTakeNew;
     }
 
-    if (collisionResult == CollisionResult::kConflict) {
-        if (overlay) {
-            return CollisionResult::kTakeNew;
-        }
-
-        // Error!
-        context->getDiagnostics()->error(DiagMessage(srcValue->getSource())
-                                         << "resource '" << resName
-                                         << "' has a conflicting value for "
-                                         << "configuration ("
-                                         << srcConfigValue->config << ")");
-        context->getDiagnostics()->note(DiagMessage(dstValue->getSource())
-                                        << "originally defined here");
-        return CollisionResult::kConflict;
-    }
-    return collisionResult;
+    // Error!
+    context->getDiagnostics()->error(
+        DiagMessage(srcValue->getSource())
+        << "resource '" << resName << "' has a conflicting value for "
+        << "configuration (" << srcConfigValue->config << ")");
+    context->getDiagnostics()->note(DiagMessage(dstValue->getSource())
+                                    << "originally defined here");
+    return CollisionResult::kConflict;
+  }
+  return collisionResult;
 }
 
-bool TableMerger::doMerge(const Source& src,
-                          ResourceTable* srcTable,
+bool TableMerger::doMerge(const Source& src, ResourceTable* srcTable,
                           ResourceTablePackage* srcPackage,
-                          const bool manglePackage,
-                          const bool overlay,
+                          const bool manglePackage, const bool overlay,
                           const bool allowNewResources,
                           const FileMergeCallback& callback) {
-    bool error = false;
+  bool error = false;
 
-    for (auto& srcType : srcPackage->types) {
-        ResourceTableType* dstType = mMasterPackage->findOrCreateType(srcType->type);
-        if (!mergeType(mContext, src, dstType, srcType.get())) {
+  for (auto& srcType : srcPackage->types) {
+    ResourceTableType* dstType =
+        mMasterPackage->findOrCreateType(srcType->type);
+    if (!mergeType(mContext, src, dstType, srcType.get())) {
+      error = true;
+      continue;
+    }
+
+    for (auto& srcEntry : srcType->entries) {
+      std::string entryName = srcEntry->name;
+      if (manglePackage) {
+        entryName = NameMangler::mangleEntry(srcPackage->name, srcEntry->name);
+      }
+
+      ResourceEntry* dstEntry;
+      if (allowNewResources) {
+        dstEntry = dstType->findOrCreateEntry(entryName);
+      } else {
+        dstEntry = dstType->findEntry(entryName);
+      }
+
+      const ResourceNameRef resName(srcPackage->name, srcType->type,
+                                    srcEntry->name);
+
+      if (!dstEntry) {
+        mContext->getDiagnostics()->error(
+            DiagMessage(src) << "resource " << resName
+                             << " does not override an existing resource");
+        mContext->getDiagnostics()->note(
+            DiagMessage(src) << "define an <add-resource> tag or use "
+                             << "--auto-add-overlay");
+        error = true;
+        continue;
+      }
+
+      if (!mergeEntry(mContext, src, dstEntry, srcEntry.get())) {
+        error = true;
+        continue;
+      }
+
+      for (auto& srcConfigValue : srcEntry->values) {
+        using CollisionResult = ResourceTable::CollisionResult;
+
+        ResourceConfigValue* dstConfigValue = dstEntry->findValue(
+            srcConfigValue->config, srcConfigValue->product);
+        if (dstConfigValue) {
+          CollisionResult collisionResult = mergeConfigValue(
+              mContext, resName, overlay, dstConfigValue, srcConfigValue.get());
+          if (collisionResult == CollisionResult::kConflict) {
             error = true;
             continue;
+          } else if (collisionResult == CollisionResult::kKeepOriginal) {
+            continue;
+          }
+        } else {
+          dstConfigValue = dstEntry->findOrCreateValue(srcConfigValue->config,
+                                                       srcConfigValue->product);
         }
 
-        for (auto& srcEntry : srcType->entries) {
-            std::string entryName = srcEntry->name;
-            if (manglePackage) {
-                entryName = NameMangler::mangleEntry(srcPackage->name, srcEntry->name);
+        // Continue if we're taking the new resource.
+
+        if (FileReference* f =
+                valueCast<FileReference>(srcConfigValue->value.get())) {
+          std::unique_ptr<FileReference> newFileRef;
+          if (manglePackage) {
+            newFileRef = cloneAndMangleFile(srcPackage->name, *f);
+          } else {
+            newFileRef = std::unique_ptr<FileReference>(
+                f->clone(&mMasterTable->stringPool));
+          }
+
+          if (callback) {
+            if (!callback(resName, srcConfigValue->config, newFileRef.get(),
+                          f)) {
+              error = true;
+              continue;
             }
+          }
+          dstConfigValue->value = std::move(newFileRef);
 
-            ResourceEntry* dstEntry;
-            if (allowNewResources) {
-                dstEntry = dstType->findOrCreateEntry(entryName);
-            } else {
-                dstEntry = dstType->findEntry(entryName);
-            }
-
-            const ResourceNameRef resName(srcPackage->name, srcType->type, srcEntry->name);
-
-            if (!dstEntry) {
-                mContext->getDiagnostics()->error(DiagMessage(src)
-                                                  << "resource " << resName
-                                                  << " does not override an existing resource");
-                mContext->getDiagnostics()->note(DiagMessage(src)
-                                                 << "define an <add-resource> tag or use "
-                                                 << "--auto-add-overlay");
-                error = true;
-                continue;
-            }
-
-            if (!mergeEntry(mContext, src, dstEntry, srcEntry.get())) {
-                error = true;
-                continue;
-            }
-
-            for (auto& srcConfigValue : srcEntry->values) {
-                using CollisionResult = ResourceTable::CollisionResult;
-
-                ResourceConfigValue* dstConfigValue = dstEntry->findValue(srcConfigValue->config,
-                                                                          srcConfigValue->product);
-                if (dstConfigValue) {
-                    CollisionResult collisionResult = mergeConfigValue(
-                            mContext, resName, overlay, dstConfigValue, srcConfigValue.get());
-                    if (collisionResult == CollisionResult::kConflict) {
-                        error = true;
-                        continue;
-                    } else if (collisionResult == CollisionResult::kKeepOriginal) {
-                        continue;
-                    }
-                } else {
-                    dstConfigValue = dstEntry->findOrCreateValue(srcConfigValue->config,
-                                                                 srcConfigValue->product);
-                }
-
-                // Continue if we're taking the new resource.
-
-                if (FileReference* f = valueCast<FileReference>(srcConfigValue->value.get())) {
-                    std::unique_ptr<FileReference> newFileRef;
-                    if (manglePackage) {
-                        newFileRef = cloneAndMangleFile(srcPackage->name, *f);
-                    } else {
-                        newFileRef = std::unique_ptr<FileReference>(f->clone(
-                                &mMasterTable->stringPool));
-                    }
-
-                    if (callback) {
-                        if (!callback(resName, srcConfigValue->config, newFileRef.get(), f)) {
-                            error = true;
-                            continue;
-                        }
-                    }
-                    dstConfigValue->value = std::move(newFileRef);
-
-                } else {
-                    dstConfigValue->value = std::unique_ptr<Value>(srcConfigValue->value->clone(
-                            &mMasterTable->stringPool));
-                }
-            }
+        } else {
+          dstConfigValue->value = std::unique_ptr<Value>(
+              srcConfigValue->value->clone(&mMasterTable->stringPool));
         }
+      }
     }
-    return !error;
+  }
+  return !error;
 }
 
-std::unique_ptr<FileReference> TableMerger::cloneAndMangleFile(const std::string& package,
-                                                               const FileReference& fileRef) {
-    StringPiece prefix, entry, suffix;
-    if (util::extractResFilePathParts(*fileRef.path, &prefix, &entry, &suffix)) {
-        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());
-        newFileRef->setSource(fileRef.getSource());
-        return newFileRef;
-    }
-    return std::unique_ptr<FileReference>(fileRef.clone(&mMasterTable->stringPool));
+std::unique_ptr<FileReference> TableMerger::cloneAndMangleFile(
+    const std::string& package, const FileReference& fileRef) {
+  StringPiece prefix, entry, suffix;
+  if (util::extractResFilePathParts(*fileRef.path, &prefix, &entry, &suffix)) {
+    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());
+    newFileRef->setSource(fileRef.getSource());
+    return newFileRef;
+  }
+  return std::unique_ptr<FileReference>(
+      fileRef.clone(&mMasterTable->stringPool));
 }
 
-bool TableMerger::mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file, bool overlay) {
-    ResourceTable table;
-    std::string path = ResourceUtils::buildResourceFileName(fileDesc, nullptr);
-    std::unique_ptr<FileReference> fileRef = util::make_unique<FileReference>(
-            table.stringPool.makeRef(path));
-    fileRef->setSource(fileDesc.source);
-    fileRef->file = file;
+bool TableMerger::mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file,
+                                bool overlay) {
+  ResourceTable table;
+  std::string path = ResourceUtils::buildResourceFileName(fileDesc, nullptr);
+  std::unique_ptr<FileReference> fileRef =
+      util::make_unique<FileReference>(table.stringPool.makeRef(path));
+  fileRef->setSource(fileDesc.source);
+  fileRef->file = file;
 
-    ResourceTablePackage* pkg = table.createPackage(fileDesc.name.package, 0x0);
-    pkg->findOrCreateType(fileDesc.name.type)
-            ->findOrCreateEntry(fileDesc.name.entry)
-            ->findOrCreateValue(fileDesc.config, {})
-            ->value = std::move(fileRef);
+  ResourceTablePackage* pkg = table.createPackage(fileDesc.name.package, 0x0);
+  pkg->findOrCreateType(fileDesc.name.type)
+      ->findOrCreateEntry(fileDesc.name.entry)
+      ->findOrCreateValue(fileDesc.config, {})
+      ->value = std::move(fileRef);
 
-    return doMerge(file->getSource(), &table, pkg,
-                   false /* mangle */, overlay /* overlay */, true /* allow new */, {});
+  return doMerge(file->getSource(), &table, pkg, false /* mangle */,
+                 overlay /* overlay */, true /* allow new */, {});
 }
 
 bool TableMerger::mergeFile(const ResourceFile& fileDesc, io::IFile* file) {
-    return mergeFileImpl(fileDesc, file, false /* overlay */);
+  return mergeFileImpl(fileDesc, file, false /* overlay */);
 }
 
-bool TableMerger::mergeFileOverlay(const ResourceFile& fileDesc, io::IFile* file) {
-    return mergeFileImpl(fileDesc, file, true /* overlay */);
+bool TableMerger::mergeFileOverlay(const ResourceFile& fileDesc,
+                                   io::IFile* file) {
+  return mergeFileImpl(fileDesc, file, true /* overlay */);
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/TableMerger.h b/tools/aapt2/link/TableMerger.h
index 3473a27..c2e7181 100644
--- a/tools/aapt2/link/TableMerger.h
+++ b/tools/aapt2/link/TableMerger.h
@@ -31,96 +31,111 @@
 namespace aapt {
 
 struct TableMergerOptions {
-    /**
-     * If true, resources in overlays can be added without previously having existed.
-     */
-    bool autoAddOverlay = false;
+  /**
+   * If true, resources in overlays can be added without previously having
+   * existed.
+   */
+  bool autoAddOverlay = false;
 };
 
 /**
- * TableMerger takes resource tables and merges all packages within the tables that have the same
+ * TableMerger takes resource tables and merges all packages within the tables
+ * that have the same
  * package ID.
  *
- * If a package has a different name, all the entries in that table have their names mangled
- * to include the package name. This way there are no collisions. In order to do this correctly,
- * the TableMerger needs to also mangle any FileReference paths. Once these are mangled,
- * the original source path of the file, along with the new destination path is recorded in the
+ * If a package has a different name, all the entries in that table have their
+ * names mangled
+ * to include the package name. This way there are no collisions. In order to do
+ * this correctly,
+ * the TableMerger needs to also mangle any FileReference paths. Once these are
+ * mangled,
+ * the original source path of the file, along with the new destination path is
+ * recorded in the
  * queue returned from getFileMergeQueue().
  *
- * Once the merging is complete, a separate process can go collect the files from the various
- * source APKs and either copy or process their XML and put them in the correct location in
+ * Once the merging is complete, a separate process can go collect the files
+ * from the various
+ * source APKs and either copy or process their XML and put them in the correct
+ * location in
  * the final APK.
  */
 class TableMerger {
-public:
-    /**
-     * Note: The outTable ResourceTable must live longer than this TableMerger. References
-     * are made to this ResourceTable for efficiency reasons.
-     */
-    TableMerger(IAaptContext* context, ResourceTable* outTable, const TableMergerOptions& options);
+ public:
+  /**
+   * Note: The outTable ResourceTable must live longer than this TableMerger.
+   * References
+   * are made to this ResourceTable for efficiency reasons.
+   */
+  TableMerger(IAaptContext* context, ResourceTable* outTable,
+              const TableMergerOptions& options);
 
-    const std::set<std::string>& getMergedPackages() const {
-        return mMergedPackages;
-    }
+  const std::set<std::string>& getMergedPackages() const {
+    return mMergedPackages;
+  }
 
-    /**
-     * Merges resources from the same or empty package. This is for local sources.
-     * An io::IFileCollection is optional and used to find the referenced Files and process them.
-     */
-    bool merge(const Source& src, ResourceTable* table,
-               io::IFileCollection* collection = nullptr);
+  /**
+   * Merges resources from the same or empty package. This is for local sources.
+   * An io::IFileCollection is optional and used to find the referenced Files
+   * and process them.
+   */
+  bool merge(const Source& src, ResourceTable* table,
+             io::IFileCollection* collection = nullptr);
 
-    /**
-     * Merges resources from an overlay ResourceTable.
-     * An io::IFileCollection is optional and used to find the referenced Files and process them.
-     */
-    bool mergeOverlay(const Source& src, ResourceTable* table,
-                      io::IFileCollection* collection = nullptr);
+  /**
+   * Merges resources from an overlay ResourceTable.
+   * An io::IFileCollection is optional and used to find the referenced Files
+   * and process them.
+   */
+  bool mergeOverlay(const Source& src, ResourceTable* table,
+                    io::IFileCollection* collection = nullptr);
 
-    /**
-     * 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 StringPiece& package, ResourceTable* table,
-                        io::IFileCollection* collection);
+  /**
+   * 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 StringPiece& package,
+                      ResourceTable* table, io::IFileCollection* collection);
 
-    /**
-     * Merges a compiled file that belongs to this same or empty package. This is for local sources.
-     */
-    bool mergeFile(const ResourceFile& fileDesc, io::IFile* file);
+  /**
+   * Merges a compiled file that belongs to this same or empty package. This is
+   * for local sources.
+   */
+  bool mergeFile(const ResourceFile& fileDesc, io::IFile* file);
 
-    /**
-     * Merges a compiled file from an overlay, overriding an existing definition.
-     */
-    bool mergeFileOverlay(const ResourceFile& fileDesc, io::IFile* file);
+  /**
+   * Merges a compiled file from an overlay, overriding an existing definition.
+   */
+  bool mergeFileOverlay(const ResourceFile& fileDesc, io::IFile* file);
 
-private:
-    using FileMergeCallback = std::function<bool(const ResourceNameRef&,
-                                                 const ConfigDescription& config,
-                                                 FileReference*, FileReference*)>;
+ private:
+  using FileMergeCallback = std::function<bool(const ResourceNameRef&,
+                                               const ConfigDescription& config,
+                                               FileReference*, FileReference*)>;
 
-    IAaptContext* mContext;
-    ResourceTable* mMasterTable;
-    TableMergerOptions mOptions;
-    ResourceTablePackage* mMasterPackage;
+  IAaptContext* mContext;
+  ResourceTable* mMasterTable;
+  TableMergerOptions mOptions;
+  ResourceTablePackage* mMasterPackage;
 
-    std::set<std::string> mMergedPackages;
+  std::set<std::string> mMergedPackages;
 
-    bool mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file, bool overlay);
+  bool mergeFileImpl(const ResourceFile& fileDesc, io::IFile* file,
+                     bool overlay);
 
-    bool mergeImpl(const Source& src, ResourceTable* srcTable, io::IFileCollection* collection,
-                   bool overlay, bool allowNew);
+  bool mergeImpl(const Source& src, ResourceTable* srcTable,
+                 io::IFileCollection* collection, bool overlay, bool allowNew);
 
-    bool doMerge(const Source& src, ResourceTable* srcTable, ResourceTablePackage* srcPackage,
-                 const bool manglePackage,
-                 const bool overlay,
-                 const bool allowNewResources,
-                 const FileMergeCallback& callback);
+  bool doMerge(const Source& src, ResourceTable* srcTable,
+               ResourceTablePackage* srcPackage, const bool manglePackage,
+               const bool overlay, const bool allowNewResources,
+               const FileMergeCallback& callback);
 
-    std::unique_ptr<FileReference> cloneAndMangleFile(const std::string& package,
-                                                      const FileReference& value);
+  std::unique_ptr<FileReference> cloneAndMangleFile(const std::string& package,
+                                                    const FileReference& value);
 };
 
-} // namespace aapt
+}  // namespace aapt
 
 #endif /* AAPT_TABLEMERGER_H */
diff --git a/tools/aapt2/link/TableMerger_test.cpp b/tools/aapt2/link/TableMerger_test.cpp
index fb1cb21..e0b2b66 100644
--- a/tools/aapt2/link/TableMerger_test.cpp
+++ b/tools/aapt2/link/TableMerger_test.cpp
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
+#include "link/TableMerger.h"
 #include "filter/ConfigFilter.h"
 #include "io/FileSystem.h"
-#include "link/TableMerger.h"
 #include "test/Builders.h"
 #include "test/Context.h"
 
@@ -25,292 +25,327 @@
 namespace aapt {
 
 struct TableMergerTest : public ::testing::Test {
-    std::unique_ptr<IAaptContext> mContext;
+  std::unique_ptr<IAaptContext> mContext;
 
-    void SetUp() override {
-        mContext = test::ContextBuilder()
-                // We are compiling this package.
-                .setCompilationPackage("com.app.a")
+  void SetUp() override {
+    mContext =
+        test::ContextBuilder()
+            // We are compiling this package.
+            .setCompilationPackage("com.app.a")
 
-                // Merge all packages that have this package ID.
-                .setPackageId(0x7f)
+            // Merge all packages that have this package ID.
+            .setPackageId(0x7f)
 
-                // Mangle all packages that do not have this package name.
-                .setNameManglerPolicy(NameManglerPolicy{ "com.app.a", { "com.app.b" } })
+            // Mangle all packages that do not have this package name.
+            .setNameManglerPolicy(NameManglerPolicy{"com.app.a", {"com.app.b"}})
 
-                .build();
-    }
+            .build();
+  }
 };
 
 TEST_F(TableMergerTest, SimpleMerge) {
-    std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .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> tableA =
+      test::ResourceTableBuilder()
+          .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("com.app.b", 0x7f)
-            .addSimple("com.app.b:id/foo")
-            .build();
+  std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
+                                              .setPackageId("com.app.b", 0x7f)
+                                              .addSimple("com.app.b:id/foo")
+                                              .build();
 
-    ResourceTable finalTable;
-    TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
-    io::FileCollection collection;
+  ResourceTable finalTable;
+  TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
+  io::FileCollection collection;
 
-    ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_TRUE(merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
+  ASSERT_TRUE(merger.merge({}, tableA.get()));
+  ASSERT_TRUE(
+      merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
 
-    EXPECT_TRUE(merger.getMergedPackages().count("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("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")));
+  // Entries from com.app.a should not be mangled.
+  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("com.app.b:id/foo")));
+  // The unmangled name should not be present.
+  AAPT_EXPECT_FALSE(
+      finalTable.findResource(test::parseNameOrDie("com.app.b:id/foo")));
 
-    // Look for the mangled name.
-    AAPT_EXPECT_TRUE(finalTable.findResource(test::parseNameOrDie("com.app.a:id/com.app.b$foo")));
+  // Look for the mangled name.
+  AAPT_EXPECT_TRUE(finalTable.findResource(
+      test::parseNameOrDie("com.app.a:id/com.app.b$foo")));
 }
 
 TEST_F(TableMergerTest, MergeFile) {
-    ResourceTable finalTable;
-    TableMergerOptions options;
-    options.autoAddOverlay = false;
-    TableMerger merger(mContext.get(), &finalTable, options);
+  ResourceTable finalTable;
+  TableMergerOptions options;
+  options.autoAddOverlay = false;
+  TableMerger merger(mContext.get(), &finalTable, options);
 
-    ResourceFile fileDesc;
-    fileDesc.config = test::parseConfigOrDie("hdpi-v4");
-    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");
+  ResourceFile fileDesc;
+  fileDesc.config = test::parseConfigOrDie("hdpi-v4");
+  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));
+  ASSERT_TRUE(merger.mergeFile(fileDesc, &testFile));
 
-    FileReference* file = test::getValueForConfig<FileReference>(&finalTable,
-                                                                 "com.app.a:layout/main",
-                                                                 test::parseConfigOrDie("hdpi-v4"));
-    ASSERT_NE(nullptr, file);
-    EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path);
+  FileReference* file = test::getValueForConfig<FileReference>(
+      &finalTable, "com.app.a:layout/main", test::parseConfigOrDie("hdpi-v4"));
+  ASSERT_NE(nullptr, file);
+  EXPECT_EQ(std::string("res/layout-hdpi-v4/main.xml"), *file->path);
 }
 
 TEST_F(TableMergerTest, MergeFileOverlay) {
-    ResourceTable finalTable;
-    TableMergerOptions tableMergerOptions;
-    tableMergerOptions.autoAddOverlay = false;
-    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+  ResourceTable finalTable;
+  TableMergerOptions tableMergerOptions;
+  tableMergerOptions.autoAddOverlay = false;
+  TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
 
-    ResourceFile fileDesc;
-    fileDesc.name = test::parseNameOrDie("xml/foo");
-    test::TestFile fileA("path/to/fileA.xml.flat");
-    test::TestFile fileB("path/to/fileB.xml.flat");
+  ResourceFile fileDesc;
+  fileDesc.name = test::parseNameOrDie("xml/foo");
+  test::TestFile fileA("path/to/fileA.xml.flat");
+  test::TestFile fileB("path/to/fileB.xml.flat");
 
-    ASSERT_TRUE(merger.mergeFile(fileDesc, &fileA));
-    ASSERT_TRUE(merger.mergeFileOverlay(fileDesc, &fileB));
+  ASSERT_TRUE(merger.mergeFile(fileDesc, &fileA));
+  ASSERT_TRUE(merger.mergeFileOverlay(fileDesc, &fileB));
 }
 
 TEST_F(TableMergerTest, MergeFileReferences) {
-    std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId("com.app.a", 0x7f)
-            .addFileReference("com.app.a:xml/file", "res/xml/file.xml")
-            .build();
-    std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId("com.app.b", 0x7f)
-            .addFileReference("com.app.b:xml/file", "res/xml/file.xml")
-            .build();
+  std::unique_ptr<ResourceTable> tableA =
+      test::ResourceTableBuilder()
+          .setPackageId("com.app.a", 0x7f)
+          .addFileReference("com.app.a:xml/file", "res/xml/file.xml")
+          .build();
+  std::unique_ptr<ResourceTable> tableB =
+      test::ResourceTableBuilder()
+          .setPackageId("com.app.b", 0x7f)
+          .addFileReference("com.app.b:xml/file", "res/xml/file.xml")
+          .build();
 
-    ResourceTable finalTable;
-    TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
-    io::FileCollection collection;
-    collection.insertFile("res/xml/file.xml");
+  ResourceTable finalTable;
+  TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
+  io::FileCollection collection;
+  collection.insertFile("res/xml/file.xml");
 
-    ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_TRUE(merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
+  ASSERT_TRUE(merger.merge({}, tableA.get()));
+  ASSERT_TRUE(
+      merger.mergeAndMangle({}, "com.app.b", tableB.get(), &collection));
 
-    FileReference* f = test::getValue<FileReference>(&finalTable, "com.app.a:xml/file");
-    ASSERT_NE(f, nullptr);
-    EXPECT_EQ(std::string("res/xml/file.xml"), *f->path);
+  FileReference* f =
+      test::getValue<FileReference>(&finalTable, "com.app.a:xml/file");
+  ASSERT_NE(f, nullptr);
+  EXPECT_EQ(std::string("res/xml/file.xml"), *f->path);
 
-    f = test::getValue<FileReference>(&finalTable, "com.app.a:xml/com.app.b$file");
-    ASSERT_NE(f, nullptr);
-    EXPECT_EQ(std::string("res/xml/com.app.b$file.xml"), *f->path);
+  f = test::getValue<FileReference>(&finalTable,
+                                    "com.app.a:xml/com.app.b$file");
+  ASSERT_NE(f, nullptr);
+  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("", 0x00)
-            .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
-            .build();
-    std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
-            .setPackageId("", 0x00)
-            .addValue("bool/foo", ResourceUtils::tryParseBool("false"))
-            .build();
+  std::unique_ptr<ResourceTable> base =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x00)
+          .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
+          .build();
+  std::unique_ptr<ResourceTable> overlay =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x00)
+          .addValue("bool/foo", ResourceUtils::tryParseBool("false"))
+          .build();
 
-    ResourceTable finalTable;
-    TableMergerOptions tableMergerOptions;
-    tableMergerOptions.autoAddOverlay = false;
-    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+  ResourceTable finalTable;
+  TableMergerOptions tableMergerOptions;
+  tableMergerOptions.autoAddOverlay = false;
+  TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
 
-    ASSERT_TRUE(merger.merge({}, base.get()));
-    ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
+  ASSERT_TRUE(merger.merge({}, base.get()));
+  ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
 
-    BinaryPrimitive* foo = test::getValue<BinaryPrimitive>(&finalTable, "com.app.a:bool/foo");
-    ASSERT_NE(nullptr, foo);
-    EXPECT_EQ(0x0u, foo->value.data);
+  BinaryPrimitive* foo =
+      test::getValue<BinaryPrimitive>(&finalTable, "com.app.a:bool/foo");
+  ASSERT_NE(nullptr, foo);
+  EXPECT_EQ(0x0u, foo->value.data);
 }
 
 TEST_F(TableMergerTest, OverrideSameResourceIdsWithOverlay) {
-    std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
-            .build();
-    std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
-            .build();
+  std::unique_ptr<ResourceTable> base =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
+                          SymbolState::kPublic)
+          .build();
+  std::unique_ptr<ResourceTable> overlay =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
+                          SymbolState::kPublic)
+          .build();
 
-    ResourceTable finalTable;
-    TableMergerOptions tableMergerOptions;
-    tableMergerOptions.autoAddOverlay = false;
-    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+  ResourceTable finalTable;
+  TableMergerOptions tableMergerOptions;
+  tableMergerOptions.autoAddOverlay = false;
+  TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
 
-    ASSERT_TRUE(merger.merge({}, base.get()));
-    ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
+  ASSERT_TRUE(merger.merge({}, base.get()));
+  ASSERT_TRUE(merger.mergeOverlay({}, overlay.get()));
 }
 
 TEST_F(TableMergerTest, FailToOverrideConflictingTypeIdsWithOverlay) {
-    std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
-            .build();
-    std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .setSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001), SymbolState::kPublic)
-            .build();
+  std::unique_ptr<ResourceTable> base =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
+                          SymbolState::kPublic)
+          .build();
+  std::unique_ptr<ResourceTable> overlay =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .setSymbolState("bool/foo", ResourceId(0x7f, 0x02, 0x0001),
+                          SymbolState::kPublic)
+          .build();
 
-    ResourceTable finalTable;
-    TableMergerOptions tableMergerOptions;
-    tableMergerOptions.autoAddOverlay = false;
-    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+  ResourceTable finalTable;
+  TableMergerOptions tableMergerOptions;
+  tableMergerOptions.autoAddOverlay = false;
+  TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
 
-    ASSERT_TRUE(merger.merge({}, base.get()));
-    ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
+  ASSERT_TRUE(merger.merge({}, base.get()));
+  ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
 }
 
 TEST_F(TableMergerTest, FailToOverrideConflictingEntryIdsWithOverlay) {
-    std::unique_ptr<ResourceTable> base = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001), SymbolState::kPublic)
-            .build();
-    std::unique_ptr<ResourceTable> overlay = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002), SymbolState::kPublic)
-            .build();
+  std::unique_ptr<ResourceTable> base =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0001),
+                          SymbolState::kPublic)
+          .build();
+  std::unique_ptr<ResourceTable> overlay =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .setSymbolState("bool/foo", ResourceId(0x7f, 0x01, 0x0002),
+                          SymbolState::kPublic)
+          .build();
 
-    ResourceTable finalTable;
-    TableMergerOptions tableMergerOptions;
-    tableMergerOptions.autoAddOverlay = false;
-    TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
+  ResourceTable finalTable;
+  TableMergerOptions tableMergerOptions;
+  tableMergerOptions.autoAddOverlay = false;
+  TableMerger merger(mContext.get(), &finalTable, tableMergerOptions);
 
-    ASSERT_TRUE(merger.merge({}, base.get()));
-    ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
+  ASSERT_TRUE(merger.merge({}, base.get()));
+  ASSERT_FALSE(merger.mergeOverlay({}, overlay.get()));
 }
 
 TEST_F(TableMergerTest, MergeAddResourceFromOverlay) {
-    std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .setSymbolState("bool/foo", {}, SymbolState::kUndefined)
-            .build();
-    std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
-            .build();
+  std::unique_ptr<ResourceTable> tableA =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .setSymbolState("bool/foo", {}, SymbolState::kUndefined)
+          .build();
+  std::unique_ptr<ResourceTable> tableB =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
+          .build();
 
-    ResourceTable finalTable;
-    TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
+  ResourceTable finalTable;
+  TableMerger merger(mContext.get(), &finalTable, TableMergerOptions{});
 
-    ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
+  ASSERT_TRUE(merger.merge({}, tableA.get()));
+  ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
 }
 
 TEST_F(TableMergerTest, MergeAddResourceFromOverlayWithAutoAddOverlay) {
-    std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .build();
-    std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
-            .build();
+  std::unique_ptr<ResourceTable> tableA =
+      test::ResourceTableBuilder().setPackageId("", 0x7f).build();
+  std::unique_ptr<ResourceTable> tableB =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
+          .build();
 
-    ResourceTable finalTable;
-    TableMergerOptions options;
-    options.autoAddOverlay = true;
-    TableMerger merger(mContext.get(), &finalTable, options);
+  ResourceTable finalTable;
+  TableMergerOptions options;
+  options.autoAddOverlay = true;
+  TableMerger merger(mContext.get(), &finalTable, options);
 
-    ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
+  ASSERT_TRUE(merger.merge({}, tableA.get()));
+  ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
 }
 
 TEST_F(TableMergerTest, FailToMergeNewResourceWithoutAutoAddOverlay) {
-    std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .build();
-    std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId("", 0x7f)
-            .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
-            .build();
+  std::unique_ptr<ResourceTable> tableA =
+      test::ResourceTableBuilder().setPackageId("", 0x7f).build();
+  std::unique_ptr<ResourceTable> tableB =
+      test::ResourceTableBuilder()
+          .setPackageId("", 0x7f)
+          .addValue("bool/foo", ResourceUtils::tryParseBool("true"))
+          .build();
 
-    ResourceTable finalTable;
-    TableMergerOptions options;
-    options.autoAddOverlay = false;
-    TableMerger merger(mContext.get(), &finalTable, options);
+  ResourceTable finalTable;
+  TableMergerOptions options;
+  options.autoAddOverlay = false;
+  TableMerger merger(mContext.get(), &finalTable, options);
 
-    ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_FALSE(merger.mergeOverlay({}, tableB.get()));
+  ASSERT_TRUE(merger.merge({}, tableA.get()));
+  ASSERT_FALSE(merger.mergeOverlay({}, tableB.get()));
 }
 
 TEST_F(TableMergerTest, OverlaidStyleablesShouldBeMerged) {
-    std::unique_ptr<ResourceTable> tableA = test::ResourceTableBuilder()
-            .setPackageId("com.app.a", 0x7f)
-            .addValue("com.app.a:styleable/Foo", test::StyleableBuilder()
-                    .addItem("com.app.a:attr/bar")
-                    .addItem("com.app.a:attr/foo", ResourceId(0x01010000))
-                    .build())
-            .build();
+  std::unique_ptr<ResourceTable> tableA =
+      test::ResourceTableBuilder()
+          .setPackageId("com.app.a", 0x7f)
+          .addValue("com.app.a:styleable/Foo",
+                    test::StyleableBuilder()
+                        .addItem("com.app.a:attr/bar")
+                        .addItem("com.app.a:attr/foo", ResourceId(0x01010000))
+                        .build())
+          .build();
 
-    std::unique_ptr<ResourceTable> tableB = test::ResourceTableBuilder()
-            .setPackageId("com.app.a", 0x7f)
-            .addValue("com.app.a:styleable/Foo", test::StyleableBuilder()
-                    .addItem("com.app.a:attr/bat")
-                    .addItem("com.app.a:attr/foo")
-                    .build())
-            .build();
+  std::unique_ptr<ResourceTable> tableB =
+      test::ResourceTableBuilder()
+          .setPackageId("com.app.a", 0x7f)
+          .addValue("com.app.a:styleable/Foo",
+                    test::StyleableBuilder()
+                        .addItem("com.app.a:attr/bat")
+                        .addItem("com.app.a:attr/foo")
+                        .build())
+          .build();
 
-    ResourceTable finalTable;
-    TableMergerOptions options;
-    options.autoAddOverlay = true;
-    TableMerger merger(mContext.get(), &finalTable, options);
+  ResourceTable finalTable;
+  TableMergerOptions options;
+  options.autoAddOverlay = true;
+  TableMerger merger(mContext.get(), &finalTable, options);
 
-    ASSERT_TRUE(merger.merge({}, tableA.get()));
-    ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
+  ASSERT_TRUE(merger.merge({}, tableA.get()));
+  ASSERT_TRUE(merger.mergeOverlay({}, tableB.get()));
 
-    Debug::printTable(&finalTable, {});
+  Debug::printTable(&finalTable, {});
 
-    Styleable* styleable = test::getValue<Styleable>(&finalTable, "com.app.a:styleable/Foo");
-    ASSERT_NE(nullptr, styleable);
+  Styleable* styleable =
+      test::getValue<Styleable>(&finalTable, "com.app.a:styleable/Foo");
+  ASSERT_NE(nullptr, styleable);
 
-    std::vector<Reference> expectedRefs = {
-            Reference(test::parseNameOrDie("com.app.a:attr/bar")),
-            Reference(test::parseNameOrDie("com.app.a:attr/bat")),
-            Reference(test::parseNameOrDie("com.app.a:attr/foo"), ResourceId(0x01010000)),
-    };
+  std::vector<Reference> expectedRefs = {
+      Reference(test::parseNameOrDie("com.app.a:attr/bar")),
+      Reference(test::parseNameOrDie("com.app.a:attr/bat")),
+      Reference(test::parseNameOrDie("com.app.a:attr/foo"),
+                ResourceId(0x01010000)),
+  };
 
-    EXPECT_EQ(expectedRefs, styleable->entries);
+  EXPECT_EQ(expectedRefs, styleable->entries);
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/VersionCollapser.cpp b/tools/aapt2/link/VersionCollapser.cpp
index 949d656..61a1f86 100644
--- a/tools/aapt2/link/VersionCollapser.cpp
+++ b/tools/aapt2/link/VersionCollapser.cpp
@@ -24,129 +24,140 @@
 
 template <typename Iterator, typename Pred>
 class FilterIterator {
-public:
-    FilterIterator(Iterator begin, Iterator end, Pred pred=Pred()) :
-            mCurrent(begin), mEnd(end), mPred(pred) {
-        advance();
-    }
+ public:
+  FilterIterator(Iterator begin, Iterator end, Pred pred = Pred())
+      : mCurrent(begin), mEnd(end), mPred(pred) {
+    advance();
+  }
 
-    bool hasNext() {
-        return mCurrent != mEnd;
-    }
+  bool hasNext() { return mCurrent != mEnd; }
 
-    Iterator nextIter() {
-        Iterator iter = mCurrent;
-        ++mCurrent;
-        advance();
-        return iter;
-    }
+  Iterator nextIter() {
+    Iterator iter = mCurrent;
+    ++mCurrent;
+    advance();
+    return iter;
+  }
 
-    typename Iterator::reference next() {
-        return *nextIter();
-    }
+  typename Iterator::reference next() { return *nextIter(); }
 
-private:
-    void advance() {
-        for (; mCurrent != mEnd; ++mCurrent) {
-            if (mPred(*mCurrent)) {
-                return;
-            }
-        }
+ private:
+  void advance() {
+    for (; mCurrent != mEnd; ++mCurrent) {
+      if (mPred(*mCurrent)) {
+        return;
+      }
     }
+  }
 
-    Iterator mCurrent, mEnd;
-    Pred mPred;
+  Iterator mCurrent, mEnd;
+  Pred mPred;
 };
 
 template <typename Iterator, typename Pred>
-FilterIterator<Iterator, Pred> makeFilterIterator(Iterator begin, Iterator end=Iterator(),
-                                                  Pred pred=Pred()) {
-    return FilterIterator<Iterator, Pred>(begin, end, pred);
+FilterIterator<Iterator, Pred> makeFilterIterator(Iterator begin,
+                                                  Iterator end = Iterator(),
+                                                  Pred pred = Pred()) {
+  return FilterIterator<Iterator, Pred>(begin, end, pred);
 }
 
 /**
- * Every Configuration with an SDK version specified that is less than minSdk will be removed.
- * The exception is when there is no exact matching resource for the minSdk. The next smallest
+ * Every Configuration with an SDK version specified that is less than minSdk
+ * will be removed.
+ * The exception is when there is no exact matching resource for the minSdk. The
+ * next smallest
  * one will be kept.
  */
 static void collapseVersions(int minSdk, ResourceEntry* entry) {
-    // First look for all sdks less than minSdk.
-    for (auto iter = entry->values.rbegin(); iter != entry->values.rend(); ++iter) {
-        // Check if the item was already marked for removal.
-        if (!(*iter)) {
-            continue;
-        }
-
-        const ConfigDescription& config = (*iter)->config;
-        if (config.sdkVersion <= minSdk) {
-            // This is the first configuration we've found with a smaller or equal SDK level
-            // to the minimum. We MUST keep this one, but remove all others we find, which get
-            // overridden by this one.
-
-            ConfigDescription configWithoutSdk = config;
-            configWithoutSdk.sdkVersion = 0;
-            auto pred = [&](const std::unique_ptr<ResourceConfigValue>& val) -> bool {
-                // Check that the value hasn't already been marked for removal.
-                if (!val) {
-                    return false;
-                }
-
-                // Only return Configs that differ in SDK version.
-                configWithoutSdk.sdkVersion = val->config.sdkVersion;
-                return configWithoutSdk == val->config && val->config.sdkVersion <= minSdk;
-            };
-
-            // Remove the rest that match.
-            auto filterIter = makeFilterIterator(iter + 1, entry->values.rend(), pred);
-            while (filterIter.hasNext()) {
-                filterIter.next() = {};
-            }
-        }
+  // First look for all sdks less than minSdk.
+  for (auto iter = entry->values.rbegin(); iter != entry->values.rend();
+       ++iter) {
+    // Check if the item was already marked for removal.
+    if (!(*iter)) {
+      continue;
     }
 
-    // Now erase the nullptr values.
-    entry->values.erase(std::remove_if(entry->values.begin(), entry->values.end(),
-                   [](const std::unique_ptr<ResourceConfigValue>& val) -> bool {
-        return val == nullptr;
-    }), entry->values.end());
+    const ConfigDescription& config = (*iter)->config;
+    if (config.sdkVersion <= minSdk) {
+      // This is the first configuration we've found with a smaller or equal SDK
+      // level
+      // to the minimum. We MUST keep this one, but remove all others we find,
+      // which get
+      // overridden by this one.
 
-    // Strip the version qualifiers for every resource with version <= minSdk. This will ensure
-    // that the resource entries are all packed together in the same ResTable_type struct
-    // and take up less space in the resources.arsc table.
-    bool modified = false;
-    for (std::unique_ptr<ResourceConfigValue>& configValue : entry->values) {
-        if (configValue->config.sdkVersion != 0 && configValue->config.sdkVersion <= minSdk) {
-            // Override the resource with a Configuration without an SDK.
-            std::unique_ptr<ResourceConfigValue> newValue = util::make_unique<ResourceConfigValue>(
-                    configValue->config.copyWithoutSdkVersion(), configValue->product);
-            newValue->value = std::move(configValue->value);
-            configValue = std::move(newValue);
-
-            modified = true;
+      ConfigDescription configWithoutSdk = config;
+      configWithoutSdk.sdkVersion = 0;
+      auto pred = [&](const std::unique_ptr<ResourceConfigValue>& val) -> bool {
+        // Check that the value hasn't already been marked for removal.
+        if (!val) {
+          return false;
         }
-    }
 
-    if (modified) {
-        // We've modified the keys (ConfigDescription) by changing the sdkVersion to 0.
-        // We MUST re-sort to ensure ordering guarantees hold.
-        std::sort(entry->values.begin(), entry->values.end(),
-                  [](const std::unique_ptr<ResourceConfigValue>& a,
-                     const std::unique_ptr<ResourceConfigValue>& b) -> bool {
-            return a->config.compare(b->config) < 0;
-        });
+        // Only return Configs that differ in SDK version.
+        configWithoutSdk.sdkVersion = val->config.sdkVersion;
+        return configWithoutSdk == val->config &&
+               val->config.sdkVersion <= minSdk;
+      };
+
+      // Remove the rest that match.
+      auto filterIter =
+          makeFilterIterator(iter + 1, entry->values.rend(), pred);
+      while (filterIter.hasNext()) {
+        filterIter.next() = {};
+      }
     }
+  }
+
+  // Now erase the nullptr values.
+  entry->values.erase(
+      std::remove_if(entry->values.begin(), entry->values.end(),
+                     [](const std::unique_ptr<ResourceConfigValue>& val)
+                         -> bool { return val == nullptr; }),
+      entry->values.end());
+
+  // Strip the version qualifiers for every resource with version <= minSdk.
+  // This will ensure
+  // that the resource entries are all packed together in the same ResTable_type
+  // struct
+  // and take up less space in the resources.arsc table.
+  bool modified = false;
+  for (std::unique_ptr<ResourceConfigValue>& configValue : entry->values) {
+    if (configValue->config.sdkVersion != 0 &&
+        configValue->config.sdkVersion <= minSdk) {
+      // Override the resource with a Configuration without an SDK.
+      std::unique_ptr<ResourceConfigValue> newValue =
+          util::make_unique<ResourceConfigValue>(
+              configValue->config.copyWithoutSdkVersion(),
+              configValue->product);
+      newValue->value = std::move(configValue->value);
+      configValue = std::move(newValue);
+
+      modified = true;
+    }
+  }
+
+  if (modified) {
+    // We've modified the keys (ConfigDescription) by changing the sdkVersion to
+    // 0.
+    // We MUST re-sort to ensure ordering guarantees hold.
+    std::sort(entry->values.begin(), entry->values.end(),
+              [](const std::unique_ptr<ResourceConfigValue>& a,
+                 const std::unique_ptr<ResourceConfigValue>& b) -> bool {
+                return a->config.compare(b->config) < 0;
+              });
+  }
 }
 
 bool VersionCollapser::consume(IAaptContext* context, ResourceTable* table) {
-    const int minSdk = context->getMinSdkVersion();
-    for (auto& package : table->packages) {
-        for (auto& type : package->types) {
-            for (auto& entry : type->entries) {
-                collapseVersions(minSdk, entry.get());
-            }
-        }
+  const int minSdk = context->getMinSdkVersion();
+  for (auto& package : table->packages) {
+    for (auto& type : package->types) {
+      for (auto& entry : type->entries) {
+        collapseVersions(minSdk, entry.get());
+      }
     }
-    return true;
+  }
+  return true;
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/VersionCollapser_test.cpp b/tools/aapt2/link/VersionCollapser_test.cpp
index dd5f1d1..c0e0ddb 100644
--- a/tools/aapt2/link/VersionCollapser_test.cpp
+++ b/tools/aapt2/link/VersionCollapser_test.cpp
@@ -22,82 +22,96 @@
 template <typename T>
 using uptr = std::unique_ptr<T>;
 
-static uptr<ResourceTable> buildTableWithConfigs(const StringPiece& name,
-                                                 std::initializer_list<std::string> list) {
-    test::ResourceTableBuilder builder;
-    for (const std::string& item : list) {
-        builder.addSimple(name, test::parseConfigOrDie(item));
-    }
-    return builder.build();
+static uptr<ResourceTable> buildTableWithConfigs(
+    const StringPiece& name, std::initializer_list<std::string> list) {
+  test::ResourceTableBuilder builder;
+  for (const std::string& item : list) {
+    builder.addSimple(name, test::parseConfigOrDie(item));
+  }
+  return builder.build();
 }
 
 TEST(VersionCollapserTest, CollapseVersions) {
-    uptr<IAaptContext> context = test::ContextBuilder().setMinSdkVersion(7).build();
+  uptr<IAaptContext> context =
+      test::ContextBuilder().setMinSdkVersion(7).build();
 
-    const StringPiece resName = "@android:string/foo";
+  const StringPiece resName = "@android:string/foo";
 
-    uptr<ResourceTable> table =
-            buildTableWithConfigs(resName,
-                                  { "land-v4", "land-v5", "sw600dp", "land-v6",
-                                          "land-v14", "land-v21" });
+  uptr<ResourceTable> table = buildTableWithConfigs(
+      resName,
+      {"land-v4", "land-v5", "sw600dp", "land-v6", "land-v14", "land-v21"});
 
-    VersionCollapser collapser;
-    ASSERT_TRUE(collapser.consume(context.get(), table.get()));
+  VersionCollapser collapser;
+  ASSERT_TRUE(collapser.consume(context.get(), table.get()));
 
-    // These should be removed.
-    EXPECT_EQ(nullptr,
-              test::getValueForConfig<Id>(table.get(), resName, test::parseConfigOrDie("land-v4")));
-    EXPECT_EQ(nullptr,
-              test::getValueForConfig<Id>(table.get(), resName, test::parseConfigOrDie("land-v5")));
-    // This one should be removed because it was renamed to 'land', with the version dropped.
-    EXPECT_EQ(nullptr,
-              test::getValueForConfig<Id>(table.get(), resName, test::parseConfigOrDie("land-v6")));
+  // These should be removed.
+  EXPECT_EQ(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v4")));
+  EXPECT_EQ(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v5")));
+  // This one should be removed because it was renamed to 'land', with the
+  // version dropped.
+  EXPECT_EQ(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v6")));
 
-    // These should remain.
-    EXPECT_NE(nullptr,
-              test::getValueForConfig<Id>(table.get(), resName, test::parseConfigOrDie("sw600dp")));
+  // These should remain.
+  EXPECT_NE(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("sw600dp")));
 
-    // 'land' should be present because it was renamed from 'land-v6'.
-    EXPECT_NE(nullptr,
-              test::getValueForConfig<Id>(table.get(), resName, test::parseConfigOrDie("land")));
-    EXPECT_NE(nullptr,
-              test::getValueForConfig<Id>(table.get(), resName, test::parseConfigOrDie("land-v14")));
-    EXPECT_NE(nullptr,
-              test::getValueForConfig<Id>(table.get(), resName, test::parseConfigOrDie("land-v21")));
+  // 'land' should be present because it was renamed from 'land-v6'.
+  EXPECT_NE(nullptr, test::getValueForConfig<Id>(
+                         table.get(), resName, test::parseConfigOrDie("land")));
+  EXPECT_NE(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v14")));
+  EXPECT_NE(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v21")));
 }
 
 TEST(VersionCollapserTest, CollapseVersionsWhenMinSdkIsHighest) {
-    uptr<IAaptContext> context = test::ContextBuilder().setMinSdkVersion(21).build();
+  uptr<IAaptContext> context =
+      test::ContextBuilder().setMinSdkVersion(21).build();
 
-    const StringPiece resName = "@android:string/foo";
+  const StringPiece resName = "@android:string/foo";
 
-    uptr<ResourceTable> table =
-                buildTableWithConfigs(resName,
-                                      { "land-v4", "land-v5", "sw600dp", "land-v6",
-                                              "land-v14", "land-v21", "land-v22" });
-    VersionCollapser collapser;
-    ASSERT_TRUE(collapser.consume(context.get(), table.get()));
+  uptr<ResourceTable> table = buildTableWithConfigs(
+      resName, {"land-v4", "land-v5", "sw600dp", "land-v6", "land-v14",
+                "land-v21", "land-v22"});
+  VersionCollapser collapser;
+  ASSERT_TRUE(collapser.consume(context.get(), table.get()));
 
-    // These should all be removed.
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(table.get(), resName,
-                                                   test::parseConfigOrDie("land-v4")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(table.get(), resName,
-                                                   test::parseConfigOrDie("land-v5")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(table.get(), resName,
-                                                   test::parseConfigOrDie("land-v6")));
-    EXPECT_EQ(nullptr, test::getValueForConfig<Id>(table.get(), resName,
-                                                   test::parseConfigOrDie("land-v14")));
+  // These should all be removed.
+  EXPECT_EQ(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v4")));
+  EXPECT_EQ(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v5")));
+  EXPECT_EQ(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v6")));
+  EXPECT_EQ(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v14")));
 
-    // These should remain.
-    EXPECT_NE(nullptr, test::getValueForConfig<Id>(
-            table.get(), resName, test::parseConfigOrDie("sw600dp").copyWithoutSdkVersion()));
+  // These should remain.
+  EXPECT_NE(nullptr,
+            test::getValueForConfig<Id>(
+                table.get(), resName,
+                test::parseConfigOrDie("sw600dp").copyWithoutSdkVersion()));
 
-    // land-v21 should have been converted to land.
-    EXPECT_NE(nullptr, test::getValueForConfig<Id>(table.get(), resName,
-                                                   test::parseConfigOrDie("land")));
-    // land-v22 should remain as-is.
-    EXPECT_NE(nullptr, test::getValueForConfig<Id>(table.get(), resName,
-                                                   test::parseConfigOrDie("land-v22")));
+  // land-v21 should have been converted to land.
+  EXPECT_NE(nullptr, test::getValueForConfig<Id>(
+                         table.get(), resName, test::parseConfigOrDie("land")));
+  // land-v22 should remain as-is.
+  EXPECT_NE(nullptr,
+            test::getValueForConfig<Id>(table.get(), resName,
+                                        test::parseConfigOrDie("land-v22")));
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/XmlNamespaceRemover.cpp b/tools/aapt2/link/XmlNamespaceRemover.cpp
index 9f95177..6e8d80d 100644
--- a/tools/aapt2/link/XmlNamespaceRemover.cpp
+++ b/tools/aapt2/link/XmlNamespaceRemover.cpp
@@ -27,57 +27,59 @@
  * Visits each xml Node, removing URI references and nested namespaces.
  */
 class XmlVisitor : public xml::Visitor {
-public:
-    XmlVisitor(bool keepUris) : mKeepUris(keepUris) {
-    }
+ public:
+  XmlVisitor(bool keepUris) : mKeepUris(keepUris) {}
 
-    void visit(xml::Element* el) override {
-        // Strip namespaces
-        for (auto& child : el->children) {
-            while (child && xml::nodeCast<xml::Namespace>(child.get())) {
-                if (child->children.empty()) {
-                    child = {};
-                } else {
-                    child = std::move(child->children.front());
-                    child->parent = el;
-                }
-            }
+  void visit(xml::Element* el) override {
+    // Strip namespaces
+    for (auto& child : el->children) {
+      while (child && xml::nodeCast<xml::Namespace>(child.get())) {
+        if (child->children.empty()) {
+          child = {};
+        } else {
+          child = std::move(child->children.front());
+          child->parent = el;
         }
-        el->children.erase(std::remove_if(el->children.begin(), el->children.end(),
-                [](const std::unique_ptr<xml::Node>& child) -> bool {
-            return child == nullptr;
-        }), el->children.end());
-
-        if (!mKeepUris) {
-            for (xml::Attribute& attr : el->attributes) {
-                attr.namespaceUri = std::string();
-            }
-            el->namespaceUri = std::string();
-        }
-        xml::Visitor::visit(el);
+      }
     }
+    el->children.erase(
+        std::remove_if(el->children.begin(), el->children.end(),
+                       [](const std::unique_ptr<xml::Node>& child) -> bool {
+                         return child == nullptr;
+                       }),
+        el->children.end());
 
-private:
-    bool mKeepUris;
+    if (!mKeepUris) {
+      for (xml::Attribute& attr : el->attributes) {
+        attr.namespaceUri = std::string();
+      }
+      el->namespaceUri = std::string();
+    }
+    xml::Visitor::visit(el);
+  }
+
+ private:
+  bool mKeepUris;
 };
 
-} // namespace
+}  // namespace
 
-bool XmlNamespaceRemover::consume(IAaptContext* context, xml::XmlResource* resource) {
-    if (!resource->root) {
-        return false;
+bool XmlNamespaceRemover::consume(IAaptContext* context,
+                                  xml::XmlResource* resource) {
+  if (!resource->root) {
+    return false;
+  }
+  // Replace any root namespaces until the root is a non-namespace node
+  while (xml::nodeCast<xml::Namespace>(resource->root.get())) {
+    if (resource->root->children.empty()) {
+      break;
     }
-    // Replace any root namespaces until the root is a non-namespace node
-    while (xml::nodeCast<xml::Namespace>(resource->root.get())) {
-        if (resource->root->children.empty()) {
-            break;
-        }
-        resource->root = std::move(resource->root->children.front());
-        resource->root->parent = nullptr;
-    }
-    XmlVisitor visitor(mKeepUris);
-    resource->root->accept(&visitor);
-    return true;
+    resource->root = std::move(resource->root->children.front());
+    resource->root->parent = nullptr;
+  }
+  XmlVisitor visitor(mKeepUris);
+  resource->root->accept(&visitor);
+  return true;
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/XmlNamespaceRemover_test.cpp b/tools/aapt2/link/XmlNamespaceRemover_test.cpp
index e72ea439..d2daaee 100644
--- a/tools/aapt2/link/XmlNamespaceRemover_test.cpp
+++ b/tools/aapt2/link/XmlNamespaceRemover_test.cpp
@@ -20,90 +20,92 @@
 namespace aapt {
 
 class XmlUriTestVisitor : public xml::Visitor {
-public:
-    void visit(xml::Element* el) override {
-        for (const auto& attr : el->attributes) {
-            EXPECT_EQ(std::string(), attr.namespaceUri);
-        }
-        EXPECT_EQ(std::string(), el->namespaceUri);
-        xml::Visitor::visit(el);
+ public:
+  void visit(xml::Element* el) override {
+    for (const auto& attr : el->attributes) {
+      EXPECT_EQ(std::string(), attr.namespaceUri);
     }
+    EXPECT_EQ(std::string(), el->namespaceUri);
+    xml::Visitor::visit(el);
+  }
 
-    void visit(xml::Namespace* ns) override {
-        EXPECT_EQ(std::string(), ns->namespaceUri);
-        xml::Visitor::visit(ns);
-    }
+  void visit(xml::Namespace* ns) override {
+    EXPECT_EQ(std::string(), ns->namespaceUri);
+    xml::Visitor::visit(ns);
+  }
 };
 
 class XmlNamespaceTestVisitor : public xml::Visitor {
-public:
-    void visit(xml::Namespace* ns) override {
-        ADD_FAILURE() << "Detected namespace: "
-                << ns->namespacePrefix << "=\"" << ns->namespaceUri << "\"";
-        xml::Visitor::visit(ns);
-    }
+ public:
+  void visit(xml::Namespace* ns) override {
+    ADD_FAILURE() << "Detected namespace: " << ns->namespacePrefix << "=\""
+                  << ns->namespaceUri << "\"";
+    xml::Visitor::visit(ns);
+  }
 };
 
 class XmlNamespaceRemoverTest : public ::testing::Test {
-public:
-    void SetUp() override {
-        mContext = test::ContextBuilder()
-                .setCompilationPackage("com.app.test")
-                .build();
-    }
+ public:
+  void SetUp() override {
+    mContext =
+        test::ContextBuilder().setCompilationPackage("com.app.test").build();
+  }
 
-protected:
-    std::unique_ptr<IAaptContext> mContext;
+ protected:
+  std::unique_ptr<IAaptContext> mContext;
 };
 
 TEST_F(XmlNamespaceRemoverTest, RemoveUris) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
             <View xmlns:android="http://schemas.android.com/apk/res/android"
                   android:text="hello" />)EOF");
 
-    XmlNamespaceRemover remover;
-    ASSERT_TRUE(remover.consume(mContext.get(), doc.get()));
+  XmlNamespaceRemover remover;
+  ASSERT_TRUE(remover.consume(mContext.get(), doc.get()));
 
-    xml::Node* root = doc.get()->root.get();
-    ASSERT_NE(root, nullptr);
+  xml::Node* root = doc.get()->root.get();
+  ASSERT_NE(root, nullptr);
 
-    XmlUriTestVisitor visitor;
-    root->accept(&visitor);
+  XmlUriTestVisitor visitor;
+  root->accept(&visitor);
 }
 
 TEST_F(XmlNamespaceRemoverTest, RemoveNamespaces) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
             <View xmlns:android="http://schemas.android.com/apk/res/android"
                   xmlns:foo="http://schemas.android.com/apk/res/foo"
                   foo:bar="foobar"
                   android:text="hello" />)EOF");
 
-    XmlNamespaceRemover remover;
-    ASSERT_TRUE(remover.consume(mContext.get(), doc.get()));
+  XmlNamespaceRemover remover;
+  ASSERT_TRUE(remover.consume(mContext.get(), doc.get()));
 
-    xml::Node* root = doc.get()->root.get();
-    ASSERT_NE(root, nullptr);
+  xml::Node* root = doc.get()->root.get();
+  ASSERT_NE(root, nullptr);
 
-    XmlNamespaceTestVisitor visitor;
-    root->accept(&visitor);
+  XmlNamespaceTestVisitor visitor;
+  root->accept(&visitor);
 }
 
 TEST_F(XmlNamespaceRemoverTest, RemoveNestedNamespaces) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
             <View xmlns:android="http://schemas.android.com/apk/res/android"
                   android:text="hello">
               <View xmlns:foo="http://schemas.example.com/foo"
                     android:text="foo"/>
             </View>)EOF");
 
-    XmlNamespaceRemover remover;
-    ASSERT_TRUE(remover.consume(mContext.get(), doc.get()));
+  XmlNamespaceRemover remover;
+  ASSERT_TRUE(remover.consume(mContext.get(), doc.get()));
 
-    xml::Node* root = doc.get()->root.get();
-    ASSERT_NE(root, nullptr);
+  xml::Node* root = doc.get()->root.get();
+  ASSERT_NE(root, nullptr);
 
-    XmlNamespaceTestVisitor visitor;
-    root->accept(&visitor);
+  XmlNamespaceTestVisitor visitor;
+  root->accept(&visitor);
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/XmlReferenceLinker.cpp b/tools/aapt2/link/XmlReferenceLinker.cpp
index 59ffe15..945f98a 100644
--- a/tools/aapt2/link/XmlReferenceLinker.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker.cpp
@@ -29,146 +29,156 @@
 namespace {
 
 /**
- * Visits all references (including parents of styles, references in styles, arrays, etc) and
- * links their symbolic name to their Resource ID, performing mangling and package aliasing
+ * Visits all references (including parents of styles, references in styles,
+ * arrays, etc) and
+ * links their symbolic name to their Resource ID, performing mangling and
+ * package aliasing
  * as needed.
  */
 class ReferenceVisitor : public ValueVisitor {
-public:
-    using ValueVisitor::visit;
+ public:
+  using ValueVisitor::visit;
 
-    ReferenceVisitor(IAaptContext* context, SymbolTable* symbols, xml::IPackageDeclStack* decls,
-                     CallSite* callSite) :
-             mContext(context), mSymbols(symbols), mDecls(decls), mCallSite(callSite),
-             mError(false) {
+  ReferenceVisitor(IAaptContext* context, SymbolTable* symbols,
+                   xml::IPackageDeclStack* decls, CallSite* callSite)
+      : mContext(context),
+        mSymbols(symbols),
+        mDecls(decls),
+        mCallSite(callSite),
+        mError(false) {}
+
+  void visit(Reference* ref) override {
+    if (!ReferenceLinker::linkReference(ref, mContext, mSymbols, mDecls,
+                                        mCallSite)) {
+      mError = true;
     }
+  }
 
-    void visit(Reference* ref) override {
-        if (!ReferenceLinker::linkReference(ref, mContext, mSymbols, mDecls, mCallSite)) {
-            mError = true;
-        }
-    }
+  bool hasError() const { return mError; }
 
-    bool hasError() const {
-        return mError;
-    }
-
-private:
-    IAaptContext* mContext;
-    SymbolTable* mSymbols;
-    xml::IPackageDeclStack* mDecls;
-    CallSite* mCallSite;
-    bool mError;
+ private:
+  IAaptContext* mContext;
+  SymbolTable* mSymbols;
+  xml::IPackageDeclStack* mDecls;
+  CallSite* mCallSite;
+  bool mError;
 };
 
 /**
  * Visits each xml Element and compiles the attributes within.
  */
 class XmlVisitor : public xml::PackageAwareVisitor {
-public:
-    using xml::PackageAwareVisitor::visit;
+ public:
+  using xml::PackageAwareVisitor::visit;
 
-    XmlVisitor(IAaptContext* context, SymbolTable* symbols, const Source& source,
-               std::set<int>* sdkLevelsFound, CallSite* callSite) :
-            mContext(context), mSymbols(symbols), mSource(source), mSdkLevelsFound(sdkLevelsFound),
-            mCallSite(callSite), mReferenceVisitor(context, symbols, this, callSite) {
-    }
+  XmlVisitor(IAaptContext* context, SymbolTable* symbols, const Source& source,
+             std::set<int>* sdkLevelsFound, CallSite* callSite)
+      : mContext(context),
+        mSymbols(symbols),
+        mSource(source),
+        mSdkLevelsFound(sdkLevelsFound),
+        mCallSite(callSite),
+        mReferenceVisitor(context, symbols, this, callSite) {}
 
-    void visit(xml::Element* el) override {
-        const Source source = mSource.withLine(el->lineNumber);
-        for (xml::Attribute& attr : el->attributes) {
-            Maybe<xml::ExtractedPackage> maybePackage =
-                    xml::extractPackageFromNamespace(attr.namespaceUri);
-            if (maybePackage) {
-                // There is a valid package name for this attribute. We will look this up.
-                StringPiece package = maybePackage.value().package;
-                if (package.empty()) {
-                    // Empty package means the 'current' or 'local' package.
-                    package = mContext->getCompilationPackage();
-                }
-
-                Reference attrRef(ResourceNameRef(package, ResourceType::kAttr, attr.name));
-                attrRef.privateReference = maybePackage.value().privateNamespace;
-
-                std::string errStr;
-                attr.compiledAttribute = ReferenceLinker::compileXmlAttribute(
-                        attrRef, mContext->getNameMangler(), mSymbols, mCallSite, &errStr);
-
-                // Convert the string value into a compiled Value if this is a valid attribute.
-                if (attr.compiledAttribute) {
-                    if (attr.compiledAttribute.value().id) {
-                        // Record all SDK levels from which the attributes were defined.
-                        const size_t sdkLevel = findAttributeSdkLevel(
-                                attr.compiledAttribute.value().id.value());
-                        if (sdkLevel > 1) {
-                            mSdkLevelsFound->insert(sdkLevel);
-                        }
-                    }
-
-                    const Attribute* attribute = &attr.compiledAttribute.value().attribute;
-                    attr.compiledValue = ResourceUtils::tryParseItemForAttribute(attr.value,
-                                                                              attribute);
-                    if (!attr.compiledValue &&
-                            !(attribute->typeMask & android::ResTable_map::TYPE_STRING)) {
-                        // We won't be able to encode this as a string.
-                        mContext->getDiagnostics()->error(
-                                DiagMessage(source) << "'" << attr.value << "' "
-                                                    << "is incompatible with attribute "
-                                                    << package << ":" << attr.name << " "
-                                                    << *attribute);
-                        mError = true;
-                    }
-
-                } else {
-                    mContext->getDiagnostics()->error(DiagMessage(source)
-                                                      << "attribute '" << package << ":"
-                                                      << attr.name << "' " << errStr);
-                    mError = true;
-
-                }
-            } else if (!attr.compiledValue) {
-                // We still encode references, but only if we haven't manually set this to
-                // another compiled value.
-                attr.compiledValue = ResourceUtils::tryParseReference(attr.value);
-            }
-
-            if (attr.compiledValue) {
-                // With a compiledValue, we must resolve the reference and assign it an ID.
-                attr.compiledValue->setSource(source);
-                attr.compiledValue->accept(&mReferenceVisitor);
-            }
+  void visit(xml::Element* el) override {
+    const Source source = mSource.withLine(el->lineNumber);
+    for (xml::Attribute& attr : el->attributes) {
+      Maybe<xml::ExtractedPackage> maybePackage =
+          xml::extractPackageFromNamespace(attr.namespaceUri);
+      if (maybePackage) {
+        // There is a valid package name for this attribute. We will look this
+        // up.
+        StringPiece package = maybePackage.value().package;
+        if (package.empty()) {
+          // Empty package means the 'current' or 'local' package.
+          package = mContext->getCompilationPackage();
         }
 
-        // Call the super implementation.
-        xml::PackageAwareVisitor::visit(el);
+        Reference attrRef(
+            ResourceNameRef(package, ResourceType::kAttr, attr.name));
+        attrRef.privateReference = maybePackage.value().privateNamespace;
+
+        std::string errStr;
+        attr.compiledAttribute = ReferenceLinker::compileXmlAttribute(
+            attrRef, mContext->getNameMangler(), mSymbols, mCallSite, &errStr);
+
+        // Convert the string value into a compiled Value if this is a valid
+        // attribute.
+        if (attr.compiledAttribute) {
+          if (attr.compiledAttribute.value().id) {
+            // Record all SDK levels from which the attributes were defined.
+            const size_t sdkLevel = findAttributeSdkLevel(
+                attr.compiledAttribute.value().id.value());
+            if (sdkLevel > 1) {
+              mSdkLevelsFound->insert(sdkLevel);
+            }
+          }
+
+          const Attribute* attribute =
+              &attr.compiledAttribute.value().attribute;
+          attr.compiledValue =
+              ResourceUtils::tryParseItemForAttribute(attr.value, attribute);
+          if (!attr.compiledValue &&
+              !(attribute->typeMask & android::ResTable_map::TYPE_STRING)) {
+            // We won't be able to encode this as a string.
+            mContext->getDiagnostics()->error(
+                DiagMessage(source) << "'" << attr.value << "' "
+                                    << "is incompatible with attribute "
+                                    << package << ":" << attr.name << " "
+                                    << *attribute);
+            mError = true;
+          }
+
+        } else {
+          mContext->getDiagnostics()->error(DiagMessage(source)
+                                            << "attribute '" << package << ":"
+                                            << attr.name << "' " << errStr);
+          mError = true;
+        }
+      } else if (!attr.compiledValue) {
+        // We still encode references, but only if we haven't manually set this
+        // to
+        // another compiled value.
+        attr.compiledValue = ResourceUtils::tryParseReference(attr.value);
+      }
+
+      if (attr.compiledValue) {
+        // With a compiledValue, we must resolve the reference and assign it an
+        // ID.
+        attr.compiledValue->setSource(source);
+        attr.compiledValue->accept(&mReferenceVisitor);
+      }
     }
 
-    bool hasError() {
-        return mError || mReferenceVisitor.hasError();
-    }
+    // Call the super implementation.
+    xml::PackageAwareVisitor::visit(el);
+  }
 
-private:
-    IAaptContext* mContext;
-    SymbolTable* mSymbols;
-    Source mSource;
-    std::set<int>* mSdkLevelsFound;
-    CallSite* mCallSite;
-    ReferenceVisitor mReferenceVisitor;
-    bool mError = false;
+  bool hasError() { return mError || mReferenceVisitor.hasError(); }
+
+ private:
+  IAaptContext* mContext;
+  SymbolTable* mSymbols;
+  Source mSource;
+  std::set<int>* mSdkLevelsFound;
+  CallSite* mCallSite;
+  ReferenceVisitor mReferenceVisitor;
+  bool mError = false;
 };
 
-} // namespace
+}  // namespace
 
-bool XmlReferenceLinker::consume(IAaptContext* context, xml::XmlResource* resource) {
-    mSdkLevelsFound.clear();
-    CallSite callSite = { resource->file.name };
-    XmlVisitor visitor(context, context->getExternalSymbols(), resource->file.source,
-                       &mSdkLevelsFound, &callSite);
-    if (resource->root) {
-        resource->root->accept(&visitor);
-        return !visitor.hasError();
-    }
-    return false;
+bool XmlReferenceLinker::consume(IAaptContext* context,
+                                 xml::XmlResource* resource) {
+  mSdkLevelsFound.clear();
+  CallSite callSite = {resource->file.name};
+  XmlVisitor visitor(context, context->getExternalSymbols(),
+                     resource->file.source, &mSdkLevelsFound, &callSite);
+  if (resource->root) {
+    resource->root->accept(&visitor);
+    return !visitor.hasError();
+  }
+  return false;
 }
 
-} // namespace aapt
+}  // namespace aapt
diff --git a/tools/aapt2/link/XmlReferenceLinker_test.cpp b/tools/aapt2/link/XmlReferenceLinker_test.cpp
index 51eb62c..35d479f 100644
--- a/tools/aapt2/link/XmlReferenceLinker_test.cpp
+++ b/tools/aapt2/link/XmlReferenceLinker_test.cpp
@@ -20,237 +20,276 @@
 namespace aapt {
 
 class XmlReferenceLinkerTest : public ::testing::Test {
-public:
-    void SetUp() override {
-        mContext = test::ContextBuilder()
-                .setCompilationPackage("com.app.test")
-                .setNameManglerPolicy(
-                        NameManglerPolicy{ "com.app.test", { "com.android.support" } })
-                .addSymbolSource(test::StaticSymbolSourceBuilder()
-                        .addPublicSymbol("android:attr/layout_width", ResourceId(0x01010000),
-                                   test::AttributeBuilder()
-                                        .setTypeMask(android::ResTable_map::TYPE_ENUM |
-                                                     android::ResTable_map::TYPE_DIMENSION)
-                                        .addItem("match_parent", 0xffffffff)
-                                        .build())
-                        .addPublicSymbol("android:attr/background", ResourceId(0x01010001),
-                                   test::AttributeBuilder()
-                                        .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
-                        .addPublicSymbol("android:attr/attr", ResourceId(0x01010002),
-                                   test::AttributeBuilder().build())
-                        .addPublicSymbol("android:attr/text", ResourceId(0x01010003),
-                                   test::AttributeBuilder()
-                                        .setTypeMask(android::ResTable_map::TYPE_STRING)
-                                        .build())
+ public:
+  void SetUp() override {
+    mContext =
+        test::ContextBuilder()
+            .setCompilationPackage("com.app.test")
+            .setNameManglerPolicy(
+                NameManglerPolicy{"com.app.test", {"com.android.support"}})
+            .addSymbolSource(
+                test::StaticSymbolSourceBuilder()
+                    .addPublicSymbol(
+                        "android:attr/layout_width", ResourceId(0x01010000),
+                        test::AttributeBuilder()
+                            .setTypeMask(android::ResTable_map::TYPE_ENUM |
+                                         android::ResTable_map::TYPE_DIMENSION)
+                            .addItem("match_parent", 0xffffffff)
+                            .build())
+                    .addPublicSymbol(
+                        "android:attr/background", ResourceId(0x01010001),
+                        test::AttributeBuilder()
+                            .setTypeMask(android::ResTable_map::TYPE_COLOR)
+                            .build())
+                    .addPublicSymbol("android:attr/attr",
+                                     ResourceId(0x01010002),
+                                     test::AttributeBuilder().build())
+                    .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("android:attr/colorAccent", ResourceId(0x01010435),
-                                   test::AttributeBuilder().build())
+                    // Add one real symbol that was introduces in v21
+                    .addPublicSymbol("android:attr/colorAccent",
+                                     ResourceId(0x01010435),
+                                     test::AttributeBuilder().build())
 
-                        // Private symbol.
-                        .addSymbol("android:color/hidden", ResourceId(0x01020001))
+                    // Private symbol.
+                    .addSymbol("android:color/hidden", ResourceId(0x01020001))
 
-                        .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("com.app.test:attr/com.android.support$colorAccent",
-                                   ResourceId(0x7f010001), test::AttributeBuilder()
-                                       .setTypeMask(android::ResTable_map::TYPE_COLOR).build())
-                        .addPublicSymbol("com.app.test:attr/attr", ResourceId(0x7f010002),
-                                   test::AttributeBuilder().build())
-                        .build())
-                .build();
-    }
+                    .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(
+                        "com.app.test:attr/com.android.support$colorAccent",
+                        ResourceId(0x7f010001),
+                        test::AttributeBuilder()
+                            .setTypeMask(android::ResTable_map::TYPE_COLOR)
+                            .build())
+                    .addPublicSymbol("com.app.test:attr/attr",
+                                     ResourceId(0x7f010002),
+                                     test::AttributeBuilder().build())
+                    .build())
+            .build();
+  }
 
-protected:
-    std::unique_ptr<IAaptContext> mContext;
+ protected:
+  std::unique_ptr<IAaptContext> mContext;
 };
 
 TEST_F(XmlReferenceLinkerTest, LinkBasicAttributes) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
         <View xmlns:android="http://schemas.android.com/apk/res/android"
               android:layout_width="match_parent"
               android:background="@color/green"
               android:text="hello"
               class="hello" />)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
+  XmlReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
 
-    xml::Element* viewEl = xml::findRootElement(doc.get());
-    ASSERT_NE(viewEl, nullptr);
+  xml::Element* viewEl = xml::findRootElement(doc.get());
+  ASSERT_NE(viewEl, nullptr);
 
-    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);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010000));
-    ASSERT_NE(xmlAttr->compiledValue, nullptr);
-    ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
+  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);
+  EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(),
+            ResourceId(0x01010000));
+  ASSERT_NE(xmlAttr->compiledValue, nullptr);
+  ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
 
-    xmlAttr = viewEl->findAttribute(xml::kSchemaAndroid, "background");
-    ASSERT_NE(xmlAttr, nullptr);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010001));
-    ASSERT_NE(xmlAttr->compiledValue, nullptr);
-    Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
-    ASSERT_NE(ref, nullptr);
-    AAPT_ASSERT_TRUE(ref->name);
-    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(xml::kSchemaAndroid, "background");
+  ASSERT_NE(xmlAttr, nullptr);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+  EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(),
+            ResourceId(0x01010001));
+  ASSERT_NE(xmlAttr->compiledValue, nullptr);
+  Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
+  ASSERT_NE(ref, nullptr);
+  AAPT_ASSERT_TRUE(ref->name);
+  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(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(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("", "class");
-    ASSERT_NE(xmlAttr, nullptr);
-    AAPT_ASSERT_FALSE(xmlAttr->compiledAttribute);
-    ASSERT_EQ(xmlAttr->compiledValue, nullptr);
+  xmlAttr = viewEl->findAttribute("", "class");
+  ASSERT_NE(xmlAttr, nullptr);
+  AAPT_ASSERT_FALSE(xmlAttr->compiledAttribute);
+  ASSERT_EQ(xmlAttr->compiledValue, nullptr);
 }
 
 TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreNotLinked) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
         <View xmlns:android="http://schemas.android.com/apk/res/android"
               android:colorAccent="@android:color/hidden" />)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_FALSE(linker.consume(mContext.get(), doc.get()));
+  XmlReferenceLinker linker;
+  ASSERT_FALSE(linker.consume(mContext.get(), doc.get()));
 }
 
-TEST_F(XmlReferenceLinkerTest, PrivateSymbolsAreLinkedWhenReferenceHasStarPrefix) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+TEST_F(XmlReferenceLinkerTest,
+       PrivateSymbolsAreLinkedWhenReferenceHasStarPrefix) {
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
     <View xmlns:android="http://schemas.android.com/apk/res/android"
           android:colorAccent="@*android:color/hidden" />)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
+  XmlReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
 }
 
 TEST_F(XmlReferenceLinkerTest, SdkLevelsAreRecorded) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
         <View xmlns:android="http://schemas.android.com/apk/res/android"
               android:colorAccent="#ffffff" />)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
-    EXPECT_TRUE(linker.getSdkLevels().count(21) == 1);
+  XmlReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
+  EXPECT_TRUE(linker.getSdkLevels().count(21) == 1);
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkMangledAttributes) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
             <View xmlns:support="http://schemas.android.com/apk/res/com.android.support"
                   support:colorAccent="#ff0000" />)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
+  XmlReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
 
-    xml::Element* viewEl = xml::findRootElement(doc.get());
-    ASSERT_NE(viewEl, nullptr);
+  xml::Element* viewEl = xml::findRootElement(doc.get());
+  ASSERT_NE(viewEl, nullptr);
 
-    xml::Attribute* xmlAttr = viewEl->findAttribute(
-            xml::buildPackageNamespace("com.android.support"), "colorAccent");
-    ASSERT_NE(xmlAttr, nullptr);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010001));
-    ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
+  xml::Attribute* xmlAttr = viewEl->findAttribute(
+      xml::buildPackageNamespace("com.android.support"), "colorAccent");
+  ASSERT_NE(xmlAttr, nullptr);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+  EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(),
+            ResourceId(0x7f010001));
+  ASSERT_NE(valueCast<BinaryPrimitive>(xmlAttr->compiledValue.get()), nullptr);
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkAutoResReference) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
             <View xmlns:app="http://schemas.android.com/apk/res-auto"
                   app:colorAccent="@app:color/red" />)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
+  XmlReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
 
-    xml::Element* viewEl = xml::findRootElement(doc.get());
-    ASSERT_NE(viewEl, nullptr);
+  xml::Element* viewEl = xml::findRootElement(doc.get());
+  ASSERT_NE(viewEl, nullptr);
 
-    xml::Attribute* xmlAttr = viewEl->findAttribute(xml::kSchemaAuto, "colorAccent");
-    ASSERT_NE(xmlAttr, nullptr);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010000));
-    Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
-    ASSERT_NE(ref, nullptr);
-    AAPT_ASSERT_TRUE(ref->name);
-    AAPT_ASSERT_TRUE(ref->id);
-    EXPECT_EQ(ref->id.value(), ResourceId(0x7f020001));
+  xml::Attribute* xmlAttr =
+      viewEl->findAttribute(xml::kSchemaAuto, "colorAccent");
+  ASSERT_NE(xmlAttr, nullptr);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+  EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(),
+            ResourceId(0x7f010000));
+  Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
+  ASSERT_NE(ref, nullptr);
+  AAPT_ASSERT_TRUE(ref->name);
+  AAPT_ASSERT_TRUE(ref->id);
+  EXPECT_EQ(ref->id.value(), ResourceId(0x7f020001));
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkViewWithShadowedPackageAlias) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
             <View xmlns:app="http://schemas.android.com/apk/res/android"
                   app:attr="@app:id/id">
               <View xmlns:app="http://schemas.android.com/apk/res/com.app.test"
                     app:attr="@app:id/id"/>
             </View>)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
+  XmlReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
 
-    xml::Element* viewEl = xml::findRootElement(doc.get());
-    ASSERT_NE(viewEl, nullptr);
+  xml::Element* viewEl = xml::findRootElement(doc.get());
+  ASSERT_NE(viewEl, nullptr);
 
-    // All attributes and references in this element should be referring to "android" (0x01).
-    xml::Attribute* xmlAttr = viewEl->findAttribute(xml::kSchemaAndroid, "attr");
-    ASSERT_NE(xmlAttr, nullptr);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
-    AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x01010002));
-    Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
-    ASSERT_NE(ref, nullptr);
-    AAPT_ASSERT_TRUE(ref->id);
-    EXPECT_EQ(ref->id.value(), ResourceId(0x01030000));
+  // All attributes and references in this element should be referring to
+  // "android" (0x01).
+  xml::Attribute* xmlAttr = viewEl->findAttribute(xml::kSchemaAndroid, "attr");
+  ASSERT_NE(xmlAttr, nullptr);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute);
+  AAPT_ASSERT_TRUE(xmlAttr->compiledAttribute.value().id);
+  EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(),
+            ResourceId(0x01010002));
+  Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
+  ASSERT_NE(ref, nullptr);
+  AAPT_ASSERT_TRUE(ref->id);
+  EXPECT_EQ(ref->id.value(), ResourceId(0x01030000));
 
-    ASSERT_FALSE(viewEl->getChildElements().empty());
-    viewEl = viewEl->getChildElements().front();
-    ASSERT_NE(viewEl, nullptr);
+  ASSERT_FALSE(viewEl->getChildElements().empty());
+  viewEl = viewEl->getChildElements().front();
+  ASSERT_NE(viewEl, nullptr);
 
-    // All attributes and references in this element should be referring to "com.app.test" (0x7f).
-    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);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010002));
-    ref = valueCast<Reference>(xmlAttr->compiledValue.get());
-    ASSERT_NE(ref, nullptr);
-    AAPT_ASSERT_TRUE(ref->id);
-    EXPECT_EQ(ref->id.value(), ResourceId(0x7f030000));
+  // All attributes and references in this element should be referring to
+  // "com.app.test" (0x7f).
+  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);
+  EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(),
+            ResourceId(0x7f010002));
+  ref = valueCast<Reference>(xmlAttr->compiledValue.get());
+  ASSERT_NE(ref, nullptr);
+  AAPT_ASSERT_TRUE(ref->id);
+  EXPECT_EQ(ref->id.value(), ResourceId(0x7f030000));
 }
 
 TEST_F(XmlReferenceLinkerTest, LinkViewWithLocalPackageAndAliasOfTheSameName) {
-    std::unique_ptr<xml::XmlResource> doc = test::buildXmlDomForPackageName(mContext.get(), R"EOF(
+  std::unique_ptr<xml::XmlResource> doc =
+      test::buildXmlDomForPackageName(mContext.get(), R"EOF(
             <View xmlns:android="http://schemas.android.com/apk/res/com.app.test"
                   android:attr="@id/id"/>)EOF");
 
-    XmlReferenceLinker linker;
-    ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
+  XmlReferenceLinker linker;
+  ASSERT_TRUE(linker.consume(mContext.get(), doc.get()));
 
-    xml::Element* viewEl = xml::findRootElement(doc.get());
-    ASSERT_NE(viewEl, nullptr);
+  xml::Element* viewEl = xml::findRootElement(doc.get());
+  ASSERT_NE(viewEl, nullptr);
 
-    // All attributes and references in this element should be referring to "com.app.test" (0x7f).
-    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);
-    EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(), ResourceId(0x7f010002));
-    Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
-    ASSERT_NE(ref, nullptr);
-    AAPT_ASSERT_TRUE(ref->id);
-    EXPECT_EQ(ref->id.value(), ResourceId(0x7f030000));
+  // All attributes and references in this element should be referring to
+  // "com.app.test" (0x7f).
+  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);
+  EXPECT_EQ(xmlAttr->compiledAttribute.value().id.value(),
+            ResourceId(0x7f010002));
+  Reference* ref = valueCast<Reference>(xmlAttr->compiledValue.get());
+  ASSERT_NE(ref, nullptr);
+  AAPT_ASSERT_TRUE(ref->id);
+  EXPECT_EQ(ref->id.value(), ResourceId(0x7f030000));
 }
 
-} // namespace aapt
+}  // namespace aapt