AAPT2

First checking of AAPT2. The individual phases of AAPT2 work, but there
are some missing pieces.

For early testing we are missing:
- Need to properly mark file references and include them in package
- Need to package into zip

Final AAPT for apps we are missing:
- Need to crush PNGs
- Need to parse 9-patches
- Need to validate all of AndroidManifest.xml
- Need to write align method to align resource tables for splits.

Final AAPT for apps + system we are missing:
- Need to handle overlays
- Need to store comments for R file
- Need to handle --shared-lib (dynamic references too).

New AAPT features coming:
- Need to import compiled libraries
    - Name mangling
    - R file generation for library code

Change-Id: I95f8a63581b81a1f424ae6fb2c373c883b72c18d
diff --git a/tools/aapt2/Linker.cpp b/tools/aapt2/Linker.cpp
new file mode 100644
index 0000000..a863197
--- /dev/null
+++ b/tools/aapt2/Linker.cpp
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Linker.h"
+#include "Logger.h"
+#include "ResourceParser.h"
+#include "ResourceTable.h"
+#include "ResourceValues.h"
+#include "StringPiece.h"
+#include "Util.h"
+
+#include <androidfw/AssetManager.h>
+#include <array>
+#include <iostream>
+#include <map>
+#include <ostream>
+#include <set>
+#include <sstream>
+#include <tuple>
+#include <vector>
+
+namespace aapt {
+
+Linker::Args::Args(const ResourceNameRef& r, const SourceLine& s) : referrer(r), source(s) {
+}
+
+Linker::Linker(std::shared_ptr<ResourceTable> table, std::shared_ptr<Resolver> resolver) :
+        mTable(table), mResolver(resolver), mError(false) {
+}
+
+bool Linker::linkAndValidate() {
+    std::bitset<256> usedTypeIds;
+    std::array<std::set<uint16_t>, 256> usedIds;
+    usedTypeIds.set(0);
+
+    // First build the graph of references.
+    for (auto& type : *mTable) {
+        if (type->typeId != ResourceTableType::kUnsetTypeId) {
+            // The ID for this type has already been set. We
+            // mark this ID as taken so we don't re-assign it
+            // later.
+            usedTypeIds.set(type->typeId);
+        }
+
+        for (auto& entry : type->entries) {
+            if (type->typeId != ResourceTableType::kUnsetTypeId &&
+                    entry->entryId != ResourceEntry::kUnsetEntryId) {
+                // The ID for this entry has already been set. We
+                // mark this ID as taken so we don't re-assign it
+                // later.
+                usedIds[type->typeId].insert(entry->entryId);
+            }
+
+            for (auto& valueConfig : entry->values) {
+                // Dispatch to the right method of this linker
+                // based on the value's type.
+                valueConfig.value->accept(*this, Args{
+                        ResourceNameRef{ mTable->getPackage(), type->type, entry->name },
+                        valueConfig.source
+                });
+            }
+        }
+    }
+
+    /*
+     * Assign resource IDs that are available.
+     */
+    size_t nextTypeIndex = 0;
+    for (auto& type : *mTable) {
+        if (type->typeId == ResourceTableType::kUnsetTypeId) {
+            while (nextTypeIndex < usedTypeIds.size() && usedTypeIds[nextTypeIndex]) {
+                nextTypeIndex++;
+            }
+            type->typeId = nextTypeIndex++;
+        }
+
+        const auto endEntryIter = std::end(usedIds[type->typeId]);
+        auto nextEntryIter = std::begin(usedIds[type->typeId]);
+        size_t nextIndex = 0;
+        for (auto& entry : type->entries) {
+            if (entry->entryId == ResourceTableType::kUnsetTypeId) {
+                while (nextEntryIter != endEntryIter &&
+                        nextIndex == *nextEntryIter) {
+                    nextIndex++;
+                    ++nextEntryIter;
+                }
+                entry->entryId = nextIndex++;
+
+                // Update callers of this resource with the right ID.
+                auto callersIter = mGraph.find(ResourceNameRef{
+                        mTable->getPackage(),
+                        type->type,
+                        entry->name
+                });
+
+                if (callersIter != std::end(mGraph)) {
+                    for (Node& caller : callersIter->second) {
+                        caller.reference->id = ResourceId(mTable->getPackageId(),
+                                                          type->typeId,
+                                                          entry->entryId);
+                    }
+                }
+            }
+        }
+    }
+
+    return !mError;
+}
+
+const Linker::ResourceNameToSourceMap& Linker::getUnresolvedReferences() const {
+    return mUnresolvedSymbols;
+}
+
+void Linker::visit(Reference& reference, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    Maybe<ResourceId> result = mResolver->findId(reference.name);
+    if (!result) {
+        addUnresolvedSymbol(reference.name, args.source);
+        return;
+    }
+
+    const ResourceId& id = result.value();
+    if (id.isValid()) {
+        reference.id = id;
+    } else {
+        // We need to update the ID when it is set, so add it
+        // to the graph.
+        mGraph[reference.name].push_back(Node{
+                args.referrer,
+                args.source.path,
+                args.source.line,
+                &reference
+        });
+    }
+
+    // TODO(adamlesinski): Verify the referencedType is another reference
+    // or a compatible primitive.
+}
+
+void Linker::processAttributeValue(const ResourceNameRef& name, const SourceLine& source,
+        const Attribute& attr, std::unique_ptr<Item>& value) {
+    std::unique_ptr<Item> convertedValue;
+    visitFunc<RawString>(*value, [&](RawString& str) {
+        // This is a raw string, so check if it can be converted to anything.
+        // We can NOT swap value with the converted value in here, since
+        // we called through the original value.
+
+        auto onCreateReference = [&](const ResourceName& name) {
+            mTable->addResource(name, ConfigDescription{},
+                    source, util::make_unique<Id>());
+        };
+
+        convertedValue = ResourceParser::parseItemForAttribute(
+                *str.value, attr, mResolver->getDefaultPackage(),
+                onCreateReference);
+        if (!convertedValue && attr.typeMask & android::ResTable_map::TYPE_STRING) {
+            // Last effort is to parse as a string.
+            util::StringBuilder builder;
+            builder.append(*str.value);
+            if (builder) {
+                convertedValue = util::make_unique<String>(
+                        mTable->getValueStringPool().makeRef(builder.str()));
+            }
+        }
+    });
+
+    if (convertedValue) {
+        value = std::move(convertedValue);
+    }
+
+    // Process this new or old value (it can be a reference!).
+    value->accept(*this, Args{ name, source });
+
+    // Flatten the value to see what resource type it is.
+    android::Res_value resValue;
+    value->flatten(resValue);
+
+    // Always allow references.
+    const uint32_t typeMask = attr.typeMask | android::ResTable_map::TYPE_REFERENCE;
+    if (!(typeMask & ResourceParser::androidTypeToAttributeTypeMask(resValue.dataType))) {
+        Logger::error(source)
+                << *value
+                << " is not compatible with attribute "
+                << attr
+                << "."
+                << std::endl;
+        mError = true;
+    }
+}
+
+void Linker::visit(Style& style, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    if (style.parent.name.isValid()) {
+        visit(style.parent, a);
+    }
+
+    for (Style::Entry& styleEntry : style.entries) {
+        Maybe<Resolver::Entry> result = mResolver->findAttribute(styleEntry.key.name);
+        if (!result || !result.value().attr) {
+            addUnresolvedSymbol(styleEntry.key.name, args.source);
+            continue;
+        }
+
+        const Resolver::Entry& entry = result.value();
+        if (entry.id.isValid()) {
+            styleEntry.key.id = entry.id;
+        } else {
+            // Create a dependency for the style on this attribute.
+            mGraph[styleEntry.key.name].push_back(Node{
+                    args.referrer,
+                    args.source.path,
+                    args.source.line,
+                    &styleEntry.key
+            });
+        }
+        processAttributeValue(args.referrer, args.source, *entry.attr, styleEntry.value);
+    }
+}
+
+void Linker::visit(Attribute& attr, ValueVisitorArgs& a) {
+    static constexpr uint32_t kMask = android::ResTable_map::TYPE_ENUM |
+            android::ResTable_map::TYPE_FLAGS;
+    if (attr.typeMask & kMask) {
+        for (auto& symbol : attr.symbols) {
+            visit(symbol.symbol, a);
+        }
+    }
+}
+
+void Linker::visit(Styleable& styleable, ValueVisitorArgs& a) {
+    for (auto& attrRef : styleable.entries) {
+        visit(attrRef, a);
+    }
+}
+
+void Linker::visit(Sentinel& sentinel, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+    addUnresolvedSymbol(args.referrer, args.source);
+}
+
+void Linker::visit(Array& array, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    for (auto& item : array.items) {
+        item->accept(*this, Args{ args.referrer, args.source });
+    }
+}
+
+void Linker::visit(Plural& plural, ValueVisitorArgs& a) {
+    Args& args = static_cast<Args&>(a);
+
+    for (auto& item : plural.values) {
+        if (item) {
+            item->accept(*this, Args{ args.referrer, args.source });
+        }
+    }
+}
+
+void Linker::addUnresolvedSymbol(const ResourceNameRef& name, const SourceLine& source) {
+    mUnresolvedSymbols[name.toResourceName()].push_back(source);
+}
+
+::std::ostream& operator<<(::std::ostream& out, const Linker::Node& node) {
+    return out << node.name << "(" << node.source << ":" << node.line << ")";
+}
+
+} // namespace aapt