AAPT2: Ensure string pool ordering is compact

Keep styledstrings at the beginning of the StringPool
to reduce the padding in the StyledString array.

Bug:32336940
Test: manual
Change-Id: Iec820c21a54daac40ecc3b2f87517a0f1efc9d3d
diff --git a/tools/aapt2/proto/TableProtoDeserializer.cpp b/tools/aapt2/proto/TableProtoDeserializer.cpp
index 595fa6f..0dfb01c 100644
--- a/tools/aapt2/proto/TableProtoDeserializer.cpp
+++ b/tools/aapt2/proto/TableProtoDeserializer.cpp
@@ -27,445 +27,460 @@
 namespace {
 
 class ReferenceIdToNameVisitor : public ValueVisitor {
-public:
-    using ValueVisitor::visit;
+ public:
+  using ValueVisitor::visit;
 
-    explicit ReferenceIdToNameVisitor(const std::map<ResourceId, ResourceNameRef>* mapping) :
-            mMapping(mapping) {
-        assert(mMapping);
+  explicit ReferenceIdToNameVisitor(
+      const std::map<ResourceId, ResourceNameRef>* mapping)
+      : mMapping(mapping) {
+    assert(mMapping);
+  }
+
+  void visit(Reference* reference) override {
+    if (!reference->id || !reference->id.value().isValid()) {
+      return;
     }
 
-    void visit(Reference* reference) override {
-        if (!reference->id || !reference->id.value().isValid()) {
-            return;
-        }
-
-        ResourceId id = reference->id.value();
-        auto cacheIter = mMapping->find(id);
-        if (cacheIter != mMapping->end()) {
-            reference->name = cacheIter->second.toResourceName();
-        }
+    ResourceId id = reference->id.value();
+    auto cacheIter = mMapping->find(id);
+    if (cacheIter != mMapping->end()) {
+      reference->name = cacheIter->second.toResourceName();
     }
+  }
 
-private:
-    const std::map<ResourceId, ResourceNameRef>* mMapping;
+ private:
+  const std::map<ResourceId, ResourceNameRef>* mMapping;
 };
 
 class PackagePbDeserializer {
-public:
-    PackagePbDeserializer(const android::ResStringPool* valuePool,
-                          const android::ResStringPool* sourcePool,
-                          const android::ResStringPool* symbolPool,
-                          const Source& source, IDiagnostics* diag) :
-            mValuePool(valuePool), mSourcePool(sourcePool), mSymbolPool(symbolPool),
-            mSource(source), mDiag(diag) {
+ public:
+  PackagePbDeserializer(const android::ResStringPool* valuePool,
+                        const android::ResStringPool* sourcePool,
+                        const android::ResStringPool* symbolPool,
+                        const Source& source, IDiagnostics* diag)
+      : mValuePool(valuePool),
+        mSourcePool(sourcePool),
+        mSymbolPool(symbolPool),
+        mSource(source),
+        mDiag(diag) {}
+
+ public:
+  bool deserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
+    Maybe<uint8_t> id;
+    if (pbPackage.has_package_id()) {
+      id = static_cast<uint8_t>(pbPackage.package_id());
     }
 
-public:
-    bool deserializeFromPb(const pb::Package& pbPackage, ResourceTable* table) {
-        Maybe<uint8_t> id;
-        if (pbPackage.has_package_id()) {
-            id = static_cast<uint8_t>(pbPackage.package_id());
-        }
+    std::map<ResourceId, ResourceNameRef> idIndex;
 
-        std::map<ResourceId, ResourceNameRef> idIndex;
+    ResourceTablePackage* pkg =
+        table->createPackage(pbPackage.package_name(), id);
+    for (const pb::Type& pbType : pbPackage.types()) {
+      const ResourceType* resType = parseResourceType(pbType.name());
+      if (!resType) {
+        mDiag->error(DiagMessage(mSource) << "unknown type '" << pbType.name()
+                                          << "'");
+        return {};
+      }
 
-        ResourceTablePackage* pkg = table->createPackage(pbPackage.package_name(), id);
-        for (const pb::Type& pbType : pbPackage.types()) {
-            const ResourceType* resType = parseResourceType(pbType.name());
-            if (!resType) {
-                mDiag->error(DiagMessage(mSource) << "unknown type '" << pbType.name() << "'");
-                return {};
+      ResourceTableType* type = pkg->findOrCreateType(*resType);
+
+      for (const pb::Entry& pbEntry : pbType.entries()) {
+        ResourceEntry* entry = type->findOrCreateEntry(pbEntry.name());
+
+        // Deserialize the symbol status (public/private with source and
+        // comments).
+        if (pbEntry.has_symbol_status()) {
+          const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
+          if (pbStatus.has_source()) {
+            deserializeSourceFromPb(pbStatus.source(), *mSourcePool,
+                                    &entry->symbolStatus.source);
+          }
+
+          if (pbStatus.has_comment()) {
+            entry->symbolStatus.comment = pbStatus.comment();
+          }
+
+          SymbolState visibility =
+              deserializeVisibilityFromPb(pbStatus.visibility());
+          entry->symbolStatus.state = visibility;
+
+          if (visibility == SymbolState::kPublic) {
+            // This is a public symbol, we must encode the ID now if there is
+            // one.
+            if (pbEntry.has_id()) {
+              entry->id = static_cast<uint16_t>(pbEntry.id());
             }
 
-            ResourceTableType* type = pkg->findOrCreateType(*resType);
-
-            for (const pb::Entry& pbEntry : pbType.entries()) {
-                ResourceEntry* entry = type->findOrCreateEntry(pbEntry.name());
-
-                // Deserialize the symbol status (public/private with source and comments).
-                if (pbEntry.has_symbol_status()) {
-                    const pb::SymbolStatus& pbStatus = pbEntry.symbol_status();
-                    if (pbStatus.has_source()) {
-                        deserializeSourceFromPb(pbStatus.source(), *mSourcePool,
-                                                &entry->symbolStatus.source);
-                    }
-
-                    if (pbStatus.has_comment()) {
-                        entry->symbolStatus.comment = pbStatus.comment();
-                    }
-
-                    SymbolState visibility = deserializeVisibilityFromPb(pbStatus.visibility());
-                    entry->symbolStatus.state = visibility;
-
-                    if (visibility == SymbolState::kPublic) {
-                        // This is a public symbol, we must encode the ID now if there is one.
-                        if (pbEntry.has_id()) {
-                            entry->id = static_cast<uint16_t>(pbEntry.id());
-                        }
-
-                        if (type->symbolStatus.state != SymbolState::kPublic) {
-                            // If the type has not been made public, do so now.
-                            type->symbolStatus.state = SymbolState::kPublic;
-                            if (pbType.has_id()) {
-                                type->id = static_cast<uint8_t>(pbType.id());
-                            }
-                        }
-                    } else if (visibility == SymbolState::kPrivate) {
-                        if (type->symbolStatus.state == SymbolState::kUndefined) {
-                            type->symbolStatus.state = SymbolState::kPrivate;
-                        }
-                    }
-                }
-
-                ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
-                if (resId.isValid()) {
-                    idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
-                }
-
-                for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
-                    const pb::ConfigDescription& pbConfig = pbConfigValue.config();
-
-                    ConfigDescription config;
-                    if (!deserializeConfigDescriptionFromPb(pbConfig, &config)) {
-                        mDiag->error(DiagMessage(mSource) << "invalid configuration");
-                        return {};
-                    }
-
-                    ResourceConfigValue* configValue = entry->findOrCreateValue(config,
-                                                                                pbConfig.product());
-                    if (configValue->value) {
-                        // Duplicate config.
-                        mDiag->error(DiagMessage(mSource) << "duplicate configuration");
-                        return {};
-                    }
-
-                    configValue->value = deserializeValueFromPb(pbConfigValue.value(),
-                                                                config, &table->stringPool);
-                    if (!configValue->value) {
-                        return {};
-                    }
-                }
+            if (type->symbolStatus.state != SymbolState::kPublic) {
+              // If the type has not been made public, do so now.
+              type->symbolStatus.state = SymbolState::kPublic;
+              if (pbType.has_id()) {
+                type->id = static_cast<uint8_t>(pbType.id());
+              }
             }
+          } else if (visibility == SymbolState::kPrivate) {
+            if (type->symbolStatus.state == SymbolState::kUndefined) {
+              type->symbolStatus.state = SymbolState::kPrivate;
+            }
+          }
         }
 
-        ReferenceIdToNameVisitor visitor(&idIndex);
-        visitAllValuesInPackage(pkg, &visitor);
-        return true;
+        ResourceId resId(pbPackage.package_id(), pbType.id(), pbEntry.id());
+        if (resId.isValid()) {
+          idIndex[resId] = ResourceNameRef(pkg->name, type->type, entry->name);
+        }
+
+        for (const pb::ConfigValue& pbConfigValue : pbEntry.config_values()) {
+          const pb::ConfigDescription& pbConfig = pbConfigValue.config();
+
+          ConfigDescription config;
+          if (!deserializeConfigDescriptionFromPb(pbConfig, &config)) {
+            mDiag->error(DiagMessage(mSource) << "invalid configuration");
+            return {};
+          }
+
+          ResourceConfigValue* configValue =
+              entry->findOrCreateValue(config, pbConfig.product());
+          if (configValue->value) {
+            // Duplicate config.
+            mDiag->error(DiagMessage(mSource) << "duplicate configuration");
+            return {};
+          }
+
+          configValue->value = deserializeValueFromPb(
+              pbConfigValue.value(), config, &table->stringPool);
+          if (!configValue->value) {
+            return {};
+          }
+        }
+      }
     }
 
-private:
-    std::unique_ptr<Item> deserializeItemFromPb(const pb::Item& pbItem,
+    ReferenceIdToNameVisitor visitor(&idIndex);
+    visitAllValuesInPackage(pkg, &visitor);
+    return true;
+  }
+
+ private:
+  std::unique_ptr<Item> deserializeItemFromPb(const pb::Item& pbItem,
+                                              const ConfigDescription& config,
+                                              StringPool* pool) {
+    if (pbItem.has_ref()) {
+      const pb::Reference& pbRef = pbItem.ref();
+      std::unique_ptr<Reference> ref = util::make_unique<Reference>();
+      if (!deserializeReferenceFromPb(pbRef, ref.get())) {
+        return {};
+      }
+      return std::move(ref);
+
+    } else if (pbItem.has_prim()) {
+      const pb::Primitive& pbPrim = pbItem.prim();
+      android::Res_value prim = {};
+      prim.dataType = static_cast<uint8_t>(pbPrim.type());
+      prim.data = pbPrim.data();
+      return util::make_unique<BinaryPrimitive>(prim);
+
+    } else if (pbItem.has_id()) {
+      return util::make_unique<Id>();
+
+    } else if (pbItem.has_str()) {
+      const uint32_t idx = pbItem.str().idx();
+      const std::string str = util::getString(*mValuePool, idx);
+
+      const android::ResStringPool_span* spans = mValuePool->styleAt(idx);
+      if (spans && spans->name.index != android::ResStringPool_span::END) {
+        StyleString styleStr = {str};
+        while (spans->name.index != android::ResStringPool_span::END) {
+          styleStr.spans.push_back(
+              Span{util::getString(*mValuePool, spans->name.index),
+                   spans->firstChar, spans->lastChar});
+          spans++;
+        }
+        return util::make_unique<StyledString>(pool->makeRef(
+            styleStr,
+            StringPool::Context(StringPool::Context::kStylePriority, config)));
+      }
+      return util::make_unique<String>(
+          pool->makeRef(str, StringPool::Context(config)));
+
+    } else if (pbItem.has_raw_str()) {
+      const uint32_t idx = pbItem.raw_str().idx();
+      const std::string str = util::getString(*mValuePool, idx);
+      return util::make_unique<RawString>(
+          pool->makeRef(str, StringPool::Context(config)));
+
+    } else if (pbItem.has_file()) {
+      const uint32_t idx = pbItem.file().path_idx();
+      const std::string str = util::getString(*mValuePool, idx);
+      return util::make_unique<FileReference>(pool->makeRef(
+          str,
+          StringPool::Context(StringPool::Context::kHighPriority, config)));
+
+    } else {
+      mDiag->error(DiagMessage(mSource) << "unknown item");
+    }
+    return {};
+  }
+
+  std::unique_ptr<Value> deserializeValueFromPb(const pb::Value& pbValue,
                                                 const ConfigDescription& config,
                                                 StringPool* pool) {
-        if (pbItem.has_ref()) {
-            const pb::Reference& pbRef = pbItem.ref();
-            std::unique_ptr<Reference> ref = util::make_unique<Reference>();
-            if (!deserializeReferenceFromPb(pbRef, ref.get())) {
-                return {};
-            }
-            return std::move(ref);
+    const bool isWeak = pbValue.has_weak() ? pbValue.weak() : false;
 
-        } else if (pbItem.has_prim()) {
-            const pb::Primitive& pbPrim = pbItem.prim();
-            android::Res_value prim = {};
-            prim.dataType = static_cast<uint8_t>(pbPrim.type());
-            prim.data = pbPrim.data();
-            return util::make_unique<BinaryPrimitive>(prim);
-
-        } else if (pbItem.has_id()) {
-            return util::make_unique<Id>();
-
-        } else if (pbItem.has_str()) {
-            const uint32_t idx = pbItem.str().idx();
-            const std::string str = util::getString(*mValuePool, idx);
-
-            const android::ResStringPool_span* spans = mValuePool->styleAt(idx);
-            if (spans && spans->name.index != android::ResStringPool_span::END) {
-                StyleString styleStr = { str };
-                while (spans->name.index != android::ResStringPool_span::END) {
-                    styleStr.spans.push_back(Span{
-                            util::getString(*mValuePool, spans->name.index),
-                            spans->firstChar,
-                            spans->lastChar
-                    });
-                    spans++;
-                }
-                return util::make_unique<StyledString>(
-                        pool->makeRef(styleStr, StringPool::Context{ 1, config }));
-            }
-            return util::make_unique<String>(
-                    pool->makeRef(str, StringPool::Context{ 1, config }));
-
-        } else if (pbItem.has_raw_str()) {
-            const uint32_t idx = pbItem.raw_str().idx();
-            const std::string str = util::getString(*mValuePool, idx);
-            return util::make_unique<RawString>(
-                    pool->makeRef(str, StringPool::Context{ 1, config }));
-
-        } else if (pbItem.has_file()) {
-            const uint32_t idx = pbItem.file().path_idx();
-            const std::string str = util::getString(*mValuePool, idx);
-            return util::make_unique<FileReference>(
-                    pool->makeRef(str, StringPool::Context{ 0, config }));
-
-        } else {
-            mDiag->error(DiagMessage(mSource) << "unknown item");
-        }
+    std::unique_ptr<Value> value;
+    if (pbValue.has_item()) {
+      value = deserializeItemFromPb(pbValue.item(), config, pool);
+      if (!value) {
         return {};
-    }
+      }
 
-    std::unique_ptr<Value> deserializeValueFromPb(const pb::Value& pbValue,
-                                                  const ConfigDescription& config,
-                                                  StringPool* pool) {
-        const bool isWeak = pbValue.has_weak() ? pbValue.weak() : false;
-
-        std::unique_ptr<Value> value;
-        if (pbValue.has_item()) {
-            value = deserializeItemFromPb(pbValue.item(), config, pool);
-            if (!value) {
-                return {};
-            }
-
-        } else if (pbValue.has_compound_value()) {
-            const pb::CompoundValue& pbCompoundValue = pbValue.compound_value();
-            if (pbCompoundValue.has_attr()) {
-                const pb::Attribute& pbAttr = pbCompoundValue.attr();
-                std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
-                attr->typeMask = pbAttr.format_flags();
-                attr->minInt = pbAttr.min_int();
-                attr->maxInt = pbAttr.max_int();
-                for (const pb::Attribute_Symbol& pbSymbol : pbAttr.symbols()) {
-                    Attribute::Symbol symbol;
-                    deserializeItemCommon(pbSymbol, &symbol.symbol);
-                    if (!deserializeReferenceFromPb(pbSymbol.name(), &symbol.symbol)) {
-                        return {};
-                    }
-                    symbol.value = pbSymbol.value();
-                    attr->symbols.push_back(std::move(symbol));
-                }
-                value = std::move(attr);
-
-            } else if (pbCompoundValue.has_style()) {
-                const pb::Style& pbStyle = pbCompoundValue.style();
-                std::unique_ptr<Style> style = util::make_unique<Style>();
-                if (pbStyle.has_parent()) {
-                    style->parent = Reference();
-                    if (!deserializeReferenceFromPb(pbStyle.parent(), &style->parent.value())) {
-                        return {};
-                    }
-
-                    if (pbStyle.has_parent_source()) {
-                        Source parentSource;
-                        deserializeSourceFromPb(pbStyle.parent_source(), *mSourcePool,
-                                                &parentSource);
-                        style->parent.value().setSource(std::move(parentSource));
-                    }
-                }
-
-                for (const pb::Style_Entry& pbEntry : pbStyle.entries()) {
-                    Style::Entry entry;
-                    deserializeItemCommon(pbEntry, &entry.key);
-                    if (!deserializeReferenceFromPb(pbEntry.key(), &entry.key)) {
-                        return {};
-                    }
-
-                    entry.value = deserializeItemFromPb(pbEntry.item(), config, pool);
-                    if (!entry.value) {
-                        return {};
-                    }
-
-                    deserializeItemCommon(pbEntry, entry.value.get());
-                    style->entries.push_back(std::move(entry));
-                }
-                value = std::move(style);
-
-            } else if (pbCompoundValue.has_styleable()) {
-                const pb::Styleable& pbStyleable = pbCompoundValue.styleable();
-                std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
-                for (const pb::Styleable_Entry& pbEntry : pbStyleable.entries()) {
-                    Reference attrRef;
-                    deserializeItemCommon(pbEntry, &attrRef);
-                    deserializeReferenceFromPb(pbEntry.attr(), &attrRef);
-                    styleable->entries.push_back(std::move(attrRef));
-                }
-                value = std::move(styleable);
-
-            } else if (pbCompoundValue.has_array()) {
-                const pb::Array& pbArray = pbCompoundValue.array();
-                std::unique_ptr<Array> array = util::make_unique<Array>();
-                for (const pb::Array_Entry& pbEntry : pbArray.entries()) {
-                    std::unique_ptr<Item> item = deserializeItemFromPb(pbEntry.item(), config,
-                                                                       pool);
-                    if (!item) {
-                        return {};
-                    }
-
-                    deserializeItemCommon(pbEntry, item.get());
-                    array->items.push_back(std::move(item));
-                }
-                value = std::move(array);
-
-            } else if (pbCompoundValue.has_plural()) {
-                const pb::Plural& pbPlural = pbCompoundValue.plural();
-                std::unique_ptr<Plural> plural = util::make_unique<Plural>();
-                for (const pb::Plural_Entry& pbEntry : pbPlural.entries()) {
-                    size_t pluralIdx = deserializePluralEnumFromPb(pbEntry.arity());
-                    plural->values[pluralIdx] = deserializeItemFromPb(pbEntry.item(), config,
-                                                                      pool);
-                    if (!plural->values[pluralIdx]) {
-                        return {};
-                    }
-
-                    deserializeItemCommon(pbEntry, plural->values[pluralIdx].get());
-                }
-                value = std::move(plural);
-
-            } else {
-                mDiag->error(DiagMessage(mSource) << "unknown compound value");
-                return {};
-            }
-        } else {
-            mDiag->error(DiagMessage(mSource) << "unknown value");
+    } else if (pbValue.has_compound_value()) {
+      const pb::CompoundValue& pbCompoundValue = pbValue.compound_value();
+      if (pbCompoundValue.has_attr()) {
+        const pb::Attribute& pbAttr = pbCompoundValue.attr();
+        std::unique_ptr<Attribute> attr = util::make_unique<Attribute>(isWeak);
+        attr->typeMask = pbAttr.format_flags();
+        attr->minInt = pbAttr.min_int();
+        attr->maxInt = pbAttr.max_int();
+        for (const pb::Attribute_Symbol& pbSymbol : pbAttr.symbols()) {
+          Attribute::Symbol symbol;
+          deserializeItemCommon(pbSymbol, &symbol.symbol);
+          if (!deserializeReferenceFromPb(pbSymbol.name(), &symbol.symbol)) {
             return {};
+          }
+          symbol.value = pbSymbol.value();
+          attr->symbols.push_back(std::move(symbol));
+        }
+        value = std::move(attr);
+
+      } else if (pbCompoundValue.has_style()) {
+        const pb::Style& pbStyle = pbCompoundValue.style();
+        std::unique_ptr<Style> style = util::make_unique<Style>();
+        if (pbStyle.has_parent()) {
+          style->parent = Reference();
+          if (!deserializeReferenceFromPb(pbStyle.parent(),
+                                          &style->parent.value())) {
+            return {};
+          }
+
+          if (pbStyle.has_parent_source()) {
+            Source parentSource;
+            deserializeSourceFromPb(pbStyle.parent_source(), *mSourcePool,
+                                    &parentSource);
+            style->parent.value().setSource(std::move(parentSource));
+          }
         }
 
-        assert(value && "forgot to set value");
+        for (const pb::Style_Entry& pbEntry : pbStyle.entries()) {
+          Style::Entry entry;
+          deserializeItemCommon(pbEntry, &entry.key);
+          if (!deserializeReferenceFromPb(pbEntry.key(), &entry.key)) {
+            return {};
+          }
 
-        value->setWeak(isWeak);
-        deserializeItemCommon(pbValue, value.get());
-        return value;
+          entry.value = deserializeItemFromPb(pbEntry.item(), config, pool);
+          if (!entry.value) {
+            return {};
+          }
+
+          deserializeItemCommon(pbEntry, entry.value.get());
+          style->entries.push_back(std::move(entry));
+        }
+        value = std::move(style);
+
+      } else if (pbCompoundValue.has_styleable()) {
+        const pb::Styleable& pbStyleable = pbCompoundValue.styleable();
+        std::unique_ptr<Styleable> styleable = util::make_unique<Styleable>();
+        for (const pb::Styleable_Entry& pbEntry : pbStyleable.entries()) {
+          Reference attrRef;
+          deserializeItemCommon(pbEntry, &attrRef);
+          deserializeReferenceFromPb(pbEntry.attr(), &attrRef);
+          styleable->entries.push_back(std::move(attrRef));
+        }
+        value = std::move(styleable);
+
+      } else if (pbCompoundValue.has_array()) {
+        const pb::Array& pbArray = pbCompoundValue.array();
+        std::unique_ptr<Array> array = util::make_unique<Array>();
+        for (const pb::Array_Entry& pbEntry : pbArray.entries()) {
+          std::unique_ptr<Item> item =
+              deserializeItemFromPb(pbEntry.item(), config, pool);
+          if (!item) {
+            return {};
+          }
+
+          deserializeItemCommon(pbEntry, item.get());
+          array->items.push_back(std::move(item));
+        }
+        value = std::move(array);
+
+      } else if (pbCompoundValue.has_plural()) {
+        const pb::Plural& pbPlural = pbCompoundValue.plural();
+        std::unique_ptr<Plural> plural = util::make_unique<Plural>();
+        for (const pb::Plural_Entry& pbEntry : pbPlural.entries()) {
+          size_t pluralIdx = deserializePluralEnumFromPb(pbEntry.arity());
+          plural->values[pluralIdx] =
+              deserializeItemFromPb(pbEntry.item(), config, pool);
+          if (!plural->values[pluralIdx]) {
+            return {};
+          }
+
+          deserializeItemCommon(pbEntry, plural->values[pluralIdx].get());
+        }
+        value = std::move(plural);
+
+      } else {
+        mDiag->error(DiagMessage(mSource) << "unknown compound value");
+        return {};
+      }
+    } else {
+      mDiag->error(DiagMessage(mSource) << "unknown value");
+      return {};
     }
 
-    bool deserializeReferenceFromPb(const pb::Reference& pbRef, Reference* outRef) {
-        outRef->referenceType = deserializeReferenceTypeFromPb(pbRef.type());
-        outRef->privateReference = pbRef.private_();
+    assert(value && "forgot to set value");
 
-        if (!pbRef.has_id() && !pbRef.has_symbol_idx()) {
-            return false;
-        }
+    value->setWeak(isWeak);
+    deserializeItemCommon(pbValue, value.get());
+    return value;
+  }
 
-        if (pbRef.has_id()) {
-            outRef->id = ResourceId(pbRef.id());
-        }
+  bool deserializeReferenceFromPb(const pb::Reference& pbRef,
+                                  Reference* outRef) {
+    outRef->referenceType = deserializeReferenceTypeFromPb(pbRef.type());
+    outRef->privateReference = pbRef.private_();
 
-        if (pbRef.has_symbol_idx()) {
-            const std::string strSymbol = util::getString(*mSymbolPool, pbRef.symbol_idx());
-            ResourceNameRef nameRef;
-            if (!ResourceUtils::parseResourceName(strSymbol, &nameRef, nullptr)) {
-                mDiag->error(DiagMessage(mSource) << "invalid reference name '"
-                             << strSymbol << "'");
-                return false;
-            }
-
-            outRef->name = nameRef.toResourceName();
-        }
-        return true;
+    if (!pbRef.has_id() && !pbRef.has_symbol_idx()) {
+      return false;
     }
 
-    template <typename T>
-    void deserializeItemCommon(const T& pbItem, Value* outValue) {
-        if (pbItem.has_source()) {
-            Source source;
-            deserializeSourceFromPb(pbItem.source(), *mSourcePool, &source);
-            outValue->setSource(std::move(source));
-        }
-
-        if (pbItem.has_comment()) {
-            outValue->setComment(pbItem.comment());
-        }
+    if (pbRef.has_id()) {
+      outRef->id = ResourceId(pbRef.id());
     }
 
-private:
-    const android::ResStringPool* mValuePool;
-    const android::ResStringPool* mSourcePool;
-    const android::ResStringPool* mSymbolPool;
-    const Source mSource;
-    IDiagnostics* mDiag;
+    if (pbRef.has_symbol_idx()) {
+      const std::string strSymbol =
+          util::getString(*mSymbolPool, pbRef.symbol_idx());
+      ResourceNameRef nameRef;
+      if (!ResourceUtils::parseResourceName(strSymbol, &nameRef, nullptr)) {
+        mDiag->error(DiagMessage(mSource) << "invalid reference name '"
+                                          << strSymbol << "'");
+        return false;
+      }
+
+      outRef->name = nameRef.toResourceName();
+    }
+    return true;
+  }
+
+  template <typename T>
+  void deserializeItemCommon(const T& pbItem, Value* outValue) {
+    if (pbItem.has_source()) {
+      Source source;
+      deserializeSourceFromPb(pbItem.source(), *mSourcePool, &source);
+      outValue->setSource(std::move(source));
+    }
+
+    if (pbItem.has_comment()) {
+      outValue->setComment(pbItem.comment());
+    }
+  }
+
+ private:
+  const android::ResStringPool* mValuePool;
+  const android::ResStringPool* mSourcePool;
+  const android::ResStringPool* mSymbolPool;
+  const Source mSource;
+  IDiagnostics* mDiag;
 };
 
-} // namespace
+}  // namespace
 
-std::unique_ptr<ResourceTable> deserializeTableFromPb(const pb::ResourceTable& pbTable,
-                                                      const Source& source,
-                                                      IDiagnostics* diag) {
-    // We import the android namespace because on Windows NO_ERROR is a macro, not an enum, which
-    // causes errors when qualifying it with android::
-    using namespace android;
+std::unique_ptr<ResourceTable> deserializeTableFromPb(
+    const pb::ResourceTable& pbTable, const Source& source,
+    IDiagnostics* diag) {
+  // We import the android namespace because on Windows NO_ERROR is a macro, not
+  // an enum, which
+  // causes errors when qualifying it with android::
+  using namespace android;
 
-    std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
+  std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
 
-    if (!pbTable.has_string_pool()) {
-        diag->error(DiagMessage(source) << "no string pool found");
-        return {};
-    }
+  if (!pbTable.has_string_pool()) {
+    diag->error(DiagMessage(source) << "no string pool found");
+    return {};
+  }
 
-    ResStringPool valuePool;
-    status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
-                                      pbTable.string_pool().data().size());
+  ResStringPool valuePool;
+  status_t result = valuePool.setTo(pbTable.string_pool().data().data(),
+                                    pbTable.string_pool().data().size());
+  if (result != NO_ERROR) {
+    diag->error(DiagMessage(source) << "invalid string pool");
+    return {};
+  }
+
+  ResStringPool sourcePool;
+  if (pbTable.has_source_pool()) {
+    result = sourcePool.setTo(pbTable.source_pool().data().data(),
+                              pbTable.source_pool().data().size());
     if (result != NO_ERROR) {
-        diag->error(DiagMessage(source) << "invalid string pool");
-        return {};
+      diag->error(DiagMessage(source) << "invalid source pool");
+      return {};
     }
+  }
 
-    ResStringPool sourcePool;
-    if (pbTable.has_source_pool()) {
-        result = sourcePool.setTo(pbTable.source_pool().data().data(),
-                                  pbTable.source_pool().data().size());
-        if (result != NO_ERROR) {
-            diag->error(DiagMessage(source) << "invalid source pool");
-            return {};
-        }
+  ResStringPool symbolPool;
+  if (pbTable.has_symbol_pool()) {
+    result = symbolPool.setTo(pbTable.symbol_pool().data().data(),
+                              pbTable.symbol_pool().data().size());
+    if (result != NO_ERROR) {
+      diag->error(DiagMessage(source) << "invalid symbol pool");
+      return {};
     }
+  }
 
-    ResStringPool symbolPool;
-    if (pbTable.has_symbol_pool()) {
-        result = symbolPool.setTo(pbTable.symbol_pool().data().data(),
-                                  pbTable.symbol_pool().data().size());
-        if (result != NO_ERROR) {
-            diag->error(DiagMessage(source) << "invalid symbol pool");
-            return {};
-        }
+  PackagePbDeserializer packagePbDeserializer(&valuePool, &sourcePool,
+                                              &symbolPool, source, diag);
+  for (const pb::Package& pbPackage : pbTable.packages()) {
+    if (!packagePbDeserializer.deserializeFromPb(pbPackage, table.get())) {
+      return {};
     }
-
-    PackagePbDeserializer packagePbDeserializer(&valuePool, &sourcePool, &symbolPool, source, diag);
-    for (const pb::Package& pbPackage : pbTable.packages()) {
-        if (!packagePbDeserializer.deserializeFromPb(pbPackage, table.get())) {
-            return {};
-        }
-    }
-    return table;
+  }
+  return table;
 }
 
-std::unique_ptr<ResourceFile> deserializeCompiledFileFromPb(const pb::CompiledFile& pbFile,
-                                                            const Source& source,
-                                                            IDiagnostics* diag) {
-    std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
+std::unique_ptr<ResourceFile> deserializeCompiledFileFromPb(
+    const pb::CompiledFile& pbFile, const Source& source, IDiagnostics* diag) {
+  std::unique_ptr<ResourceFile> file = util::make_unique<ResourceFile>();
 
-    ResourceNameRef nameRef;
+  ResourceNameRef nameRef;
 
-    // Need to create an lvalue here so that nameRef can point to something real.
-    if (!ResourceUtils::parseResourceName(pbFile.resource_name(), &nameRef)) {
-        diag->error(DiagMessage(source) << "invalid resource name in compiled file header: "
-                    << pbFile.resource_name());
-        return {};
+  // Need to create an lvalue here so that nameRef can point to something real.
+  if (!ResourceUtils::parseResourceName(pbFile.resource_name(), &nameRef)) {
+    diag->error(DiagMessage(source)
+                << "invalid resource name in compiled file header: "
+                << pbFile.resource_name());
+    return {};
+  }
+  file->name = nameRef.toResourceName();
+  file->source.path = pbFile.source_path();
+  deserializeConfigDescriptionFromPb(pbFile.config(), &file->config);
+
+  for (const pb::CompiledFile_Symbol& pbSymbol : pbFile.exported_symbols()) {
+    // Need to create an lvalue here so that nameRef can point to something
+    // real.
+    if (!ResourceUtils::parseResourceName(pbSymbol.resource_name(), &nameRef)) {
+      diag->error(DiagMessage(source)
+                  << "invalid resource name for exported symbol in "
+                     "compiled file header: "
+                  << pbFile.resource_name());
+      return {};
     }
-    file->name = nameRef.toResourceName();
-    file->source.path = pbFile.source_path();
-    deserializeConfigDescriptionFromPb(pbFile.config(), &file->config);
-
-    for (const pb::CompiledFile_Symbol& pbSymbol : pbFile.exported_symbols()) {
-        // Need to create an lvalue here so that nameRef can point to something real.
-        if (!ResourceUtils::parseResourceName(pbSymbol.resource_name(), &nameRef)) {
-            diag->error(DiagMessage(source) << "invalid resource name for exported symbol in "
-                                               "compiled file header: "
-                                            << pbFile.resource_name());
-            return {};
-        }
-        file->exportedSymbols.push_back(
-                SourcedResourceName{ nameRef.toResourceName(), pbSymbol.line_no() });
-    }
-    return file;
+    file->exportedSymbols.push_back(
+        SourcedResourceName{nameRef.toResourceName(), pbSymbol.line_no()});
+  }
+  return file;
 }
 
-} // namespace aapt
+}  // namespace aapt