/*
 * 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 "AppInfo.h"
#include "Debug.h"
#include "Flags.h"
#include "Locale.h"
#include "NameMangler.h"
#include "ResourceUtils.h"
#include "compile/IdAssigner.h"
#include "filter/ConfigFilter.h"
#include "flatten/Archive.h"
#include "flatten/TableFlattener.h"
#include "flatten/XmlFlattener.h"
#include "io/FileSystem.h"
#include "io/ZipArchive.h"
#include "java/JavaClassGenerator.h"
#include "java/ManifestClassGenerator.h"
#include "java/ProguardRules.h"
#include "link/Linkers.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"
#include "proto/ProtoSerialize.h"
#include "split/TableSplitter.h"
#include "unflatten/BinaryResourceParser.h"
#include "util/Files.h"
#include "util/StringPiece.h"
#include "xml/XmlDom.h"

#include <google/protobuf/io/coded_stream.h>

#include <fstream>
#include <sys/stat.h>
#include <vector>

namespace aapt {

struct LinkOptions {
    std::string outputPath;
    std::string manifestPath;
    std::vector<std::string> includePaths;
    std::vector<std::string> overlayFiles;
    Maybe<std::string> generateJavaClassPath;
    Maybe<std::u16string> customJavaPackage;
    std::set<std::u16string> extraJavaPackages;
    Maybe<std::string> generateProguardRulesPath;
    bool noAutoVersion = false;
    bool noVersionVectors = false;
    bool staticLib = false;
    bool noStaticLibPackages = false;
    bool generateNonFinalIds = false;
    bool outputToDirectory = false;
    bool autoAddOverlay = false;
    bool doNotCompressAnything = false;
    std::vector<std::string> extensionsToNotCompress;
    Maybe<std::u16string> privateSymbols;
    ManifestFixerOptions manifestFixerOptions;
    std::unordered_set<std::string> products;
    TableSplitterOptions tableSplitterOptions;
};

class LinkContext : public IAaptContext {
public:
    LinkContext() : mNameMangler({}) {
    }

    IDiagnostics* getDiagnostics() override {
        return &mDiagnostics;
    }

    NameMangler* getNameMangler() override {
        return &mNameMangler;
    }

    void setNameManglerPolicy(const NameManglerPolicy& policy) {
        mNameMangler = NameMangler(policy);
    }

    const std::u16string& getCompilationPackage() override {
        return mCompilationPackage;
    }

    void setCompilationPackage(const StringPiece16& packageName) {
        mCompilationPackage = packageName.toString();
    }

    uint8_t getPackageId() override {
        return mPackageId;
    }

    void setPackageId(uint8_t id) {
        mPackageId = id;
    }

    SymbolTable* getExternalSymbols() override {
        return &mSymbols;
    }

    bool verbose() override {
        return mVerbose;
    }

    void setVerbose(bool val) {
        mVerbose = val;
    }

private:
    StdErrDiagnostics mDiagnostics;
    NameMangler mNameMangler;
    std::u16string mCompilationPackage;
    uint8_t mPackageId = 0x0;
    SymbolTable mSymbols;
    bool mVerbose = false;
};

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());
    size_t bufferSize = data->size();

    // If the file ends with .flat, we must strip off the CompiledFileHeader from it.
    if (util::stringEndsWith<char>(file->getSource().path, ".flat")) {
        CompiledFileInputStream inputStream(data->data(), data->size());
        if (!inputStream.CompiledFile()) {
            context->getDiagnostics()->error(DiagMessage(file->getSource())
                                             << "invalid compiled file header");
            return false;
        }
        buffer = reinterpret_cast<const uint8_t*>(inputStream.data());
        bufferSize = inputStream.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");
    return false;
}

/*static std::unique_ptr<ResourceTable> loadTable(const Source& source, const void* data, size_t len,
                                                IDiagnostics* diag) {
    std::unique_ptr<ResourceTable> table = util::make_unique<ResourceTable>();
    BinaryResourceParser parser(diag, table.get(), source, data, len);
    if (!parser.parse()) {
        return {};
    }
    return table;
}*/

static std::unique_ptr<ResourceTable> loadTableFromPb(const Source& source,
                                                      const void* data, size_t len,
                                                      IDiagnostics* diag) {
    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;
}

/**
 * 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> loadBinaryXmlSkipFileExport(const Source& source,
                                                                     const void* data, size_t len,
                                                                     IDiagnostics* diag) {
    CompiledFileInputStream inputStream(data, len);
    if (!inputStream.CompiledFile()) {
        diag->error(DiagMessage(source) << "invalid compiled file header");
        return {};
    }

    const uint8_t* xmlData = reinterpret_cast<const uint8_t*>(inputStream.data());
    const size_t xmlDataLen = inputStream.size();

    std::unique_ptr<xml::XmlResource> xmlRes = xml::inflate(xmlData, xmlDataLen, diag, source);
    if (!xmlRes) {
        return {};
    }
    return xmlRes;
}

static std::unique_ptr<ResourceFile> loadFileExportHeader(const Source& source,
                                                          const void* data, size_t len,
                                                          IDiagnostics* diag) {
    CompiledFileInputStream inputStream(data, len);
    const pb::CompiledFile* pbFile = inputStream.CompiledFile();
    if (!pbFile) {
        diag->error(DiagMessage(source) << "invalid compiled file header");
        return {};
    }

    std::unique_ptr<ResourceFile> resFile = deserializeCompiledFileFromPb(*pbFile, source, diag);
    if (!resFile) {
        return {};
    }
    return resFile;
}

struct ResourceFileFlattenerOptions {
    bool noAutoVersion = false;
    bool noVersionVectors = false;
    bool keepRawValues = false;
    bool doNotCompressAnything = false;
    std::vector<std::string> extensionsToNotCompress;
};

class ResourceFileFlattener {
public:
    ResourceFileFlattener(const ResourceFileFlattenerOptions& options,
                          IAaptContext* context, proguard::KeepSet* keepSet) :
            mOptions(options), mContext(context), mKeepSet(keepSet) {
    }

    bool flatten(ResourceTable* table, IArchiveWriter* archiveWriter);

private:
    struct FileOperation {
        io::IFile* fileToCopy;
        std::unique_ptr<xml::XmlResource> xmlToFlatten;
        std::string dstPath;
        bool skipVersion = false;
    };

    uint32_t getCompressionFlags(const StringPiece& str);

    bool linkAndVersionXmlFile(const ResourceEntry* entry, const ResourceFile& fileDesc,
                               io::IFile* file, ResourceTable* table, FileOperation* outFileOp);

    ResourceFileFlattenerOptions mOptions;
    IAaptContext* mContext;
    proguard::KeepSet* mKeepSet;
};

uint32_t ResourceFileFlattener::getCompressionFlags(const StringPiece& str) {
    if (mOptions.doNotCompressAnything) {
        return 0;
    }

    for (const std::string& extension : mOptions.extensionsToNotCompress) {
        if (util::stringEndsWith<char>(str, extension)) {
            return 0;
        }
    }
    return ArchiveEntry::kCompress;
}

bool ResourceFileFlattener::linkAndVersionXmlFile(const ResourceEntry* entry,
                                                  const ResourceFile& fileDesc,
                                                  io::IFile* file,
                                                  ResourceTable* table,
                                                  FileOperation* outFileOp) {
    const StringPiece srcPath = file->getSource().path;
    if (mContext->verbose()) {
        mContext->getDiagnostics()->note(DiagMessage() << "linking " << srcPath);
    }

    std::unique_ptr<io::IData> data = file->openAsData();
    if (!data) {
        mContext->getDiagnostics()->error(DiagMessage(file->getSource()) << "failed to open file");
        return false;
    }

    if (util::stringEndsWith<char>(srcPath, ".flat")) {
        outFileOp->xmlToFlatten = loadBinaryXmlSkipFileExport(file->getSource(),
                                                              data->data(), data->size(),
                                                              mContext->getDiagnostics());
    } else {
        outFileOp->xmlToFlatten = xml::inflate(data->data(), data->size(),
                                               mContext->getDiagnostics(),
                                               file->getSource());
    }

    if (!outFileOp->xmlToFlatten) {
        return false;
    }

    // Copy the the file description header.
    outFileOp->xmlToFlatten->file = fileDesc;

    XmlReferenceLinker xmlLinker;
    if (!xmlLinker.consume(mContext, outFileOp->xmlToFlatten.get())) {
        return false;
    }

    if (!proguard::collectProguardRules(outFileOp->xmlToFlatten->file.source,
                                        outFileOp->xmlToFlatten.get(), mKeepSet)) {
        return false;
    }

    if (!mOptions.noAutoVersion) {
        if (mOptions.noVersionVectors) {
            // Skip this if it is a vector or animated-vector.
            xml::Element* el = xml::findRootElement(outFileOp->xmlToFlatten.get());
            if (el && el->namespaceUri.empty()) {
                if (el->name == u"vector" || el->name == u"animated-vector") {
                    // We are NOT going to version this file.
                    outFileOp->skipVersion = true;
                    return true;
                }
            }
        }

        // Find the first SDK level used that is higher than this defined config and
        // not superseded by a lower or equal SDK level resource.
        for (int sdkLevel : xmlLinker.getSdkLevels()) {
            if (sdkLevel > outFileOp->xmlToFlatten->file.config.sdkVersion) {
                if (!shouldGenerateVersionedResource(entry, outFileOp->xmlToFlatten->file.config,
                                                     sdkLevel)) {
                    // If we shouldn't generate a versioned resource, stop checking.
                    break;
                }

                ResourceFile versionedFileDesc = outFileOp->xmlToFlatten->file;
                versionedFileDesc.config.sdkVersion = (uint16_t) sdkLevel;

                if (mContext->verbose()) {
                    mContext->getDiagnostics()->note(DiagMessage(versionedFileDesc.source)
                                                     << "auto-versioning resource from config '"
                                                     << outFileOp->xmlToFlatten->file.config
                                                     << "' -> '"
                                                     << versionedFileDesc.config << "'");
                }

                std::u16string genPath = util::utf8ToUtf16(ResourceUtils::buildResourceFileName(
                        versionedFileDesc, mContext->getNameMangler()));

                bool added = table->addFileReferenceAllowMangled(versionedFileDesc.name,
                                                                 versionedFileDesc.config,
                                                                 versionedFileDesc.source,
                                                                 genPath,
                                                                 file,
                                                                 mContext->getDiagnostics());
                if (!added) {
                    return false;
                }
                break;
            }
        }
    }
    return true;
}

/**
 * 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, StringPiece16>, 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();
            for (auto& entry : type->entries) {
                // Iterate via indices because auto generated values can be inserted ahead of
                // the value being processed.
                for (size_t i = 0; i < entry->values.size(); i++) {
                    ResourceConfigValue* configValue = entry->values[i].get();

                    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.dstPath = util::utf16ToUtf8(*fileRef->path);

                    const StringPiece srcPath = file->getSource().path;
                    if (type->type != ResourceType::kRaw &&
                            (util::stringEndsWith<char>(srcPath, ".xml.flat") ||
                            util::stringEndsWith<char>(srcPath, ".xml"))) {
                        ResourceFile fileDesc;
                        fileDesc.config = configValue->config;
                        fileDesc.name = ResourceName(pkg->name, type->type, entry->name);
                        fileDesc.source = fileRef->getSource();
                        if (!linkAndVersionXmlFile(entry.get(), fileDesc, file, table, &fileOp)) {
                            error = true;
                            continue;
                        }

                    } else {
                        fileOp.fileToCopy = file;
                    }

                    // NOTE(adamlesinski): Explicitly construct a StringPiece16 here, or else
                    // we end up copying the string in the std::make_pair() method, then creating
                    // a StringPiece16 from the copy, which would cause us to end up referencing
                    // garbage in the map.
                    const StringPiece16 entryName(entry->name);
                    configSortedFiles[std::make_pair(configValue->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>(config.sdkVersion, 1u);
                    }

                    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;
}

class LinkCommand {
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");
            }

            // 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) {
        // Make sure the first element is <manifest> with package attribute.
        if (xml::Element* manifestEl = xml::findRootElement(xmlRes->root.get())) {
            if (manifestEl->namespaceUri.empty() && manifestEl->name == u"manifest") {
                if (xml::Attribute* packageAttr = manifestEl->findAttribute({}, u"package")) {
                    return AppInfo{ packageAttr->value };
                }
            }
        }
        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 == u"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() {
        if (mOptions.outputToDirectory) {
            return createDirectoryArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
        } else {
            return createZipFileArchiveWriter(mContext->getDiagnostics(), mOptions.outputPath);
        }
    }

    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;
        }

        std::unique_ptr<pb::ResourceTable> pbTable = serializeTableToPb(table);

        // Wrap our IArchiveWriter with an adaptor that implements the ZeroCopyOutputStream
        // interface.
        {
            google::protobuf::io::CopyingOutputStreamAdaptor adaptor(writer);

            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 StringPiece16& packageNameToGenerate,
                       const StringPiece16& outPackage, JavaClassGeneratorOptions javaOptions) {
        if (!mOptions.generateJavaClassPath) {
            return true;
        }

        std::string outPath = mOptions.generateJavaClassPath.value();
        file::appendPath(&outPath, file::packageToPath(util::utf16ToUtf8(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::string outPath = mOptions.generateJavaClassPath.value();
        file::appendPath(&outPath,
                         file::packageToPath(util::utf16ToUtf8(mContext->getCompilationPackage())));
        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;
        }

        ManifestClassGenerator generator;
        if (!generator.generate(mContext->getDiagnostics(), mContext->getCompilationPackage(),
                                manifestXml, &fout)) {
            return false;
        }

        if (!fout) {
            mContext->getDiagnostics()->error(
                    DiagMessage() << "failed writing to '" << outPath << "': " << strerror(errno));
            return false;
        }
        return true;
    }

    bool writeProguardFile(const proguard::KeepSet& keepSet) {
        if (!mOptions.generateProguardRulesPath) {
            return true;
        }

        const std::string& outPath = mOptions.generateProguardRulesPath.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 = u"";
            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 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<char>(path, ".flata") ||
                util::stringEndsWith<char>(path, ".jar") ||
                util::stringEndsWith<char>(path, ".jack") ||
                util::stringEndsWith<char>(path, ".zip")) {
            return mergeArchive(path, override);
        } else if (util::stringEndsWith<char>(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<char>(src.path, ".arsc.flat")) {
            return mergeResourceTable(file, override);

        } else if (util::stringEndsWith<char>(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;
            }

            std::unique_ptr<ResourceFile> resourceFile = loadFileExportHeader(
                    src, data->data(), data->size(), mContext->getDiagnostics());
            if (resourceFile) {
                return mergeCompiledFile(file, resourceFile.get(), override);
            }
            return false;
        }

        // Ignore non .flat files. This could be classes.dex or something else that happens
        // to be in an archive.
        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;
        }

        if (Maybe<AppInfo> maybeAppInfo = extractAppInfoFromManifest(manifestXml.get())) {
            mContext->setCompilationPackage(maybeAppInfo.value().package);
        } else {
            mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
                                             << "no package specified in <manifest> tag");
            return 1;
        }

        if (!util::isJavaPackageName(mContext->getCompilationPackage())) {
            mContext->getDiagnostics()->error(DiagMessage(mOptions.manifestPath)
                                             << "invalid package name '"
                                             << mContext->getCompilationPackage()
                                             << "'");
            return 1;
        }

        mContext->setNameManglerPolicy(NameManglerPolicy{ mContext->getCompilationPackage() });

        if (mContext->getCompilationPackage() == u"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;
            }
        }

        if (!mOptions.staticLib) {
            // Assign IDs if we are building a regular app.
            IdAssigner idAssigner;
            if (!idAssigner.consume(mContext, &mFinalTable)) {
                mContext->getDiagnostics()->error(DiagMessage() << "failed assigning IDs");
                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");
                }

                if (mOptions.tableSplitterOptions.configFilter != nullptr ||
                        mOptions.tableSplitterOptions.preferredDensity) {
                    mContext->getDiagnostics()->warn(
                            DiagMessage() << "can't strip resources when building static library");
                }
            } else {
                ProductFilter productFilter(mOptions.products);
                if (!productFilter.consume(mContext, &mFinalTable)) {
                    mContext->getDiagnostics()->error(DiagMessage() << "failed stripping products");
                    return 1;
                }

                // TODO(adamlesinski): Actually pass in split constraints and handle splits at the file
                // level.
                TableSplitter tableSplitter({}, mOptions.tableSplitterOptions);
                if (!tableSplitter.verifySplitConstraints(mContext)) {
                    return 1;
                }
                tableSplitter.splitTable(&mFinalTable);
            }
        }

        proguard::KeepSet proguardKeepSet;

        std::unique_ptr<IArchiveWriter> archiveWriter = makeArchiveWriter();
        if (!archiveWriter) {
            mContext->getDiagnostics()->error(DiagMessage() << "failed to create archive");
            return 1;
        }

        bool error = false;
        {
            ManifestFixer manifestFixer(mOptions.manifestFixerOptions);
            if (!manifestFixer.consume(mContext, manifestXml.get())) {
                error = true;
            }

            // 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 (!proguard::collectProguardRulesForManifest(Source(mOptions.manifestPath),
                                                               manifestXml.get(),
                                                               &proguardKeepSet)) {
                    error = true;
                }

                if (mOptions.generateJavaClassPath) {
                    if (!writeManifestJavaFile(manifestXml.get())) {
                        error = true;
                    }
                }

                const bool keepRawValues = mOptions.staticLib;
                bool result = flattenXml(manifestXml.get(), "AndroidManifest.xml", {},
                                         keepRawValues, archiveWriter.get(), mContext);
                if (!result) {
                    error = true;
                }
            } else {
                error = true;
            }
        }

        if (error) {
            mContext->getDiagnostics()->error(DiagMessage() << "failed processing manifest");
            return 1;
        }

        ResourceFileFlattenerOptions fileFlattenerOptions;
        fileFlattenerOptions.keepRawValues = mOptions.staticLib;
        fileFlattenerOptions.doNotCompressAnything = mOptions.doNotCompressAnything;
        fileFlattenerOptions.extensionsToNotCompress = mOptions.extensionsToNotCompress;
        fileFlattenerOptions.noAutoVersion = mOptions.noAutoVersion;
        fileFlattenerOptions.noVersionVectors = mOptions.noVersionVectors;
        ResourceFileFlattener fileFlattener(fileFlattenerOptions, mContext, &proguardKeepSet);

        if (!fileFlattener.flatten(&mFinalTable, archiveWriter.get())) {
            mContext->getDiagnostics()->error(DiagMessage() << "failed linking file resources");
            return 1;
        }

        if (!mOptions.noAutoVersion) {
            AutoVersioner versioner;
            if (!versioner.consume(mContext, &mFinalTable)) {
                mContext->getDiagnostics()->error(DiagMessage() << "failed versioning styles");
                return 1;
            }
        }

        if (mOptions.staticLib) {
            if (!flattenTableToPb(&mFinalTable, archiveWriter.get())) {
                mContext->getDiagnostics()->error(DiagMessage()
                                                  << "failed to write resources.arsc.flat");
                return 1;
            }
        } else {
            if (!flattenTable(&mFinalTable, archiveWriter.get())) {
                mContext->getDiagnostics()->error(DiagMessage()
                                                  << "failed to write resources.arsc");
                return 1;
            }
        }

        if (mOptions.generateJavaClassPath) {
            JavaClassGeneratorOptions options;
            options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;

            if (mOptions.staticLib || mOptions.generateNonFinalIds) {
                options.useFinal = false;
            }

            const StringPiece16 actualPackage = mContext->getCompilationPackage();
            StringPiece16 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::u16string& extraPackage : mOptions.extraJavaPackages) {
                if (!writeJavaFile(&mFinalTable, actualPackage, extraPackage, options)) {
                    return 1;
                }
            }
        }

        if (mOptions.generateProguardRulesPath) {
            if (!writeProguardFile(proguardKeepSet)) {
                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;
    Maybe<std::string> privateSymbolsPackage;
    Maybe<std::string> minSdkVersion, targetSdkVersion;
    Maybe<std::string> renameManifestPackage, renameInstrumentationTargetPackage;
    Maybe<std::string> versionCode, versionName;
    Maybe<std::string> customJavaPackage;
    std::vector<std::string> extraJavaPackages;
    Maybe<std::string> configs;
    Maybe<std::string> preferredDensity;
    Maybe<std::string> productList;
    bool legacyXFlag = false;
    bool requireLocalization = false;
    bool verbose = false;
    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.",
                              &options.overlayFiles)
            .optionalFlag("--java", "Directory in which to generate R.java",
                          &options.generateJavaClassPath)
            .optionalFlag("--proguard", "Output file for generated Proguard rules",
                          &options.generateProguardRulesPath)
            .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("-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)
            .optionalFlag("--min-sdk-version", "Default minimum SDK version to use for "
                          "AndroidManifest.xml", &minSdkVersion)
            .optionalFlag("--target-sdk-version", "Default target SDK version to use for "
                          "AndroidManifest.xml", &targetSdkVersion)
            .optionalFlag("--version-code", "Version code (integer) to inject into the "
                          "AndroidManifest.xml if none is present", &versionCode)
            .optionalFlag("--version-name", "Version name to inject into the AndroidManifest.xml "
                          "if none is present", &versionName)
            .optionalSwitch("--static-lib", "Generate a static Android library", &options.staticLib)
            .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("--private-symbols", "Package name to use when generating R.java for "
                          "private symbols.\n"
                          "If not specified, public and private symbols will use the application's "
                          "package name", &privateSymbolsPackage)
            .optionalFlag("--custom-package", "Custom Java package under which to generate R.java",
                          &customJavaPackage)
            .optionalFlagList("--extra-packages", "Generate the same R.java but with different "
                              "package names", &extraJavaPackages)
            .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",
                          &renameManifestPackage)
            .optionalFlag("--rename-instrumentation-target-package",
                          "Changes the name of the target package for instrumentation. Most useful "
                          "when used\nin conjunction with --rename-manifest-package",
                          &renameInstrumentationTargetPackage)
            .optionalFlagList("-0", "File extensions not to compress",
                              &options.extensionsToNotCompress)
            .optionalSwitch("-v", "Enables verbose logging", &verbose);

    if (!flags.parse("aapt2 link", args, &std::cerr)) {
        return 1;
    }

    if (verbose) {
        context.setVerbose(verbose);
    }

    if (privateSymbolsPackage) {
        options.privateSymbols = util::utf8ToUtf16(privateSymbolsPackage.value());
    }

    if (minSdkVersion) {
        options.manifestFixerOptions.minSdkVersionDefault =
                util::utf8ToUtf16(minSdkVersion.value());
    }

    if (targetSdkVersion) {
        options.manifestFixerOptions.targetSdkVersionDefault =
                util::utf8ToUtf16(targetSdkVersion.value());
    }

    if (renameManifestPackage) {
        options.manifestFixerOptions.renameManifestPackage =
                util::utf8ToUtf16(renameManifestPackage.value());
    }

    if (renameInstrumentationTargetPackage) {
        options.manifestFixerOptions.renameInstrumentationTargetPackage =
                util::utf8ToUtf16(renameInstrumentationTargetPackage.value());
    }

    if (versionCode) {
        options.manifestFixerOptions.versionCodeDefault = util::utf8ToUtf16(versionCode.value());
    }

    if (versionName) {
        options.manifestFixerOptions.versionNameDefault = util::utf8ToUtf16(versionName.value());
    }

    if (customJavaPackage) {
        options.customJavaPackage = util::utf8ToUtf16(customJavaPackage.value());
    }

    // Populate the set of extra packages for which to generate R.java.
    for (std::string& extraPackage : extraJavaPackages) {
        // A given package can actually be a colon separated list of packages.
        for (StringPiece package : util::split(extraPackage, ':')) {
            options.extraJavaPackages.insert(util::utf8ToUtf16(package));
        }
    }

    if (productList) {
        for (StringPiece product : util::tokenize<char>(productList.value(), ',')) {
            if (product != "" && product != "default") {
                options.products.insert(product.toString());
            }
        }
    }

    AxisConfigFilter filter;
    if (configs) {
        for (const StringPiece& configStr : util::tokenize<char>(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;
    }

    // Turn off auto versioning for static-libs.
    if (options.staticLib) {
        options.noAutoVersion = true;
        options.noVersionVectors = true;
    }

    LinkCommand cmd(&context, options);
    return cmd.run(flags.getArgs());
}

} // namespace aapt
