/*
 * 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 <sys/stat.h>

#include <fstream>
#include <queue>
#include <unordered_map>
#include <vector>

#include "android-base/errors.h"
#include "android-base/file.h"
#include "androidfw/StringPiece.h"
#include "google/protobuf/io/coded_stream.h"

#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/ManifestFixer.h"
#include "link/ReferenceLinker.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 "xml/XmlDom.h"

using android::StringPiece;
using ::google::protobuf::io::CopyingOutputStreamAdaptor;

namespace aapt {

struct LinkOptions {
  std::string output_path;
  std::string manifest_path;
  std::vector<std::string> include_paths;
  std::vector<std::string> overlay_files;
  bool output_to_directory = false;
  bool auto_add_overlay = false;

  // Java/Proguard options.
  Maybe<std::string> generate_java_class_path;
  Maybe<std::string> custom_java_package;
  std::set<std::string> extra_java_packages;
  Maybe<std::string> generate_proguard_rules_path;
  Maybe<std::string> generate_main_dex_proguard_rules_path;
  bool generate_non_final_ids = false;
  std::vector<std::string> javadoc_annotations;
  Maybe<std::string> private_symbols;

  // Optimizations/features.
  bool no_auto_version = false;
  bool no_version_vectors = false;
  bool no_resource_deduping = false;
  bool no_xml_namespaces = false;
  bool do_not_compress_anything = false;
  std::unordered_set<std::string> extensions_to_not_compress;

  // Static lib options.
  bool static_lib = false;
  bool no_static_lib_packages = false;

  // AndroidManifest.xml massaging options.
  ManifestFixerOptions manifest_fixer_options;

  // Products to use/filter on.
  std::unordered_set<std::string> products;

  // Split APK options.
  TableSplitterOptions table_splitter_options;
  std::vector<SplitConstraints> split_constraints;
  std::vector<std::string> split_paths;

  // Stable ID options.
  std::unordered_map<ResourceName, ResourceId> stable_id_map;
  Maybe<std::string> resource_id_map_path;
};

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

  IDiagnostics* GetDiagnostics() override { return &diagnostics_; }

  NameMangler* GetNameMangler() override { return &name_mangler_; }

  void SetNameManglerPolicy(const NameManglerPolicy& policy) {
    name_mangler_ = NameMangler(policy);
  }

  const std::string& GetCompilationPackage() override {
    return compilation_package_;
  }

  void SetCompilationPackage(const StringPiece& package_name) {
    compilation_package_ = package_name.to_string();
  }

  uint8_t GetPackageId() override { return package_id_; }

  void SetPackageId(uint8_t id) { package_id_ = id; }

  SymbolTable* GetExternalSymbols() override { return &symbols_; }

  bool IsVerbose() override { return verbose_; }

  void SetVerbose(bool val) { verbose_ = val; }

  int GetMinSdkVersion() override { return min_sdk_version_; }

  void SetMinSdkVersion(int minSdk) { min_sdk_version_ = minSdk; }

 private:
  DISALLOW_COPY_AND_ASSIGN(LinkContext);

  StdErrDiagnostics diagnostics_;
  NameMangler name_mangler_;
  std::string compilation_package_;
  uint8_t package_id_ = 0x0;
  SymbolTable symbols_;
  bool verbose_ = false;
  int min_sdk_version_ = 0;
};

static bool CopyFileToArchive(io::IFile* file, const std::string& out_path,
                              uint32_t compression_flags,
                              IArchiveWriter* writer, IAaptContext* context) {
  std::unique_ptr<io::IData> data = file->OpenAsData();
  if (!data) {
    context->GetDiagnostics()->Error(DiagMessage(file->GetSource())
                                     << "failed to open file");
    return false;
  }

  const uint8_t* buffer = reinterpret_cast<const uint8_t*>(data->data());
  const size_t buffer_size = data->size();

  if (context->IsVerbose()) {
    context->GetDiagnostics()->Note(DiagMessage() << "writing " << out_path
                                                  << " to archive");
  }

  if (writer->StartEntry(out_path, compression_flags)) {
    if (writer->WriteEntry(buffer, buffer_size)) {
      if (writer->FinishEntry()) {
        return true;
      }
    }
  }

  context->GetDiagnostics()->Error(DiagMessage() << "failed to write file "
                                                 << out_path);
  return false;
}

static bool FlattenXml(xml::XmlResource* xml_res, const StringPiece& path,
                       Maybe<size_t> max_sdk_level, bool keep_raw_values,
                       IArchiveWriter* writer, IAaptContext* context) {
  BigBuffer buffer(1024);
  XmlFlattenerOptions options = {};
  options.keep_raw_values = keep_raw_values;
  options.max_sdk_level = max_sdk_level;
  XmlFlattener flattener(&buffer, options);
  if (!flattener.Consume(context, xml_res)) {
    return false;
  }

  if (context->IsVerbose()) {
    DiagMessage msg;
    msg << "writing " << path << " to archive";
    if (max_sdk_level) {
      msg << " maxSdkLevel=" << max_sdk_level.value()
          << " keepRawValues=" << keep_raw_values;
    }
    context->GetDiagnostics()->Note(msg);
  }

  if (writer->StartEntry(path, ArchiveEntry::kCompress)) {
    if (writer->WriteEntry(buffer)) {
      if (writer->FinishEntry()) {
        return true;
      }
    }
  }
  context->GetDiagnostics()->Error(DiagMessage() << "failed to write " << path
                                                 << " to archive");
  return false;
}

static std::unique_ptr<ResourceTable> LoadTableFromPb(const Source& source,
                                                      const void* data,
                                                      size_t len,
                                                      IDiagnostics* diag) {
  pb::ResourceTable pb_table;
  if (!pb_table.ParseFromArray(data, len)) {
    diag->Error(DiagMessage(source) << "invalid compiled table");
    return {};
  }

  std::unique_ptr<ResourceTable> table =
      DeserializeTableFromPb(pb_table, 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));
}

struct ResourceFileFlattenerOptions {
  bool no_auto_version = false;
  bool no_version_vectors = false;
  bool no_xml_namespaces = false;
  bool keep_raw_values = false;
  bool do_not_compress_anything = false;
  bool update_proguard_spec = false;
  std::unordered_set<std::string> extensions_to_not_compress;
};

class ResourceFileFlattener {
 public:
  ResourceFileFlattener(const ResourceFileFlattenerOptions& options,
                        IAaptContext* context, proguard::KeepSet* keep_set)
      : options_(options), context_(context), keep_set_(keep_set) {}

  bool Flatten(ResourceTable* table, IArchiveWriter* archive_writer);

 private:
  struct FileOperation {
    ConfigDescription config;

    // The entry this file came from.
    const ResourceEntry* entry;

    // The file to copy as-is.
    io::IFile* file_to_copy;

    // The XML to process and flatten.
    std::unique_ptr<xml::XmlResource> xml_to_flatten;

    // The destination to write this file to.
    std::string dst_path;
    bool skip_version = false;
  };

  uint32_t GetCompressionFlags(const StringPiece& str);

  bool LinkAndVersionXmlFile(ResourceTable* table, FileOperation* file_op,
                             std::queue<FileOperation>* out_file_op_queue);

  ResourceFileFlattenerOptions options_;
  IAaptContext* context_;
  proguard::KeepSet* keep_set_;
};

uint32_t ResourceFileFlattener::GetCompressionFlags(const StringPiece& str) {
  if (options_.do_not_compress_anything) {
    return 0;
  }

  for (const std::string& extension : options_.extensions_to_not_compress) {
    if (util::EndsWith(str, extension)) {
      return 0;
    }
  }
  return ArchiveEntry::kCompress;
}

bool ResourceFileFlattener::LinkAndVersionXmlFile(
    ResourceTable* table, FileOperation* file_op,
    std::queue<FileOperation>* out_file_op_queue) {
  xml::XmlResource* doc = file_op->xml_to_flatten.get();
  const Source& src = doc->file.source;

  if (context_->IsVerbose()) {
    context_->GetDiagnostics()->Note(DiagMessage() << "linking " << src.path);
  }

  XmlReferenceLinker xml_linker;
  if (!xml_linker.Consume(context_, doc)) {
    return false;
  }

  if (options_.update_proguard_spec &&
      !proguard::CollectProguardRules(src, doc, keep_set_)) {
    return false;
  }

  if (options_.no_xml_namespaces) {
    XmlNamespaceRemover namespace_remover;
    if (!namespace_remover.Consume(context_, doc)) {
      return false;
    }
  }

  if (!options_.no_auto_version) {
    if (options_.no_version_vectors) {
      // Skip this if it is a vector or animated-vector.
      xml::Element* el = xml::FindRootElement(doc);
      if (el && el->namespace_uri.empty()) {
        if (el->name == "vector" || el->name == "animated-vector") {
          // We are NOT going to version this file.
          file_op->skip_version = true;
          return true;
        }
      }
    }

    const ConfigDescription& config = file_op->config;

    // Find the first SDK level used that is higher than this defined config and
    // not superseded by a lower or equal SDK level resource.
    const int min_sdk_version = context_->GetMinSdkVersion();
    for (int sdk_level : xml_linker.sdk_levels()) {
      if (sdk_level > min_sdk_version && sdk_level > config.sdkVersion) {
        if (!ShouldGenerateVersionedResource(file_op->entry, config,
                                             sdk_level)) {
          // If we shouldn't generate a versioned resource, stop checking.
          break;
        }

        ResourceFile versioned_file_desc = doc->file;
        versioned_file_desc.config.sdkVersion = (uint16_t)sdk_level;

        FileOperation new_file_op;
        new_file_op.xml_to_flatten = util::make_unique<xml::XmlResource>(
            versioned_file_desc, doc->root->Clone());
        new_file_op.config = versioned_file_desc.config;
        new_file_op.entry = file_op->entry;
        new_file_op.dst_path = ResourceUtils::BuildResourceFileName(
            versioned_file_desc, context_->GetNameMangler());

        if (context_->IsVerbose()) {
          context_->GetDiagnostics()->Note(
              DiagMessage(versioned_file_desc.source)
              << "auto-versioning resource from config '" << config << "' -> '"
              << versioned_file_desc.config << "'");
        }

        bool added = table->AddFileReferenceAllowMangled(
            versioned_file_desc.name, versioned_file_desc.config,
            versioned_file_desc.source, new_file_op.dst_path, nullptr,
            context_->GetDiagnostics());
        if (!added) {
          return false;
        }

        out_file_op_queue->push(std::move(new_file_op));
        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* archive_writer) {
  bool error = false;
  std::map<std::pair<ConfigDescription, StringPiece>, FileOperation>
      config_sorted_files;

  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.
      config_sorted_files.clear();
      std::queue<FileOperation> file_operations;

      // Populate the queue with all files in the ResourceTable.
      for (auto& entry : type->entries) {
        for (auto& config_value : entry->values) {
          FileReference* file_ref =
              ValueCast<FileReference>(config_value->value.get());
          if (!file_ref) {
            continue;
          }

          io::IFile* file = file_ref->file;
          if (!file) {
            context_->GetDiagnostics()->Error(DiagMessage(file_ref->GetSource())
                                              << "file not found");
            return false;
          }

          FileOperation file_op;
          file_op.entry = entry.get();
          file_op.dst_path = *file_ref->path;
          file_op.config = config_value->config;

          const StringPiece src_path = file->GetSource().path;
          if (type->type != ResourceType::kRaw &&
              (util::EndsWith(src_path, ".xml.flat") ||
               util::EndsWith(src_path, ".xml"))) {
            std::unique_ptr<io::IData> data = file->OpenAsData();
            if (!data) {
              context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
                                                << "failed to open file");
              return false;
            }

            file_op.xml_to_flatten =
                xml::Inflate(data->data(), data->size(),
                             context_->GetDiagnostics(), file->GetSource());

            if (!file_op.xml_to_flatten) {
              return false;
            }

            file_op.xml_to_flatten->file.config = config_value->config;
            file_op.xml_to_flatten->file.source = file_ref->GetSource();
            file_op.xml_to_flatten->file.name =
                ResourceName(pkg->name, type->type, entry->name);

            // Enqueue the XML files to be processed.
            file_operations.push(std::move(file_op));
          } else {
            file_op.file_to_copy = file;

            // NOTE(adamlesinski): Explicitly construct a StringPiece here, or
            // else we end up copying the string in the std::make_pair() method,
            // then creating a StringPiece from the copy, which would cause us
            // to end up referencing garbage in the map.
            const StringPiece entry_name(entry->name);
            config_sorted_files[std::make_pair(
                config_value->config, entry_name)] = std::move(file_op);
          }
        }
      }

      // Now process the XML queue
      for (; !file_operations.empty(); file_operations.pop()) {
        FileOperation& file_op = file_operations.front();

        if (!LinkAndVersionXmlFile(table, &file_op, &file_operations)) {
          error = true;
          continue;
        }

        // NOTE(adamlesinski): Explicitly construct a StringPiece here, or else
        // we end up copying the string in the std::make_pair() method, then
        // creating a StringPiece from the copy, which would cause us to end up
        // referencing garbage in the map.
        const StringPiece entry_name(file_op.entry->name);
        config_sorted_files[std::make_pair(file_op.config, entry_name)] =
            std::move(file_op);
      }

      if (error) {
        return false;
      }

      // Now flatten the sorted values.
      for (auto& map_entry : config_sorted_files) {
        const ConfigDescription& config = map_entry.first.first;
        const FileOperation& file_op = map_entry.second;

        if (file_op.xml_to_flatten) {
          Maybe<size_t> max_sdk_level;
          if (!options_.no_auto_version && !file_op.skip_version) {
            max_sdk_level =
                std::max<size_t>(std::max<size_t>(config.sdkVersion, 1u),
                                 context_->GetMinSdkVersion());
          }

          bool result = FlattenXml(
              file_op.xml_to_flatten.get(), file_op.dst_path, max_sdk_level,
              options_.keep_raw_values, archive_writer, context_);
          if (!result) {
            error = true;
          }
        } else {
          bool result = CopyFileToArchive(
              file_op.file_to_copy, file_op.dst_path,
              GetCompressionFlags(file_op.dst_path), archive_writer, context_);
          if (!result) {
            error = true;
          }
        }
      }
    }
  }
  return !error;
}

static bool WriteStableIdMapToPath(
    IDiagnostics* diag,
    const std::unordered_map<ResourceName, ResourceId>& id_map,
    const std::string& id_map_path) {
  std::ofstream fout(id_map_path, std::ofstream::binary);
  if (!fout) {
    diag->Error(DiagMessage(id_map_path) << strerror(errno));
    return false;
  }

  for (const auto& entry : id_map) {
    const ResourceName& name = entry.first;
    const ResourceId& id = entry.second;
    fout << name << " = " << id << "\n";
  }

  if (!fout) {
    diag->Error(DiagMessage(id_map_path)
                << "failed writing to file: "
                << android::base::SystemErrorCodeToString(errno));
    return false;
  }

  return true;
}

static bool LoadStableIdMap(
    IDiagnostics* diag, const std::string& path,
    std::unordered_map<ResourceName, ResourceId>* out_id_map) {
  std::string content;
  if (!android::base::ReadFileToString(path, &content)) {
    diag->Error(DiagMessage(path) << "failed reading stable ID file");
    return false;
  }

  out_id_map->clear();
  size_t line_no = 0;
  for (StringPiece line : util::Tokenize(content, '\n')) {
    line_no++;
    line = util::TrimWhitespace(line);
    if (line.empty()) {
      continue;
    }

    auto iter = std::find(line.begin(), line.end(), '=');
    if (iter == line.end()) {
      diag->Error(DiagMessage(Source(path, line_no)) << "missing '='");
      return false;
    }

    ResourceNameRef name;
    StringPiece res_name_str =
        util::TrimWhitespace(line.substr(0, std::distance(line.begin(), iter)));
    if (!ResourceUtils::ParseResourceName(res_name_str, &name)) {
      diag->Error(DiagMessage(Source(path, line_no))
                  << "invalid resource name '" << res_name_str << "'");
      return false;
    }

    const size_t res_id_start_idx = std::distance(line.begin(), iter) + 1;
    const size_t res_id_str_len = line.size() - res_id_start_idx;
    StringPiece res_id_str =
        util::TrimWhitespace(line.substr(res_id_start_idx, res_id_str_len));

    Maybe<ResourceId> maybe_id = ResourceUtils::ParseResourceId(res_id_str);
    if (!maybe_id) {
      diag->Error(DiagMessage(Source(path, line_no)) << "invalid resource ID '"
                                                     << res_id_str << "'");
      return false;
    }

    (*out_id_map)[name.ToResourceName()] = maybe_id.value();
  }
  return true;
}

static bool ParseSplitParameter(const StringPiece& arg, IDiagnostics* diag,
                                std::string* out_path,
                                SplitConstraints* out_split) {
  std::vector<std::string> parts = util::Split(arg, ':');
  if (parts.size() != 2) {
    diag->Error(DiagMessage() << "invalid split parameter '" << arg << "'");
    diag->Note(
        DiagMessage()
        << "should be --split path/to/output.apk:<config>[,<config>...]");
    return false;
  }
  *out_path = parts[0];
  std::vector<ConfigDescription> configs;
  for (const StringPiece& config_str : util::Tokenize(parts[1], ',')) {
    configs.push_back({});
    if (!ConfigDescription::Parse(config_str, &configs.back())) {
      diag->Error(DiagMessage() << "invalid config '" << config_str
                                << "' in split parameter '" << arg << "'");
      return false;
    }
  }
  out_split->configs.insert(configs.begin(), configs.end());
  return true;
}

class LinkCommand {
 public:
  LinkCommand(LinkContext* context, const LinkOptions& options)
      : options_(options),
        context_(context),
        final_table_(),
        file_collection_(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> asset_source =
        util::make_unique<AssetManagerSymbolSource>();
    for (const std::string& path : options_.include_paths) {
      if (context_->IsVerbose()) {
        context_->GetDiagnostics()->Note(DiagMessage(path)
                                         << "loading include path");
      }

      // First try to load the file as a static lib.
      std::string error_str;
      std::unique_ptr<ResourceTable> static_include =
          LoadStaticLibrary(path, &error_str);
      if (static_include) {
        if (!options_.static_lib) {
          // Can't include static libraries when not building a static library.
          context_->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 (options_.no_static_lib_packages) {
          if (ResourceTablePackage* pkg =
                  static_include->FindPackageById(0x7f)) {
            pkg->name = context_->GetCompilationPackage();
          }
        }

        context_->GetExternalSymbols()->AppendSource(
            util::make_unique<ResourceTableSymbolSource>(static_include.get()));

        static_table_includes_.push_back(std::move(static_include));

      } else if (!error_str.empty()) {
        // We had an error with reading, so fail.
        context_->GetDiagnostics()->Error(DiagMessage(path) << error_str);
        return false;
      }

      if (!asset_source->AddAssetPath(path)) {
        context_->GetDiagnostics()->Error(DiagMessage(path)
                                          << "failed to load include path");
        return false;
      }
    }

    context_->GetExternalSymbols()->AppendSource(std::move(asset_source));
    return true;
  }

  Maybe<AppInfo> ExtractAppInfoFromManifest(xml::XmlResource* xml_res,
                                            IDiagnostics* diag) {
    // Make sure the first element is <manifest> with package attribute.
    if (xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get())) {
      AppInfo app_info;

      if (!manifest_el->namespace_uri.empty() ||
          manifest_el->name != "manifest") {
        diag->Error(DiagMessage(xml_res->file.source)
                    << "root tag must be <manifest>");
        return {};
      }

      xml::Attribute* package_attr = manifest_el->FindAttribute({}, "package");
      if (!package_attr) {
        diag->Error(DiagMessage(xml_res->file.source)
                    << "<manifest> must have a 'package' attribute");
        return {};
      }

      app_info.package = package_attr->value;

      if (xml::Attribute* version_code_attr =
              manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCode")) {
        Maybe<uint32_t> maybe_code =
            ResourceUtils::ParseInt(version_code_attr->value);
        if (!maybe_code) {
          diag->Error(DiagMessage(xml_res->file.source.WithLine(
                          manifest_el->line_number))
                      << "invalid android:versionCode '"
                      << version_code_attr->value << "'");
          return {};
        }
        app_info.version_code = maybe_code.value();
      }

      if (xml::Attribute* revision_code_attr =
              manifest_el->FindAttribute(xml::kSchemaAndroid, "revisionCode")) {
        Maybe<uint32_t> maybe_code =
            ResourceUtils::ParseInt(revision_code_attr->value);
        if (!maybe_code) {
          diag->Error(DiagMessage(xml_res->file.source.WithLine(
                          manifest_el->line_number))
                      << "invalid android:revisionCode '"
                      << revision_code_attr->value << "'");
          return {};
        }
        app_info.revision_code = maybe_code.value();
      }

      if (xml::Element* uses_sdk_el = manifest_el->FindChild({}, "uses-sdk")) {
        if (xml::Attribute* min_sdk = uses_sdk_el->FindAttribute(
                xml::kSchemaAndroid, "minSdkVersion")) {
          app_info.min_sdk_version = min_sdk->value;
        }
      }
      return app_info;
    }
    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 is_ext_package_func =
        [&](const std::unique_ptr<ResourceTablePackage>& pkg) -> bool {
      return context_->GetCompilationPackage() != pkg->name || !pkg->id ||
             pkg->id.value() != context_->GetPackageId();
    };

    bool error = false;
    for (const auto& package : final_table_.packages) {
      if (is_ext_package_func(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 res_name(package->name, type->type, entry->name);

            for (const auto& config_value : 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>(config_value->value.get()) &&
                  package->name == "android") {
                context_->GetDiagnostics()->Warn(
                    DiagMessage(config_value->value->GetSource())
                    << "generated id '" << res_name
                    << "' for external package '" << package->name << "'");
              } else {
                context_->GetDiagnostics()->Error(
                    DiagMessage(config_value->value->GetSource())
                    << "defined resource '" << res_name
                    << "' for external package '" << package->name << "'");
                error = true;
              }
            }
          }
        }
      }
    }

    auto new_end_iter =
        std::remove_if(final_table_.packages.begin(),
                       final_table_.packages.end(), is_ext_package_func);
    final_table_.packages.erase(new_end_iter, final_table_.packages.end());
    return !error;
  }

  /**
   * Returns true if no IDs have been set, false otherwise.
   */
  bool VerifyNoIdsSet() {
    for (const auto& package : final_table_.packages) {
      for (const auto& type : package->types) {
        if (type->id) {
          context_->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 res_name(package->name, type->type, entry->name);
            context_->GetDiagnostics()->Error(
                DiagMessage() << "entry " << res_name << " has ID " << std::hex
                              << (int)entry->id.value() << std::dec
                              << " assigned");
            return false;
          }
        }
      }
    }
    return true;
  }

  std::unique_ptr<IArchiveWriter> MakeArchiveWriter(const StringPiece& out) {
    if (options_.output_to_directory) {
      return CreateDirectoryArchiveWriter(context_->GetDiagnostics(), out);
    } else {
      return CreateZipFileArchiveWriter(context_->GetDiagnostics(), out);
    }
  }

  bool FlattenTable(ResourceTable* table, IArchiveWriter* writer) {
    BigBuffer buffer(1024);
    TableFlattener flattener(&buffer);
    if (!flattener.Consume(context_, table)) {
      return false;
    }

    if (writer->StartEntry("resources.arsc", ArchiveEntry::kAlign)) {
      if (writer->WriteEntry(buffer)) {
        if (writer->FinishEntry()) {
          return true;
        }
      }
    }

    context_->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)) {
      context_->GetDiagnostics()->Error(DiagMessage() << "failed to open");
      return false;
    }

    // Make sure CopyingOutputStreamAdaptor is deleted before we call
    // writer->FinishEntry().
    {
      // Wrap our IArchiveWriter with an adaptor that implements the
      // ZeroCopyOutputStream interface.
      CopyingOutputStreamAdaptor adaptor(writer);

      std::unique_ptr<pb::ResourceTable> pb_table = SerializeTableToPb(table);
      if (!pb_table->SerializeToZeroCopyStream(&adaptor)) {
        context_->GetDiagnostics()->Error(DiagMessage() << "failed to write");
        return false;
      }
    }

    if (!writer->FinishEntry()) {
      context_->GetDiagnostics()->Error(DiagMessage()
                                        << "failed to finish entry");
      return false;
    }
    return true;
  }

  bool WriteJavaFile(ResourceTable* table,
                     const StringPiece& package_name_to_generate,
                     const StringPiece& out_package,
                     const JavaClassGeneratorOptions& java_options) {
    if (!options_.generate_java_class_path) {
      return true;
    }

    std::string out_path = options_.generate_java_class_path.value();
    file::AppendPath(&out_path, file::PackageToPath(out_package));
    if (!file::mkdirs(out_path)) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed to create directory '" << out_path << "'");
      return false;
    }

    file::AppendPath(&out_path, "R.java");

    std::ofstream fout(out_path, std::ofstream::binary);
    if (!fout) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed writing to '" << out_path << "': "
                        << android::base::SystemErrorCodeToString(errno));
      return false;
    }

    JavaClassGenerator generator(context_, table, java_options);
    if (!generator.Generate(package_name_to_generate, out_package, &fout)) {
      context_->GetDiagnostics()->Error(DiagMessage(out_path)
                                        << generator.getError());
      return false;
    }

    if (!fout) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed writing to '" << out_path << "': "
                        << android::base::SystemErrorCodeToString(errno));
    }
    return true;
  }

  bool WriteManifestJavaFile(xml::XmlResource* manifest_xml) {
    if (!options_.generate_java_class_path) {
      return true;
    }

    std::unique_ptr<ClassDefinition> manifest_class =
        GenerateManifestClass(context_->GetDiagnostics(), manifest_xml);

    if (!manifest_class) {
      // Something bad happened, but we already logged it, so exit.
      return false;
    }

    if (manifest_class->empty()) {
      // Empty Manifest class, no need to generate it.
      return true;
    }

    // Add any JavaDoc annotations to the generated class.
    for (const std::string& annotation : options_.javadoc_annotations) {
      std::string proper_annotation = "@";
      proper_annotation += annotation;
      manifest_class->GetCommentBuilder()->AppendComment(proper_annotation);
    }

    const std::string& package_utf8 = context_->GetCompilationPackage();

    std::string out_path = options_.generate_java_class_path.value();
    file::AppendPath(&out_path, file::PackageToPath(package_utf8));

    if (!file::mkdirs(out_path)) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed to create directory '" << out_path << "'");
      return false;
    }

    file::AppendPath(&out_path, "Manifest.java");

    std::ofstream fout(out_path, std::ofstream::binary);
    if (!fout) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed writing to '" << out_path << "': "
                        << android::base::SystemErrorCodeToString(errno));
      return false;
    }

    if (!ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8,
                                        true, &fout)) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed writing to '" << out_path << "': "
                        << android::base::SystemErrorCodeToString(errno));
      return false;
    }
    return true;
  }

  bool WriteProguardFile(const Maybe<std::string>& out,
                         const proguard::KeepSet& keep_set) {
    if (!out) {
      return true;
    }

    const std::string& out_path = out.value();
    std::ofstream fout(out_path, std::ofstream::binary);
    if (!fout) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed to open '" << out_path << "': "
                        << android::base::SystemErrorCodeToString(errno));
      return false;
    }

    proguard::WriteKeepSet(&fout, keep_set);
    if (!fout) {
      context_->GetDiagnostics()->Error(
          DiagMessage() << "failed writing to '" << out_path << "': "
                        << android::base::SystemErrorCodeToString(errno));
      return false;
    }
    return true;
  }

  std::unique_ptr<ResourceTable> LoadStaticLibrary(const std::string& input,
                                                   std::string* out_error) {
    std::unique_ptr<io::ZipFileCollection> collection =
        io::ZipFileCollection::Create(input, out_error);
    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(),
                           context_->GetDiagnostics());
  }

  bool MergeStaticLibrary(const std::string& input, bool override) {
    if (context_->IsVerbose()) {
      context_->GetDiagnostics()->Note(DiagMessage()
                                       << "merging static library " << input);
    }

    std::string error_str;
    std::unique_ptr<io::ZipFileCollection> collection =
        io::ZipFileCollection::Create(input, &error_str);
    if (!collection) {
      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
      return false;
    }

    std::unique_ptr<ResourceTable> table =
        LoadTablePbFromCollection(collection.get());
    if (!table) {
      context_->GetDiagnostics()->Error(DiagMessage(input)
                                        << "invalid static library");
      return false;
    }

    ResourceTablePackage* pkg = table->FindPackageById(0x7f);
    if (!pkg) {
      context_->GetDiagnostics()->Error(DiagMessage(input)
                                        << "static library has no package");
      return false;
    }

    bool result;
    if (options_.no_static_lib_packages) {
      // Merge all resources as if they were in the compilation package. This is
      // the old behavior 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()) {
        options_.extra_java_packages.insert(pkg->name);
      }

      pkg->name = "";
      if (override) {
        result = table_merger_->MergeOverlay(Source(input), table.get(),
                                             collection.get());
      } else {
        result =
            table_merger_->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 = table_merger_->MergeAndMangle(Source(input), pkg->name,
                                             table.get(), collection.get());
    }

    if (!result) {
      return false;
    }

    // Make sure to move the collection into the set of IFileCollections.
    collections_.push_back(std::move(collection));
    return true;
  }

  bool MergeResourceTable(io::IFile* file, bool override) {
    if (context_->IsVerbose()) {
      context_->GetDiagnostics()->Note(
          DiagMessage() << "merging resource table " << file->GetSource());
    }

    std::unique_ptr<io::IData> data = file->OpenAsData();
    if (!data) {
      context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
                                        << "failed to open file");
      return false;
    }

    std::unique_ptr<ResourceTable> table =
        LoadTableFromPb(file->GetSource(), data->data(), data->size(),
                        context_->GetDiagnostics());
    if (!table) {
      return false;
    }

    bool result = false;
    if (override) {
      result = table_merger_->MergeOverlay(file->GetSource(), table.get());
    } else {
      result = table_merger_->Merge(file->GetSource(), table.get());
    }
    return result;
  }

  bool MergeCompiledFile(io::IFile* file, ResourceFile* file_desc,
                         bool override) {
    if (context_->IsVerbose()) {
      context_->GetDiagnostics()->Note(
          DiagMessage() << "merging '" << file_desc->name
                        << "' from compiled file " << file->GetSource());
    }

    bool result = false;
    if (override) {
      result = table_merger_->MergeFileOverlay(*file_desc, file);
    } else {
      result = table_merger_->MergeFile(*file_desc, file);
    }

    if (!result) {
      return false;
    }

    // Add the exports of this file to the table.
    for (SourcedResourceName& exported_symbol : file_desc->exported_symbols) {
      if (exported_symbol.name.package.empty()) {
        exported_symbol.name.package = context_->GetCompilationPackage();
      }

      ResourceNameRef res_name = exported_symbol.name;

      Maybe<ResourceName> mangled_name =
          context_->GetNameMangler()->MangleName(exported_symbol.name);
      if (mangled_name) {
        res_name = mangled_name.value();
      }

      std::unique_ptr<Id> id = util::make_unique<Id>();
      id->SetSource(file_desc->source.WithLine(exported_symbol.line));
      bool result = final_table_.AddResourceAllowMangled(
          res_name, ConfigDescription::DefaultConfig(), std::string(),
          std::move(id), context_->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 (context_->IsVerbose()) {
      context_->GetDiagnostics()->Note(DiagMessage() << "merging archive "
                                                     << input);
    }

    std::string error_str;
    std::unique_ptr<io::ZipFileCollection> collection =
        io::ZipFileCollection::Create(input, &error_str);
    if (!collection) {
      context_->GetDiagnostics()->Error(DiagMessage(input) << error_str);
      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.
    collections_.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::EndsWith(path, ".flata") || util::EndsWith(path, ".jar") ||
        util::EndsWith(path, ".jack") || util::EndsWith(path, ".zip")) {
      return MergeArchive(path, override);
    } else if (util::EndsWith(path, ".apk")) {
      return MergeStaticLibrary(path, override);
    }

    io::IFile* file = file_collection_->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::EndsWith(src.path, ".arsc.flat")) {
      return MergeResourceTable(file, override);

    } else if (util::EndsWith(src.path, ".flat")) {
      // Try opening the file and looking for an Export header.
      std::unique_ptr<io::IData> data = file->OpenAsData();
      if (!data) {
        context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to open");
        return false;
      }

      CompiledFileInputStream input_stream(data->data(), data->size());
      uint32_t num_files = 0;
      if (!input_stream.ReadLittleEndian32(&num_files)) {
        context_->GetDiagnostics()->Error(DiagMessage(src)
                                          << "failed read num files");
        return false;
      }

      for (uint32_t i = 0; i < num_files; i++) {
        pb::CompiledFile compiled_file;
        if (!input_stream.ReadCompiledFile(&compiled_file)) {
          context_->GetDiagnostics()->Error(
              DiagMessage(src) << "failed to read compiled file header");
          return false;
        }

        uint64_t offset, len;
        if (!input_stream.ReadDataMetaData(&offset, &len)) {
          context_->GetDiagnostics()->Error(DiagMessage(src)
                                            << "failed to read data meta data");
          return false;
        }

        std::unique_ptr<ResourceFile> resource_file =
            DeserializeCompiledFileFromPb(compiled_file, file->GetSource(),
                                          context_->GetDiagnostics());
        if (!resource_file) {
          return false;
        }

        if (!MergeCompiledFile(file->CreateFileSegment(offset, len),
                               resource_file.get(), override)) {
          return false;
        }
      }
      return true;
    } else if (util::EndsWith(src.path, ".xml") ||
               util::EndsWith(src.path, ".png")) {
      // Since AAPT compiles these file types and appends .flat to them, seeing
      // their raw extensions is a sign that they weren't compiled.
      const StringPiece file_type =
          util::EndsWith(src.path, ".xml") ? "XML" : "PNG";
      context_->GetDiagnostics()->Error(DiagMessage(src)
                                        << "uncompiled " << file_type
                                        << " file passed as argument. Must be "
                                           "compiled first into .flat file.");
      return false;
    }

    // Ignore non .flat files. This could be classes.dex or something else that
    // happens
    // to be in an archive.
    return true;
  }

  std::unique_ptr<xml::XmlResource> GenerateSplitManifest(
      const AppInfo& app_info, const SplitConstraints& constraints) {
    std::unique_ptr<xml::XmlResource> doc =
        util::make_unique<xml::XmlResource>();

    std::unique_ptr<xml::Namespace> namespace_android =
        util::make_unique<xml::Namespace>();
    namespace_android->namespace_uri = xml::kSchemaAndroid;
    namespace_android->namespace_prefix = "android";

    std::unique_ptr<xml::Element> manifest_el =
        util::make_unique<xml::Element>();
    manifest_el->name = "manifest";
    manifest_el->attributes.push_back(
        xml::Attribute{"", "package", app_info.package});

    if (app_info.version_code) {
      manifest_el->attributes.push_back(
          xml::Attribute{xml::kSchemaAndroid, "versionCode",
                         std::to_string(app_info.version_code.value())});
    }

    if (app_info.revision_code) {
      manifest_el->attributes.push_back(
          xml::Attribute{xml::kSchemaAndroid, "revisionCode",
                         std::to_string(app_info.revision_code.value())});
    }

    std::stringstream split_name;
    split_name << "config." << util::Joiner(constraints.configs, "_");

    manifest_el->attributes.push_back(
        xml::Attribute{"", "split", split_name.str()});

    std::unique_ptr<xml::Element> application_el =
        util::make_unique<xml::Element>();
    application_el->name = "application";
    application_el->attributes.push_back(
        xml::Attribute{xml::kSchemaAndroid, "hasCode", "false"});

    manifest_el->AppendChild(std::move(application_el));
    namespace_android->AppendChild(std::move(manifest_el));
    doc->root = std::move(namespace_android);
    return doc;
  }

  /**
   * Writes the AndroidManifest, ResourceTable, and all XML files referenced by
   * the ResourceTable to the IArchiveWriter.
   */
  bool WriteApk(IArchiveWriter* writer, proguard::KeepSet* keep_set,
                xml::XmlResource* manifest, ResourceTable* table) {
    const bool keep_raw_values = options_.static_lib;
    bool result = FlattenXml(manifest, "AndroidManifest.xml", {},
                             keep_raw_values, writer, context_);
    if (!result) {
      return false;
    }

    ResourceFileFlattenerOptions file_flattener_options;
    file_flattener_options.keep_raw_values = keep_raw_values;
    file_flattener_options.do_not_compress_anything =
        options_.do_not_compress_anything;
    file_flattener_options.extensions_to_not_compress =
        options_.extensions_to_not_compress;
    file_flattener_options.no_auto_version = options_.no_auto_version;
    file_flattener_options.no_version_vectors = options_.no_version_vectors;
    file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces;
    file_flattener_options.update_proguard_spec =
        static_cast<bool>(options_.generate_proguard_rules_path);

    ResourceFileFlattener file_flattener(file_flattener_options, context_,
                                         keep_set);

    if (!file_flattener.Flatten(table, writer)) {
      context_->GetDiagnostics()->Error(DiagMessage()
                                        << "failed linking file resources");
      return false;
    }

    if (options_.static_lib) {
      if (!FlattenTableToPb(table, writer)) {
        context_->GetDiagnostics()->Error(
            DiagMessage() << "failed to write resources.arsc.flat");
        return false;
      }
    } else {
      if (!FlattenTable(table, writer)) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed to write resources.arsc");
        return false;
      }
    }
    return true;
  }

  int Run(const std::vector<std::string>& input_files) {
    // Load the AndroidManifest.xml
    std::unique_ptr<xml::XmlResource> manifest_xml =
        LoadXml(options_.manifest_path, context_->GetDiagnostics());
    if (!manifest_xml) {
      return 1;
    }

    // First extract the Package name without modifying it (via
    // --rename-manifest-package).
    if (Maybe<AppInfo> maybe_app_info = ExtractAppInfoFromManifest(
            manifest_xml.get(), context_->GetDiagnostics())) {
      const AppInfo& app_info = maybe_app_info.value();
      context_->SetCompilationPackage(app_info.package);
    }

    ManifestFixer manifest_fixer(options_.manifest_fixer_options);
    if (!manifest_fixer.Consume(context_, manifest_xml.get())) {
      return 1;
    }

    Maybe<AppInfo> maybe_app_info = ExtractAppInfoFromManifest(
        manifest_xml.get(), context_->GetDiagnostics());
    if (!maybe_app_info) {
      return 1;
    }

    const AppInfo& app_info = maybe_app_info.value();
    if (app_info.min_sdk_version) {
      if (Maybe<int> maybe_min_sdk_version = ResourceUtils::ParseSdkVersion(
              app_info.min_sdk_version.value())) {
        context_->SetMinSdkVersion(maybe_min_sdk_version.value());
      }
    }

    context_->SetNameManglerPolicy(
        NameManglerPolicy{context_->GetCompilationPackage()});
    if (context_->GetCompilationPackage() == "android") {
      context_->SetPackageId(0x01);
    } else {
      context_->SetPackageId(0x7f);
    }

    if (!LoadSymbolsFromIncludePaths()) {
      return 1;
    }

    TableMergerOptions table_merger_options;
    table_merger_options.auto_add_overlay = options_.auto_add_overlay;
    table_merger_ = util::make_unique<TableMerger>(context_, &final_table_,
                                                   table_merger_options);

    if (context_->IsVerbose()) {
      context_->GetDiagnostics()->Note(DiagMessage()
                                       << "linking package '"
                                       << context_->GetCompilationPackage()
                                       << "' with package ID " << std::hex
                                       << (int)context_->GetPackageId());
    }

    for (const std::string& input : input_files) {
      if (!MergePath(input, false)) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed parsing input");
        return 1;
      }
    }

    for (const std::string& input : options_.overlay_files) {
      if (!MergePath(input, true)) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed parsing overlays");
        return 1;
      }
    }

    if (!VerifyNoExternalPackages()) {
      return 1;
    }

    if (!options_.static_lib) {
      PrivateAttributeMover mover;
      if (!mover.Consume(context_, &final_table_)) {
        context_->GetDiagnostics()->Error(
            DiagMessage() << "failed moving private attributes");
        return 1;
      }

      // Assign IDs if we are building a regular app.
      IdAssigner id_assigner(&options_.stable_id_map);
      if (!id_assigner.Consume(context_, &final_table_)) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed assigning IDs");
        return 1;
      }

      // Now grab each ID and emit it as a file.
      if (options_.resource_id_map_path) {
        for (auto& package : final_table_.packages) {
          for (auto& type : package->types) {
            for (auto& entry : type->entries) {
              ResourceName name(package->name, type->type, entry->name);
              // The IDs are guaranteed to exist.
              options_.stable_id_map[std::move(name)] = ResourceId(
                  package->id.value(), type->id.value(), entry->id.value());
            }
          }
        }

        if (!WriteStableIdMapToPath(context_->GetDiagnostics(),
                                    options_.stable_id_map,
                                    options_.resource_id_map_path.value())) {
          return 1;
        }
      }
    } else {
      // Static libs are merged with other apps, and ID collisions are bad, so
      // verify that
      // no IDs have been set.
      if (!VerifyNoIdsSet()) {
        return 1;
      }
    }

    // Add the names to mangle based on our source merge earlier.
    context_->SetNameManglerPolicy(NameManglerPolicy{
        context_->GetCompilationPackage(), table_merger_->merged_packages()});

    // Add our table to the symbol table.
    context_->GetExternalSymbols()->PrependSource(
        util::make_unique<ResourceTableSymbolSource>(&final_table_));

    ReferenceLinker linker;
    if (!linker.Consume(context_, &final_table_)) {
      context_->GetDiagnostics()->Error(DiagMessage()
                                        << "failed linking references");
      return 1;
    }

    if (options_.static_lib) {
      if (!options_.products.empty()) {
        context_->GetDiagnostics()
            ->Warn(DiagMessage()
                   << "can't select products when building static library");
      }
    } else {
      ProductFilter product_filter(options_.products);
      if (!product_filter.Consume(context_, &final_table_)) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed stripping products");
        return 1;
      }
    }

    if (!options_.no_auto_version) {
      AutoVersioner versioner;
      if (!versioner.Consume(context_, &final_table_)) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed versioning styles");
        return 1;
      }
    }

    if (!options_.static_lib && context_->GetMinSdkVersion() > 0) {
      if (context_->IsVerbose()) {
        context_->GetDiagnostics()->Note(
            DiagMessage() << "collapsing resource versions for minimum SDK "
                          << context_->GetMinSdkVersion());
      }

      VersionCollapser collapser;
      if (!collapser.Consume(context_, &final_table_)) {
        return 1;
      }
    }

    if (!options_.no_resource_deduping) {
      ResourceDeduper deduper;
      if (!deduper.Consume(context_, &final_table_)) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed deduping resources");
        return 1;
      }
    }

    proguard::KeepSet proguard_keep_set;
    proguard::KeepSet proguard_main_dex_keep_set;

    if (options_.static_lib) {
      if (options_.table_splitter_options.config_filter != nullptr ||
          options_.table_splitter_options.preferred_density) {
        context_->GetDiagnostics()
            ->Warn(DiagMessage()
                   << "can't strip resources when building static library");
      }
    } else {
      // Adjust the SplitConstraints so that their SDK version is stripped if it
      // is less
      // than or equal to the minSdk. Otherwise the resources that have had
      // their SDK version
      // stripped due to minSdk won't ever match.
      std::vector<SplitConstraints> adjusted_constraints_list;
      adjusted_constraints_list.reserve(options_.split_constraints.size());
      for (const SplitConstraints& constraints : options_.split_constraints) {
        SplitConstraints adjusted_constraints;
        for (const ConfigDescription& config : constraints.configs) {
          if (config.sdkVersion <= context_->GetMinSdkVersion()) {
            adjusted_constraints.configs.insert(config.CopyWithoutSdkVersion());
          } else {
            adjusted_constraints.configs.insert(config);
          }
        }
        adjusted_constraints_list.push_back(std::move(adjusted_constraints));
      }

      TableSplitter table_splitter(adjusted_constraints_list,
                                   options_.table_splitter_options);
      if (!table_splitter.VerifySplitConstraints(context_)) {
        return 1;
      }
      table_splitter.SplitTable(&final_table_);

      // Now we need to write out the Split APKs.
      auto path_iter = options_.split_paths.begin();
      auto split_constraints_iter = adjusted_constraints_list.begin();
      for (std::unique_ptr<ResourceTable>& split_table :
           table_splitter.splits()) {
        if (context_->IsVerbose()) {
          context_->GetDiagnostics()->Note(
              DiagMessage(*path_iter)
              << "generating split with configurations '"
              << util::Joiner(split_constraints_iter->configs, ", ") << "'");
        }

        std::unique_ptr<IArchiveWriter> archive_writer =
            MakeArchiveWriter(*path_iter);
        if (!archive_writer) {
          context_->GetDiagnostics()->Error(DiagMessage()
                                            << "failed to create archive");
          return 1;
        }

        // Generate an AndroidManifest.xml for each split.
        std::unique_ptr<xml::XmlResource> split_manifest =
            GenerateSplitManifest(app_info, *split_constraints_iter);

        XmlReferenceLinker linker;
        if (!linker.Consume(context_, split_manifest.get())) {
          context_->GetDiagnostics()->Error(
              DiagMessage() << "failed to create Split AndroidManifest.xml");
          return 1;
        }

        if (!WriteApk(archive_writer.get(), &proguard_keep_set,
                      split_manifest.get(), split_table.get())) {
          return 1;
        }

        ++path_iter;
        ++split_constraints_iter;
      }
    }

    // Start writing the base APK.
    std::unique_ptr<IArchiveWriter> archive_writer =
        MakeArchiveWriter(options_.output_path);
    if (!archive_writer) {
      context_->GetDiagnostics()->Error(DiagMessage()
                                        << "failed to create archive");
      return 1;
    }

    bool error = false;
    {
      // AndroidManifest.xml has no resource name, but the CallSite is built
      // from the name
      // (aka, which package the AndroidManifest.xml is coming from).
      // So we give it a package name so it can see local resources.
      manifest_xml->file.name.package = context_->GetCompilationPackage();

      XmlReferenceLinker manifest_linker;
      if (manifest_linker.Consume(context_, manifest_xml.get())) {
        if (options_.generate_proguard_rules_path &&
            !proguard::CollectProguardRulesForManifest(
                Source(options_.manifest_path), manifest_xml.get(),
                &proguard_keep_set)) {
          error = true;
        }

        if (options_.generate_main_dex_proguard_rules_path &&
            !proguard::CollectProguardRulesForManifest(
                Source(options_.manifest_path), manifest_xml.get(),
                &proguard_main_dex_keep_set, true)) {
          error = true;
        }

        if (options_.generate_java_class_path) {
          if (!WriteManifestJavaFile(manifest_xml.get())) {
            error = true;
          }
        }

        if (options_.no_xml_namespaces) {
          // PackageParser will fail if URIs are removed from
          // AndroidManifest.xml.
          XmlNamespaceRemover namespace_remover(true /* keepUris */);
          if (!namespace_remover.Consume(context_, manifest_xml.get())) {
            error = true;
          }
        }
      } else {
        error = true;
      }
    }

    if (error) {
      context_->GetDiagnostics()->Error(DiagMessage()
                                        << "failed processing manifest");
      return 1;
    }

    if (!WriteApk(archive_writer.get(), &proguard_keep_set, manifest_xml.get(),
                  &final_table_)) {
      return 1;
    }

    if (options_.generate_java_class_path) {
      JavaClassGeneratorOptions options;
      options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
      options.javadoc_annotations = options_.javadoc_annotations;

      if (options_.static_lib || options_.generate_non_final_ids) {
        options.use_final = false;
      }

      const StringPiece actual_package = context_->GetCompilationPackage();
      StringPiece output_package = context_->GetCompilationPackage();
      if (options_.custom_java_package) {
        // Override the output java package to the custom one.
        output_package = options_.custom_java_package.value();
      }

      if (options_.private_symbols) {
        // 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(&final_table_, context_->GetCompilationPackage(),
                           output_package, options)) {
          return 1;
        }

        options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
        output_package = options_.private_symbols.value();
      }

      if (!WriteJavaFile(&final_table_, actual_package, output_package,
                         options)) {
        return 1;
      }

      for (const std::string& extra_package : options_.extra_java_packages) {
        if (!WriteJavaFile(&final_table_, actual_package, extra_package,
                           options)) {
          return 1;
        }
      }
    }

    if (!WriteProguardFile(options_.generate_proguard_rules_path,
                           proguard_keep_set)) {
      return 1;
    }

    if (!WriteProguardFile(options_.generate_main_dex_proguard_rules_path,
                           proguard_main_dex_keep_set)) {
      return 1;
    }

    if (context_->IsVerbose()) {
      DebugPrintTableOptions debug_print_table_options;
      debug_print_table_options.show_sources = true;
      Debug::PrintTable(&final_table_, debug_print_table_options);
    }
    return 0;
  }

 private:
  LinkOptions options_;
  LinkContext* context_;
  ResourceTable final_table_;

  std::unique_ptr<TableMerger> table_merger_;

  // A pointer to the FileCollection representing the filesystem (not archives).
  std::unique_ptr<io::FileCollection> file_collection_;

  // A vector of IFileCollections. This is mainly here to keep ownership of the
  // collections.
  std::vector<std::unique_ptr<io::IFileCollection>> collections_;

  // A vector of ResourceTables. This is here to retain ownership, so that the
  // SymbolTable
  // can use these.
  std::vector<std::unique_ptr<ResourceTable>> static_table_includes_;
};

int Link(const std::vector<StringPiece>& args) {
  LinkContext context;
  LinkOptions options;
  std::vector<std::string> overlay_arg_list;
  std::vector<std::string> extra_java_packages;
  Maybe<std::string> configs;
  Maybe<std::string> preferred_density;
  Maybe<std::string> product_list;
  bool legacy_x_flag = false;
  bool require_localization = false;
  bool verbose = false;
  Maybe<std::string> stable_id_file_path;
  std::vector<std::string> split_args;
  Flags flags =
      Flags()
          .RequiredFlag("-o", "Output path", &options.output_path)
          .RequiredFlag("--manifest", "Path to the Android manifest to build",
                        &options.manifest_path)
          .OptionalFlagList("-I", "Adds an Android APK to link against",
                            &options.include_paths)
          .OptionalFlagList(
              "-R",
              "Compilation unit to link, using `overlay` semantics.\n"
              "The last conflicting resource given takes precedence.",
              &overlay_arg_list)
          .OptionalFlag("--java", "Directory in which to generate R.java",
                        &options.generate_java_class_path)
          .OptionalFlag("--proguard",
                        "Output file for generated Proguard rules",
                        &options.generate_proguard_rules_path)
          .OptionalFlag(
              "--proguard-main-dex",
              "Output file for generated Proguard rules for the main dex",
              &options.generate_main_dex_proguard_rules_path)
          .OptionalSwitch("--no-auto-version",
                          "Disables automatic style and layout SDK versioning",
                          &options.no_auto_version)
          .OptionalSwitch("--no-version-vectors",
                          "Disables automatic versioning of vector drawables. "
                          "Use this only\n"
                          "when building with vector drawable support library",
                          &options.no_version_vectors)
          .OptionalSwitch("--no-resource-deduping",
                          "Disables automatic deduping of resources with\n"
                          "identical values across compatible configurations.",
                          &options.no_resource_deduping)
          .OptionalSwitch(
              "-x",
              "Legacy flag that specifies to use the package identifier 0x01",
              &legacy_x_flag)
          .OptionalSwitch("-z",
                          "Require localization of strings marked 'suggested'",
                          &require_localization)
          .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.",
              &preferred_density)
          .OptionalFlag("--product",
                        "Comma separated list of product names to keep",
                        &product_list)
          .OptionalSwitch("--output-to-dir",
                          "Outputs the APK contents to a directory specified "
                          "by -o",
                          &options.output_to_directory)
          .OptionalSwitch("--no-xml-namespaces",
                          "Removes XML namespace prefix and URI "
                          "information from AndroidManifest.xml\nand XML "
                          "binaries in res/*.",
                          &options.no_xml_namespaces)
          .OptionalFlag("--min-sdk-version",
                        "Default minimum SDK version to use for "
                        "AndroidManifest.xml",
                        &options.manifest_fixer_options.min_sdk_version_default)
          .OptionalFlag(
              "--target-sdk-version",
              "Default target SDK version to use for "
              "AndroidManifest.xml",
              &options.manifest_fixer_options.target_sdk_version_default)
          .OptionalFlag("--version-code",
                        "Version code (integer) to inject into the "
                        "AndroidManifest.xml if none is present",
                        &options.manifest_fixer_options.version_code_default)
          .OptionalFlag("--version-name",
                        "Version name to inject into the AndroidManifest.xml "
                        "if none is present",
                        &options.manifest_fixer_options.version_name_default)
          .OptionalSwitch("--static-lib", "Generate a static Android library",
                          &options.static_lib)
          .OptionalSwitch("--no-static-lib-packages",
                          "Merge all library resources under the app's package",
                          &options.no_static_lib_packages)
          .OptionalSwitch("--non-final-ids",
                          "Generates R.java without the final modifier.\n"
                          "This is implied when --static-lib is specified.",
                          &options.generate_non_final_ids)
          .OptionalFlag("--stable-ids",
                        "File containing a list of name to ID mapping.",
                        &stable_id_file_path)
          .OptionalFlag(
              "--emit-ids",
              "Emit a file at the given path with a list of name to ID\n"
              "mappings, suitable for use with --stable-ids.",
              &options.resource_id_map_path)
          .OptionalFlag("--private-symbols",
                        "Package name to use when generating R.java for "
                        "private symbols.\n"
                        "If not specified, public and private symbols will use "
                        "the application's "
                        "package name",
                        &options.private_symbols)
          .OptionalFlag("--custom-package",
                        "Custom Java package under which to generate R.java",
                        &options.custom_java_package)
          .OptionalFlagList("--extra-packages",
                            "Generate the same R.java but with different "
                            "package names",
                            &extra_java_packages)
          .OptionalFlagList("--add-javadoc-annotation",
                            "Adds a JavaDoc annotation to all "
                            "generated Java classes",
                            &options.javadoc_annotations)
          .OptionalSwitch("--auto-add-overlay",
                          "Allows the addition of new resources in "
                          "overlays without <add-resource> tags",
                          &options.auto_add_overlay)
          .OptionalFlag("--rename-manifest-package",
                        "Renames the package in AndroidManifest.xml",
                        &options.manifest_fixer_options.rename_manifest_package)
          .OptionalFlag(
              "--rename-instrumentation-target-package",
              "Changes the name of the target package for instrumentation. "
              "Most useful "
              "when used\nin conjunction with --rename-manifest-package",
              &options.manifest_fixer_options
                   .rename_instrumentation_target_package)
          .OptionalFlagList("-0", "File extensions not to compress",
                            &options.extensions_to_not_compress)
          .OptionalFlagList(
              "--split",
              "Split resources matching a set of configs out to a "
              "Split APK.\nSyntax: path/to/output.apk:<config>[,<config>[...]]",
              &split_args)
          .OptionalSwitch("-v", "Enables verbose logging", &verbose);

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

  // Expand all argument-files passed into the command line. These start with
  // '@'.
  std::vector<std::string> arg_list;
  for (const std::string& arg : flags.GetArgs()) {
    if (util::StartsWith(arg, "@")) {
      const std::string path = arg.substr(1, arg.size() - 1);
      std::string error;
      if (!file::AppendArgsFromFile(path, &arg_list, &error)) {
        context.GetDiagnostics()->Error(DiagMessage(path) << error);
        return 1;
      }
    } else {
      arg_list.push_back(arg);
    }
  }

  // Expand all argument-files passed to -R.
  for (const std::string& arg : overlay_arg_list) {
    if (util::StartsWith(arg, "@")) {
      const std::string path = arg.substr(1, arg.size() - 1);
      std::string error;
      if (!file::AppendArgsFromFile(path, &options.overlay_files, &error)) {
        context.GetDiagnostics()->Error(DiagMessage(path) << error);
        return 1;
      }
    } else {
      options.overlay_files.push_back(arg);
    }
  }

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

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

  if (product_list) {
    for (StringPiece product : util::Tokenize(product_list.value(), ',')) {
      if (product != "" && product != "default") {
        options.products.insert(product.to_string());
      }
    }
  }

  AxisConfigFilter filter;
  if (configs) {
    for (const StringPiece& config_str : util::Tokenize(configs.value(), ',')) {
      ConfigDescription config;
      LocaleValue lv;
      if (lv.InitFromFilterString(config_str)) {
        lv.WriteTo(&config);
      } else if (!ConfigDescription::Parse(config_str, &config)) {
        context.GetDiagnostics()->Error(DiagMessage() << "invalid config '"
                                                      << config_str
                                                      << "' for -c option");
        return 1;
      }

      if (config.density != 0) {
        context.GetDiagnostics()->Warn(DiagMessage() << "ignoring density '"
                                                     << config
                                                     << "' for -c option");
      } else {
        filter.AddConfig(config);
      }
    }

    options.table_splitter_options.config_filter = &filter;
  }

  if (preferred_density) {
    ConfigDescription preferred_density_config;
    if (!ConfigDescription::Parse(preferred_density.value(),
                                  &preferred_density_config)) {
      context.GetDiagnostics()->Error(
          DiagMessage() << "invalid density '" << preferred_density.value()
                        << "' for --preferred-density option");
      return 1;
    }

    // Clear the version that can be automatically added.
    preferred_density_config.sdkVersion = 0;

    if (preferred_density_config.diff(ConfigDescription::DefaultConfig()) !=
        ConfigDescription::CONFIG_DENSITY) {
      context.GetDiagnostics()->Error(
          DiagMessage() << "invalid preferred density '"
                        << preferred_density.value() << "'. "
                        << "Preferred density must only be a density value");
      return 1;
    }
    options.table_splitter_options.preferred_density =
        preferred_density_config.density;
  }

  if (!options.static_lib && stable_id_file_path) {
    if (!LoadStableIdMap(context.GetDiagnostics(), stable_id_file_path.value(),
                         &options.stable_id_map)) {
      return 1;
    }
  }

  // Populate some default no-compress extensions that are already compressed.
  options.extensions_to_not_compress.insert(
      {".jpg",   ".jpeg", ".png",  ".gif", ".wav",  ".mp2",  ".mp3",  ".ogg",
       ".aac",   ".mpg",  ".mpeg", ".mid", ".midi", ".smf",  ".jet",  ".rtttl",
       ".imy",   ".xmf",  ".mp4",  ".m4a", ".m4v",  ".3gp",  ".3gpp", ".3g2",
       ".3gpp2", ".amr",  ".awb",  ".wma", ".wmv",  ".webm", ".mkv"});

  // Parse the split parameters.
  for (const std::string& split_arg : split_args) {
    options.split_paths.push_back({});
    options.split_constraints.push_back({});
    if (!ParseSplitParameter(split_arg, context.GetDiagnostics(),
                             &options.split_paths.back(),
                             &options.split_constraints.back())) {
      return 1;
    }
  }

  // Turn off auto versioning for static-libs.
  if (options.static_lib) {
    options.no_auto_version = true;
    options.no_version_vectors = true;
  }

  LinkCommand cmd(&context, options);
  return cmd.Run(arg_list);
}

}  // namespace aapt
