AAPT2: Support static lib referencing static lib

When a static library A references static library B,
and app C references both A and B, we get the following symbol merging,
symbols from library B get imported twice.

We must only check that symbol references to library B are valid
when building library A. We should only merge all the symbols
when building final app C.

Change-Id: I23cba33b0901dcbb5328d9c9dfaa6a979c073c36
diff --git a/tools/aapt2/BinaryResourceParser.cpp b/tools/aapt2/BinaryResourceParser.cpp
index d16f63b..bbd21fb 100644
--- a/tools/aapt2/BinaryResourceParser.cpp
+++ b/tools/aapt2/BinaryResourceParser.cpp
@@ -475,10 +475,17 @@
             source.line = entry->sourceLine;
         }
 
-        if (!mTable->markPublic(name, resId, source)) {
+        if (!mTable->markPublicAllowMangled(name, resId, source)) {
             return false;
         }
 
+        // Add this resource name->id mapping to the index so
+        // that we can resolve all ID references to name references.
+        auto cacheIter = mIdIndex.find(resId);
+        if (cacheIter == mIdIndex.end()) {
+            mIdIndex.insert({ resId, name });
+        }
+
         entry++;
     }
     return true;
@@ -611,12 +618,12 @@
             source.line = sourceBlock->line;
         }
 
-        if (!mTable->addResource(name, config, source, std::move(resourceValue))) {
+        if (!mTable->addResourceAllowMangled(name, config, source, std::move(resourceValue))) {
             return false;
         }
 
         if ((entry->flags & ResTable_entry::FLAG_PUBLIC) != 0) {
-            if (!mTable->markPublic(name, resId, mSource.line(0))) {
+            if (!mTable->markPublicAllowMangled(name, resId, mSource.line(0))) {
                 return false;
             }
         }
@@ -635,6 +642,10 @@
                                                        const ConfigDescription& config,
                                                        const Res_value* value,
                                                        uint16_t flags) {
+    if (name.type == ResourceType::kId) {
+        return util::make_unique<Id>();
+    }
+
     if (value->dataType == Res_value::TYPE_STRING) {
         StringPiece16 str = util::getString(mValuePool, value->data);
 
@@ -697,13 +708,6 @@
                                                     StringPool::Context{ 1, config }));
     }
 
-    if (name.type == ResourceType::kId ||
-            (value->dataType == Res_value::TYPE_NULL &&
-            value->data == Res_value::DATA_NULL_UNDEFINED &&
-            (flags & ResTable_entry::FLAG_WEAK) != 0)) {
-        return util::make_unique<Id>();
-    }
-
     // Treat this as a raw binary primitive.
     return util::make_unique<BinaryPrimitive>(*value);
 }
@@ -789,10 +793,21 @@
                 continue;
             }
 
-            attr->symbols.push_back(Attribute::Symbol{
-                    Reference(mapEntry.name.ident),
-                    mapEntry.value.data
-            });
+            Attribute::Symbol symbol;
+            symbol.value = mapEntry.value.data;
+            if (mapEntry.name.ident == 0) {
+                // The map entry's key (id) is not set. This must be
+                // a symbol reference, so resolve it.
+                ResourceNameRef symbolName;
+                bool result = getSymbol(&mapEntry.name.ident, &symbolName);
+                assert(result);
+                symbol.symbol.name = symbolName.toResourceName();
+            } else {
+                // The map entry's key (id) is a regular reference.
+                symbol.symbol.id = mapEntry.name.ident;
+            }
+
+            attr->symbols.push_back(std::move(symbol));
         }
     }