/*
 * 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 "Link.h"

#include <sys/stat.h>
#include <cinttypes>

#include <algorithm>
#include <queue>
#include <unordered_map>
#include <vector>

#include "android-base/errors.h"
#include "android-base/file.h"
#include "android-base/stringprintf.h"
#include "androidfw/StringPiece.h"

#include "AppInfo.h"
#include "Debug.h"
#include "LoadedApk.h"
#include "Locale.h"
#include "NameMangler.h"
#include "ResourceUtils.h"
#include "ResourceValues.h"
#include "ValueVisitor.h"
#include "cmd/Util.h"
#include "compile/IdAssigner.h"
#include "compile/XmlIdCollector.h"
#include "filter/ConfigFilter.h"
#include "format/Archive.h"
#include "format/Container.h"
#include "format/binary/TableFlattener.h"
#include "format/binary/XmlFlattener.h"
#include "format/proto/ProtoDeserialize.h"
#include "format/proto/ProtoSerialize.h"
#include "io/BigBufferStream.h"
#include "io/FileStream.h"
#include "io/FileSystem.h"
#include "io/Util.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/NoDefaultResourceRemover.h"
#include "link/ReferenceLinker.h"
#include "link/TableMerger.h"
#include "link/XmlCompatVersioner.h"
#include "optimize/ResourceDeduper.h"
#include "optimize/VersionCollapser.h"
#include "process/IResourceTableConsumer.h"
#include "process/SymbolTable.h"
#include "split/TableSplitter.h"
#include "util/Files.h"
#include "xml/XmlDom.h"

using ::aapt::io::FileInputStream;
using ::android::StringPiece;
using ::android::base::StringPrintf;

namespace aapt {

class LinkContext : public IAaptContext {
 public:
  LinkContext(IDiagnostics* diagnostics)
      : diagnostics_(diagnostics), name_mangler_({}), symbols_(&name_mangler_) {
  }

  PackageType GetPackageType() override {
    return package_type_;
  }

  void SetPackageType(PackageType type) {
    package_type_ = type;
  }

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

  PackageType package_type_ = PackageType::kApp;
  IDiagnostics* diagnostics_;
  NameMangler name_mangler_;
  std::string compilation_package_;
  uint8_t package_id_ = 0x0;
  SymbolTable symbols_;
  bool verbose_ = false;
  int min_sdk_version_ = 0;
};

// A custom delegate that generates compatible pre-O IDs for use with feature splits.
// Feature splits use package IDs > 7f, which in Java (since Java doesn't have unsigned ints)
// is interpreted as a negative number. Some verification was wrongly assuming negative values
// were invalid.
//
// This delegate will attempt to masquerade any '@id/' references with ID 0xPPTTEEEE,
// where PP > 7f, as 0x7fPPEEEE. Any potential overlapping is verified and an error occurs if such
// an overlap exists.
//
// See b/37498913.
class FeatureSplitSymbolTableDelegate : public DefaultSymbolTableDelegate {
 public:
  FeatureSplitSymbolTableDelegate(IAaptContext* context) : context_(context) {
  }

  virtual ~FeatureSplitSymbolTableDelegate() = default;

  virtual std::unique_ptr<SymbolTable::Symbol> FindByName(
      const ResourceName& name,
      const std::vector<std::unique_ptr<ISymbolSource>>& sources) override {
    std::unique_ptr<SymbolTable::Symbol> symbol =
        DefaultSymbolTableDelegate::FindByName(name, sources);
    if (symbol == nullptr) {
      return {};
    }

    // Check to see if this is an 'id' with the target package.
    if (name.type == ResourceType::kId && symbol->id) {
      ResourceId* id = &symbol->id.value();
      if (id->package_id() > kAppPackageId) {
        // Rewrite the resource ID to be compatible pre-O.
        ResourceId rewritten_id(kAppPackageId, id->package_id(), id->entry_id());

        // Check that this doesn't overlap another resource.
        if (DefaultSymbolTableDelegate::FindById(rewritten_id, sources) != nullptr) {
          // The ID overlaps, so log a message (since this is a weird failure) and fail.
          context_->GetDiagnostics()->Error(DiagMessage() << "Failed to rewrite " << name
                                                          << " for pre-O feature split support");
          return {};
        }

        if (context_->IsVerbose()) {
          context_->GetDiagnostics()->Note(DiagMessage() << "rewriting " << name << " (" << *id
                                                         << ") -> (" << rewritten_id << ")");
        }

        *id = rewritten_id;
      }
    }
    return symbol;
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(FeatureSplitSymbolTableDelegate);

  IAaptContext* context_;
};

static bool FlattenXml(IAaptContext* context, const xml::XmlResource& xml_res,
                       const StringPiece& path, bool keep_raw_values, bool utf16,
                       OutputFormat format, IArchiveWriter* writer) {
  if (context->IsVerbose()) {
    context->GetDiagnostics()->Note(DiagMessage(path) << "writing to archive (keep_raw_values="
                                                      << (keep_raw_values ? "true" : "false")
                                                      << ")");
  }

  switch (format) {
    case OutputFormat::kApk: {
      BigBuffer buffer(1024);
      XmlFlattenerOptions options = {};
      options.keep_raw_values = keep_raw_values;
      options.use_utf16 = utf16;
      XmlFlattener flattener(&buffer, options);
      if (!flattener.Consume(context, &xml_res)) {
        return false;
      }

      io::BigBufferInputStream input_stream(&buffer);
      return io::CopyInputStreamToArchive(context, &input_stream, path.to_string(),
                                          ArchiveEntry::kCompress, writer);
    } break;

    case OutputFormat::kProto: {
      pb::XmlNode pb_node;
      SerializeXmlResourceToPb(xml_res, &pb_node);
      return io::CopyProtoToArchive(context, &pb_node, path.to_string(), ArchiveEntry::kCompress,
                                    writer);
    } break;
  }
  return false;
}

// Inflates an XML file from the source path.
static std::unique_ptr<xml::XmlResource> LoadXml(const std::string& path, IDiagnostics* diag) {
  FileInputStream fin(path);
  if (fin.HadError()) {
    diag->Error(DiagMessage(path) << "failed to load XML file: " << fin.GetError());
    return {};
  }
  return xml::Inflate(&fin, diag, Source(path));
}

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

// A sampling of public framework resource IDs.
struct R {
  struct attr {
    enum : uint32_t {
      paddingLeft = 0x010100d6u,
      paddingRight = 0x010100d8u,
      paddingHorizontal = 0x0101053du,

      paddingTop = 0x010100d7u,
      paddingBottom = 0x010100d9u,
      paddingVertical = 0x0101053eu,

      layout_marginLeft = 0x010100f7u,
      layout_marginRight = 0x010100f9u,
      layout_marginHorizontal = 0x0101053bu,

      layout_marginTop = 0x010100f8u,
      layout_marginBottom = 0x010100fau,
      layout_marginVertical = 0x0101053cu,
    };
  };
};

class ResourceFileFlattener {
 public:
  ResourceFileFlattener(const ResourceFileFlattenerOptions& options, IAaptContext* context,
                        proguard::KeepSet* keep_set);

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

 private:
  struct FileOperation {
    ConfigDescription config;

    // The entry this file came from.
    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;
  };

  uint32_t GetCompressionFlags(const StringPiece& str);

  std::vector<std::unique_ptr<xml::XmlResource>> LinkAndVersionXmlFile(ResourceTable* table,
                                                                       FileOperation* file_op);

  ResourceFileFlattenerOptions options_;
  IAaptContext* context_;
  proguard::KeepSet* keep_set_;
  XmlCompatVersioner::Rules rules_;
};

ResourceFileFlattener::ResourceFileFlattener(const ResourceFileFlattenerOptions& options,
                                             IAaptContext* context, proguard::KeepSet* keep_set)
    : options_(options), context_(context), keep_set_(keep_set) {
  SymbolTable* symm = context_->GetExternalSymbols();

  // Build up the rules for degrading newer attributes to older ones.
  // NOTE(adamlesinski): These rules are hardcoded right now, but they should be
  // generated from the attribute definitions themselves (b/62028956).
  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::paddingHorizontal)) {
    std::vector<ReplacementAttr> replacements{
        {"paddingLeft", R::attr::paddingLeft, Attribute(android::ResTable_map::TYPE_DIMENSION)},
        {"paddingRight", R::attr::paddingRight, Attribute(android::ResTable_map::TYPE_DIMENSION)},
    };
    rules_[R::attr::paddingHorizontal] =
        util::make_unique<DegradeToManyRule>(std::move(replacements));
  }

  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::paddingVertical)) {
    std::vector<ReplacementAttr> replacements{
        {"paddingTop", R::attr::paddingTop, Attribute(android::ResTable_map::TYPE_DIMENSION)},
        {"paddingBottom", R::attr::paddingBottom, Attribute(android::ResTable_map::TYPE_DIMENSION)},
    };
    rules_[R::attr::paddingVertical] =
        util::make_unique<DegradeToManyRule>(std::move(replacements));
  }

  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::layout_marginHorizontal)) {
    std::vector<ReplacementAttr> replacements{
        {"layout_marginLeft", R::attr::layout_marginLeft,
         Attribute(android::ResTable_map::TYPE_DIMENSION)},
        {"layout_marginRight", R::attr::layout_marginRight,
         Attribute(android::ResTable_map::TYPE_DIMENSION)},
    };
    rules_[R::attr::layout_marginHorizontal] =
        util::make_unique<DegradeToManyRule>(std::move(replacements));
  }

  if (const SymbolTable::Symbol* s = symm->FindById(R::attr::layout_marginVertical)) {
    std::vector<ReplacementAttr> replacements{
        {"layout_marginTop", R::attr::layout_marginTop,
         Attribute(android::ResTable_map::TYPE_DIMENSION)},
        {"layout_marginBottom", R::attr::layout_marginBottom,
         Attribute(android::ResTable_map::TYPE_DIMENSION)},
    };
    rules_[R::attr::layout_marginVertical] =
        util::make_unique<DegradeToManyRule>(std::move(replacements));
  }
}

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

static bool IsTransitionElement(const std::string& name) {
  return name == "fade" || name == "changeBounds" || name == "slide" || name == "explode" ||
         name == "changeImageTransform" || name == "changeTransform" ||
         name == "changeClipBounds" || name == "autoTransition" || name == "recolor" ||
         name == "changeScroll" || name == "transitionSet" || name == "transition" ||
         name == "transitionManager";
}

static bool IsVectorElement(const std::string& name) {
  return name == "vector" || name == "animated-vector" || name == "pathInterpolator" ||
         name == "objectAnimator" || name == "gradient" || name == "animated-selector";
}

template <typename T>
std::vector<T> make_singleton_vec(T&& val) {
  std::vector<T> vec;
  vec.emplace_back(std::forward<T>(val));
  return vec;
}

std::vector<std::unique_ptr<xml::XmlResource>> ResourceFileFlattener::LinkAndVersionXmlFile(
    ResourceTable* table, FileOperation* file_op) {
  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 << " (" << doc->file.name << ")");
  }

  // First, strip out any tools namespace attributes. AAPT stripped them out early, which means
  // that existing projects have out-of-date references which pass compilation.
  xml::StripAndroidStudioAttributes(doc->root.get());

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

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

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

  if (options_.no_auto_version) {
    return make_singleton_vec(std::move(file_op->xml_to_flatten));
  }

  if (options_.no_version_vectors || options_.no_version_transitions) {
    // Skip this if it is a vector or animated-vector.
    xml::Element* el = doc->root.get();
    if (el && el->namespace_uri.empty()) {
      if ((options_.no_version_vectors && IsVectorElement(el->name)) ||
          (options_.no_version_transitions && IsTransitionElement(el->name))) {
        return make_singleton_vec(std::move(file_op->xml_to_flatten));
      }
    }
  }

  const ConfigDescription& config = file_op->config;
  ResourceEntry* entry = file_op->entry;

  XmlCompatVersioner xml_compat_versioner(&rules_);
  const util::Range<ApiVersion> api_range{config.sdkVersion,
                                          FindNextApiVersionForConfig(entry, config)};
  return xml_compat_versioner.Process(context_, doc, api_range);
}

ResourceFile::Type XmlFileTypeForOutputFormat(OutputFormat format) {
  switch (format) {
    case OutputFormat::kApk:
      return ResourceFile::Type::kBinaryXml;
    case OutputFormat::kProto:
      return ResourceFile::Type::kProtoXml;
  }
  LOG_ALWAYS_FATAL("unreachable");
  return ResourceFile::Type::kUnknown;
}

bool ResourceFileFlattener::Flatten(ResourceTable* table, IArchiveWriter* archive_writer) {
  bool error = false;
  std::map<std::pair<ConfigDescription, StringPiece>, FileOperation> config_sorted_files;

  proguard::CollectResourceReferences(context_, table, keep_set_);

  for (auto& pkg : table->packages) {
    CHECK(!pkg->name.empty()) << "Packages must have names when being linked";

    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) {
          // WARNING! Do not insert or remove any resources while executing in this scope. It will
          // corrupt the iteration order.

          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;
          file_op.file_to_copy = file;

          if (type->type != ResourceType::kRaw &&
              (file_ref->type == ResourceFile::Type::kBinaryXml ||
               file_ref->type == ResourceFile::Type::kProtoXml)) {
            std::unique_ptr<io::IData> data = file->OpenAsData();
            if (!data) {
              context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
                                                << "failed to open file");
              return false;
            }

            if (file_ref->type == ResourceFile::Type::kProtoXml) {
              pb::XmlNode pb_xml_node;
              if (!pb_xml_node.ParseFromArray(data->data(), static_cast<int>(data->size()))) {
                context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
                                                  << "failed to parse proto XML");
                return false;
              }

              std::string error;
              file_op.xml_to_flatten = DeserializeXmlResourceFromPb(pb_xml_node, &error);
              if (file_op.xml_to_flatten == nullptr) {
                context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
                                                  << "failed to deserialize proto XML: " << error);
                return false;
              }
            } else {
              std::string error_str;
              file_op.xml_to_flatten = xml::Inflate(data->data(), data->size(), &error_str);
              if (file_op.xml_to_flatten == nullptr) {
                context_->GetDiagnostics()->Error(DiagMessage(file->GetSource())
                                                  << "failed to parse binary XML: " << error_str);
                return false;
              }
            }

            // Update the type that this file will be written as.
            file_ref->type = XmlFileTypeForOutputFormat(options_.output_format);

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

          // 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 flatten the sorted values.
      for (auto& map_entry : config_sorted_files) {
        const ConfigDescription& config = map_entry.first.first;
        FileOperation& file_op = map_entry.second;

        if (file_op.xml_to_flatten) {
          std::vector<std::unique_ptr<xml::XmlResource>> versioned_docs =
              LinkAndVersionXmlFile(table, &file_op);
          if (versioned_docs.empty()) {
            error = true;
            continue;
          }

          for (std::unique_ptr<xml::XmlResource>& doc : versioned_docs) {
            std::string dst_path = file_op.dst_path;
            if (doc->file.config != file_op.config) {
              // Only add the new versioned configurations.
              if (context_->IsVerbose()) {
                context_->GetDiagnostics()->Note(DiagMessage(doc->file.source)
                                                 << "auto-versioning resource from config '"
                                                 << config << "' -> '" << doc->file.config << "'");
              }

              const ResourceFile& file = doc->file;
              dst_path = ResourceUtils::BuildResourceFileName(file, context_->GetNameMangler());

              std::unique_ptr<FileReference> file_ref =
                  util::make_unique<FileReference>(table->string_pool.MakeRef(dst_path));
              file_ref->SetSource(doc->file.source);
              // Update the output format of this XML file.
              file_ref->type = XmlFileTypeForOutputFormat(options_.output_format);
              if (!table->AddResourceMangled(file.name, file.config, {}, std::move(file_ref),
                                             context_->GetDiagnostics())) {
                return false;
              }
            }

            error |= !FlattenXml(context_, *doc, dst_path, options_.keep_raw_values,
                                 false /*utf16*/, options_.output_format, archive_writer);
          }
        } else {
          error |= !io::CopyFileToArchive(context_, file_op.file_to_copy, file_op.dst_path,
                                          GetCompressionFlags(file_op.dst_path), archive_writer);
        }
      }
    }
  }
  return !error;
}

static bool WriteStableIdMapToPath(IDiagnostics* diag,
                                   const std::unordered_map<ResourceName, ResourceId>& id_map,
                                   const std::string& id_map_path) {
  io::FileOutputStream fout(id_map_path);
  if (fout.HadError()) {
    diag->Error(DiagMessage(id_map_path) << "failed to open: " << fout.GetError());
    return false;
  }

  text::Printer printer(&fout);
  for (const auto& entry : id_map) {
    const ResourceName& name = entry.first;
    const ResourceId& id = entry.second;
    printer.Print(name.to_string());
    printer.Print(" = ");
    printer.Println(id.to_string());
  }
  fout.Flush();

  if (fout.HadError()) {
    diag->Error(DiagMessage(id_map_path) << "failed writing to file: " << fout.GetError());
    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, true /*follow_symlinks*/)) {
    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 int32_t FindFrameworkAssetManagerCookie(const android::AssetManager& assets) {
  using namespace android;

  // Find the system package (0x01). AAPT always generates attributes with the type 0x01, so
  // we're looking for the first attribute resource in the system package.
  const ResTable& table = assets.getResources(true);
  Res_value val;
  ssize_t idx = table.getResource(0x01010000, &val, true);
  if (idx != NO_ERROR) {
    // Try as a bag.
    const ResTable::bag_entry* entry;
    ssize_t cnt = table.lockBag(0x01010000, &entry);
    if (cnt >= 0) {
      idx = entry->stringBlock;
    }
    table.unlockBag(entry);
  }

  if (idx < 0) {
    return 0;
  }
  return table.getTableCookie(idx);
}

class Linker {
 public:
  Linker(LinkContext* context, const LinkOptions& options)
      : options_(options),
        context_(context),
        final_table_(),
        file_collection_(util::make_unique<io::FileCollection>()) {
  }

  void ExtractCompileSdkVersions(android::AssetManager* assets) {
    using namespace android;

    int32_t cookie = FindFrameworkAssetManagerCookie(*assets);
    if (cookie == 0) {
      // No Framework assets loaded. Not a failure.
      return;
    }

    std::unique_ptr<Asset> manifest(
        assets->openNonAsset(cookie, kAndroidManifestPath, Asset::AccessMode::ACCESS_BUFFER));
    if (manifest == nullptr) {
      // No errors.
      return;
    }

    std::string error;
    std::unique_ptr<xml::XmlResource> manifest_xml =
        xml::Inflate(manifest->getBuffer(true /*wordAligned*/), manifest->getLength(), &error);
    if (manifest_xml == nullptr) {
      // No errors.
      return;
    }

    if (!options_.manifest_fixer_options.compile_sdk_version) {
      xml::Attribute* attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionCode");
      if (attr != nullptr) {
        Maybe<std::string>& compile_sdk_version = options_.manifest_fixer_options.compile_sdk_version;
        if (BinaryPrimitive* prim = ValueCast<BinaryPrimitive>(attr->compiled_value.get())) {
          switch (prim->value.dataType) {
            case Res_value::TYPE_INT_DEC:
              compile_sdk_version = StringPrintf("%" PRId32, static_cast<int32_t>(prim->value.data));
              break;
            case Res_value::TYPE_INT_HEX:
              compile_sdk_version = StringPrintf("%" PRIx32, prim->value.data);
              break;
            default:
              break;
          }
        } else if (String* str = ValueCast<String>(attr->compiled_value.get())) {
          compile_sdk_version = *str->value;
        } else {
          compile_sdk_version = attr->value;
        }
      }
    }

    if (!options_.manifest_fixer_options.compile_sdk_version_codename) {
      xml::Attribute* attr = manifest_xml->root->FindAttribute(xml::kSchemaAndroid, "versionName");
      if (attr != nullptr) {
        Maybe<std::string>& compile_sdk_version_codename =
            options_.manifest_fixer_options.compile_sdk_version_codename;
        if (String* str = ValueCast<String>(attr->compiled_value.get())) {
          compile_sdk_version_codename = *str->value;
        } else {
          compile_sdk_version_codename = attr->value;
        }
      }
    }
  }

  // Creates a SymbolTable that loads symbols from the various APKs.
  // Pre-condition: context_->GetCompilationPackage() needs to be set.
  bool LoadSymbolsFromIncludePaths() {
    auto asset_source = util::make_unique<AssetManagerSymbolSource>();
    for (const std::string& path : options_.include_paths) {
      if (context_->IsVerbose()) {
        context_->GetDiagnostics()->Note(DiagMessage() << "including " << path);
      }

      std::string error;
      auto zip_collection = io::ZipFileCollection::Create(path, &error);
      if (zip_collection == nullptr) {
        context_->GetDiagnostics()->Error(DiagMessage() << "failed to open APK: " << error);
        return false;
      }

      if (zip_collection->FindFile(kProtoResourceTablePath) != nullptr) {
        // Load this as a static library include.
        std::unique_ptr<LoadedApk> static_apk = LoadedApk::LoadProtoApkFromFileCollection(
            Source(path), std::move(zip_collection), context_->GetDiagnostics());
        if (static_apk == nullptr) {
          return false;
        }

        if (context_->GetPackageType() != PackageType::kStaticLib) {
          // Can't include static libraries when not building a static library (they have no IDs
          // assigned).
          context_->GetDiagnostics()->Error(
              DiagMessage(path) << "can't include static library when not building a static lib");
          return false;
        }

        ResourceTable* table = static_apk->GetResourceTable();

        // 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) {
          // Since package names can differ, and multiple packages can exist in a ResourceTable,
          // we place the requirement that all static libraries are built with the package
          // ID 0x7f. So if one is not found, this is an error.
          if (ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId)) {
            pkg->name = context_->GetCompilationPackage();
          } else {
            context_->GetDiagnostics()->Error(DiagMessage(path)
                                              << "no package with ID 0x7f found in static library");
            return false;
          }
        }

        context_->GetExternalSymbols()->AppendSource(
            util::make_unique<ResourceTableSymbolSource>(table));
        static_library_includes_.push_back(std::move(static_apk));
      } else {
        if (!asset_source->AddAssetPath(path)) {
          context_->GetDiagnostics()->Error(DiagMessage()
                                            << "failed to load include path " << path);
          return false;
        }
      }
    }

    // Capture the shared libraries so that the final resource table can be properly flattened
    // with support for shared libraries.
    for (auto& entry : asset_source->GetAssignedPackageIds()) {
      if (entry.first == kAppPackageId) {
        // Capture the included base feature package.
        included_feature_base_ = entry.second;
      } else if (entry.first == kFrameworkPackageId) {
        // Try to embed which version of the framework we're compiling against.
        // First check if we should use compileSdkVersion at all. Otherwise compilation may fail
        // when linking our synthesized 'android:compileSdkVersion' attribute.
        std::unique_ptr<SymbolTable::Symbol> symbol = asset_source->FindByName(
            ResourceName("android", ResourceType::kAttr, "compileSdkVersion"));
        if (symbol != nullptr && symbol->is_public) {
          // The symbol is present and public, extract the android:versionName and
          // android:versionCode from the framework AndroidManifest.xml.
          ExtractCompileSdkVersions(asset_source->GetAssetManager());
        }
      } else if (asset_source->IsPackageDynamic(entry.first)) {
        final_table_.included_packages_[entry.first] = entry.second;
      }
    }

    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.
    xml::Element* manifest_el = xml::FindRootElement(xml_res->root.get());
    if (manifest_el == nullptr) {
      return {};
    }

    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* version_code_major_attr =
        manifest_el->FindAttribute(xml::kSchemaAndroid, "versionCodeMajor")) {
      Maybe<uint32_t> maybe_code = ResourceUtils::ParseInt(version_code_major_attr->value);
      if (!maybe_code) {
        diag->Error(DiagMessage(xml_res->file.source.WithLine(manifest_el->line_number))
                        << "invalid android:versionCodeMajor '"
                        << version_code_major_attr->value << "'");
        return {};
      }
      app_info.version_code_major = 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::Attribute* split_name_attr = manifest_el->FindAttribute({}, "split")) {
      if (!split_name_attr->value.empty()) {
        app_info.split_name = split_name_attr->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 = ResourceUtils::ParseSdkVersion(min_sdk->value);
      }
    }
    return app_info;
  }

  // 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 "
                                                          << StringPrintf("%02x", type->id.value())
                                                          << " 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 "
                              << StringPrintf("%02x", entry->id.value()) << " 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, OutputFormat format, IArchiveWriter* writer) {
    switch (format) {
      case OutputFormat::kApk: {
        BigBuffer buffer(1024);
        TableFlattener flattener(options_.table_flattener_options, &buffer);
        if (!flattener.Consume(context_, table)) {
          context_->GetDiagnostics()->Error(DiagMessage() << "failed to flatten resource table");
          return false;
        }

        io::BigBufferInputStream input_stream(&buffer);
        return io::CopyInputStreamToArchive(context_, &input_stream, kApkResourceTablePath,
                                            ArchiveEntry::kAlign, writer);
      } break;

      case OutputFormat::kProto: {
        pb::ResourceTable pb_table;
        SerializeTableToPb(*table, &pb_table, context_->GetDiagnostics());
        return io::CopyProtoToArchive(context_, &pb_table, kProtoResourceTablePath,
                                      ArchiveEntry::kCompress, writer);
      } break;
    }
    return false;
  }

  bool WriteJavaFile(ResourceTable* table, const StringPiece& package_name_to_generate,
                     const StringPiece& out_package, const JavaClassGeneratorOptions& java_options,
                     const Maybe<std::string>& out_text_symbols_path = {}) {
    if (!options_.generate_java_class_path && !out_text_symbols_path) {
      return true;
    }

    std::string out_path;
    std::unique_ptr<io::FileOutputStream> fout;
    if (options_.generate_java_class_path) {
      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");

      fout = util::make_unique<io::FileOutputStream>(out_path);
      if (fout->HadError()) {
        context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
                                                        << "': " << fout->GetError());
        return false;
      }
    }

    std::unique_ptr<io::FileOutputStream> fout_text;
    if (out_text_symbols_path) {
      fout_text = util::make_unique<io::FileOutputStream>(out_text_symbols_path.value());
      if (fout_text->HadError()) {
        context_->GetDiagnostics()->Error(DiagMessage()
                                          << "failed writing to '" << out_text_symbols_path.value()
                                          << "': " << fout_text->GetError());
        return false;
      }
    }

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

    return true;
  }

  bool GenerateJavaClasses() {
    // The set of packages whose R class to call in the main classes onResourcesLoaded callback.
    std::vector<std::string> packages_to_callback;

    JavaClassGeneratorOptions template_options;
    template_options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
    template_options.javadoc_annotations = options_.javadoc_annotations;

    if (context_->GetPackageType() == PackageType::kStaticLib || options_.generate_non_final_ids) {
      template_options.use_final = false;
    }

    if (context_->GetPackageType() == PackageType::kSharedLib) {
      template_options.use_final = false;
      template_options.rewrite_callback_options = OnResourcesLoadedCallbackOptions{};
    }

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

    // Generate the private symbols if required.
    if (options_.private_symbols) {
      packages_to_callback.push_back(options_.private_symbols.value());

      // 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.
      JavaClassGeneratorOptions options = template_options;
      options.types = JavaClassGeneratorOptions::SymbolTypes::kPublicPrivate;
      if (!WriteJavaFile(&final_table_, actual_package, options_.private_symbols.value(),
                         options)) {
        return false;
      }
    }

    // Generate copies of the original package R class but with different package names.
    // This is to support non-namespaced builds.
    for (const std::string& extra_package : options_.extra_java_packages) {
      packages_to_callback.push_back(extra_package);

      JavaClassGeneratorOptions options = template_options;
      options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
      if (!WriteJavaFile(&final_table_, actual_package, extra_package, options)) {
        return false;
      }
    }

    // Generate R classes for each package that was merged (static library).
    // Use the actual package's resources only.
    for (const std::string& package : table_merger_->merged_packages()) {
      packages_to_callback.push_back(package);

      JavaClassGeneratorOptions options = template_options;
      options.types = JavaClassGeneratorOptions::SymbolTypes::kAll;
      if (!WriteJavaFile(&final_table_, package, package, options)) {
        return false;
      }
    }

    // Generate the main public R class.
    JavaClassGeneratorOptions options = template_options;

    // Only generate public symbols if we have a private package.
    if (options_.private_symbols) {
      options.types = JavaClassGeneratorOptions::SymbolTypes::kPublic;
    }

    if (options.rewrite_callback_options) {
      options.rewrite_callback_options.value().packages_to_callback =
          std::move(packages_to_callback);
    }

    if (!WriteJavaFile(&final_table_, actual_package, output_package, options,
                       options_.generate_text_symbols_path)) {
      return false;
    }

    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 =
        options_.custom_java_package.value_or_default(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");

    io::FileOutputStream fout(out_path);
    if (fout.HadError()) {
      context_->GetDiagnostics()->Error(DiagMessage() << "failed to open '" << out_path
                                                      << "': " << fout.GetError());
      return false;
    }

    ClassDefinition::WriteJavaFile(manifest_class.get(), package_utf8, true, &fout);
    fout.Flush();

    if (fout.HadError()) {
      context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
                                                      << "': " << fout.GetError());
      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();
    io::FileOutputStream fout(out_path);
    if (fout.HadError()) {
      context_->GetDiagnostics()->Error(DiagMessage() << "failed to open '" << out_path
                                                      << "': " << fout.GetError());
      return false;
    }

    proguard::WriteKeepSet(keep_set, &fout);
    fout.Flush();

    if (fout.HadError()) {
      context_->GetDiagnostics()->Error(DiagMessage() << "failed writing to '" << out_path
                                                      << "': " << fout.GetError());
      return false;
    }
    return true;
  }

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

    std::unique_ptr<LoadedApk> apk = LoadedApk::LoadApkFromPath(input, context_->GetDiagnostics());
    if (apk == nullptr) {
      context_->GetDiagnostics()->Error(DiagMessage(input) << "invalid static library");
      return false;
    }

    ResourceTable* table = apk->GetResourceTable();
    ResourceTablePackage* pkg = table->FindPackageById(kAppPackageId);
    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);
      }

      // Clear the package name, so as to make the resources look like they are coming from the
      // local package.
      pkg->name = "";
      result = table_merger_->Merge(Source(input), table, override);

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

    if (!result) {
      return false;
    }

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

  bool MergeExportedSymbols(const Source& source,
                            const std::vector<SourcedResourceName>& exported_symbols) {
    // Add the exports of this file to the table.
    for (const SourcedResourceName& exported_symbol : exported_symbols) {
      ResourceName res_name = exported_symbol.name;
      if (res_name.package.empty()) {
        res_name.package = context_->GetCompilationPackage();
      }

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

      std::unique_ptr<Id> id = util::make_unique<Id>();
      id->SetSource(source.WithLine(exported_symbol.line));
      bool result =
          final_table_.AddResourceMangled(res_name, ConfigDescription::DefaultConfig(),
                                          std::string(), std::move(id), context_->GetDiagnostics());
      if (!result) {
        return false;
      }
    }
    return true;
  }

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

    if (!table_merger_->MergeFile(compiled_file, override, file)) {
      return false;
    }
    return MergeExportedSymbols(compiled_file.source, compiled_file.exported_symbols);
  }

  // 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 file 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 an AAPT Container file (.apc/.flat) 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.
  // 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, ".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;
    } else if (!util::EndsWith(src.path, ".apc") && !util::EndsWith(src.path, ".flat")) {
      if (context_->IsVerbose()) {
        context_->GetDiagnostics()->Warn(DiagMessage(src) << "ignoring unrecognized file");
        return true;
      }
    }

    std::unique_ptr<io::InputStream> input_stream = file->OpenInputStream();
    if (input_stream == nullptr) {
      context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to open file");
      return false;
    }

    if (input_stream->HadError()) {
      context_->GetDiagnostics()->Error(DiagMessage(src)
                                        << "failed to open file: " << input_stream->GetError());
      return false;
    }

    ContainerReaderEntry* entry;
    ContainerReader reader(input_stream.get());

    if (reader.HadError()) {
      context_->GetDiagnostics()->Error(DiagMessage(src)
                                        << "failed to read file: " << reader.GetError());
      return false;
    }

    while ((entry = reader.Next()) != nullptr) {
      if (entry->Type() == ContainerEntryType::kResTable) {
        pb::ResourceTable pb_table;
        if (!entry->GetResTable(&pb_table)) {
          context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to read resource table: "
                                                             << entry->GetError());
          return false;
        }

        ResourceTable table;
        std::string error;
        if (!DeserializeTableFromPb(pb_table, nullptr /*files*/, &table, &error)) {
          context_->GetDiagnostics()->Error(DiagMessage(src)
                                            << "failed to deserialize resource table: " << error);
          return false;
        }

        if (!table_merger_->Merge(src, &table, override)) {
          context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to merge resource table");
          return false;
        }
      } else if (entry->Type() == ContainerEntryType::kResFile) {
        pb::internal::CompiledFile pb_compiled_file;
        off64_t offset;
        size_t len;
        if (!entry->GetResFileOffsets(&pb_compiled_file, &offset, &len)) {
          context_->GetDiagnostics()->Error(DiagMessage(src) << "failed to get resource file: "
                                                             << entry->GetError());
          return false;
        }

        ResourceFile resource_file;
        std::string error;
        if (!DeserializeCompiledFileFromPb(pb_compiled_file, &resource_file, &error)) {
          context_->GetDiagnostics()->Error(DiagMessage(src)
                                            << "failed to read compiled header: " << error);
          return false;
        }

        if (!MergeCompiledFile(resource_file, file->CreateFileSegment(offset, len), override)) {
          return false;
        }
      }
    }
    return true;
  }

  bool CopyAssetsDirsToApk(IArchiveWriter* writer) {
    std::map<std::string, std::unique_ptr<io::RegularFile>> merged_assets;
    for (const std::string& assets_dir : options_.assets_dirs) {
      Maybe<std::vector<std::string>> files =
          file::FindFiles(assets_dir, context_->GetDiagnostics(), nullptr);
      if (!files) {
        return false;
      }

      for (const std::string& file : files.value()) {
        std::string full_key = "assets/" + file;
        std::string full_path = assets_dir;
        file::AppendPath(&full_path, file);

        auto iter = merged_assets.find(full_key);
        if (iter == merged_assets.end()) {
          merged_assets.emplace(std::move(full_key),
                                util::make_unique<io::RegularFile>(Source(std::move(full_path))));
        } else if (context_->IsVerbose()) {
          context_->GetDiagnostics()->Warn(DiagMessage(iter->second->GetSource())
                                           << "asset file overrides '" << full_path << "'");
        }
      }
    }

    for (auto& entry : merged_assets) {
      uint32_t compression_flags = ArchiveEntry::kCompress;
      std::string extension = file::GetExtension(entry.first).to_string();
      if (options_.extensions_to_not_compress.count(extension) > 0) {
        compression_flags = 0u;
      }

      if (!io::CopyFileToArchive(context_, entry.second.get(), entry.first, compression_flags,
                                 writer)) {
        return false;
      }
    }
    return true;
  }

  // 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 = context_->GetPackageType() == PackageType::kStaticLib;
    bool result = FlattenXml(context_, *manifest, "AndroidManifest.xml", keep_raw_values,
                             true /*utf16*/, options_.output_format, writer);
    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_version_transitions = options_.no_version_transitions;
    file_flattener_options.no_xml_namespaces = options_.no_xml_namespaces;
    file_flattener_options.update_proguard_spec =
        static_cast<bool>(options_.generate_proguard_rules_path);
    file_flattener_options.output_format = options_.output_format;

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

    // Hack to fix b/68820737.
    // We need to modify the ResourceTable's package name, but that should NOT affect
    // anything else being generated, which includes the Java classes.
    // If required, the package name is modifed before flattening, and then modified back
    // to its original name.
    ResourceTablePackage* package_to_rewrite = nullptr;
    // Pre-O, the platform treats negative resource IDs [those with a package ID of 0x80
    // or higher] as invalid. In order to work around this limitation, we allow the use
    // of traditionally reserved resource IDs [those between 0x02 and 0x7E]. Allow the
    // definition of what a valid "split" package ID is to account for this.
    const bool isSplitPackage = (options_.allow_reserved_package_id &&
          context_->GetPackageId() != kAppPackageId &&
          context_->GetPackageId() != kFrameworkPackageId)
        || (!options_.allow_reserved_package_id && context_->GetPackageId() > kAppPackageId);
    if (isSplitPackage &&
        included_feature_base_ == make_value(context_->GetCompilationPackage())) {
      // The base APK is included, and this is a feature split. If the base package is
      // the same as this package, then we are building an old style Android Instant Apps feature
      // split and must apply this workaround to avoid requiring namespaces support.
      package_to_rewrite = table->FindPackage(context_->GetCompilationPackage());
      if (package_to_rewrite != nullptr) {
        CHECK_EQ(1u, table->packages.size()) << "can't change name of package when > 1 package";

        std::string new_package_name =
            StringPrintf("%s.%s", package_to_rewrite->name.c_str(),
                         app_info_.split_name.value_or_default("feature").c_str());

        if (context_->IsVerbose()) {
          context_->GetDiagnostics()->Note(
              DiagMessage() << "rewriting resource package name for feature split to '"
                            << new_package_name << "'");
        }
        package_to_rewrite->name = new_package_name;
      }
    }

    bool success = FlattenTable(table, options_.output_format, writer);

    if (package_to_rewrite != nullptr) {
      // Change the name back.
      package_to_rewrite->name = context_->GetCompilationPackage();
      if (package_to_rewrite->id) {
        table->included_packages_.erase(package_to_rewrite->id.value());
      }
    }

    if (!success) {
      context_->GetDiagnostics()->Error(DiagMessage() << "failed to write resource table");
    }
    return success;
  }

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

    // Now that the compilation package is set, load the dependencies. This will also extract
    // the Android framework's versionCode and versionName, if they exist.
    if (!LoadSymbolsFromIncludePaths()) {
      return 1;
    }

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

    app_info_ = maybe_app_info.value();
    context_->SetMinSdkVersion(app_info_.min_sdk_version.value_or_default(0));

    context_->SetNameManglerPolicy(NameManglerPolicy{context_->GetCompilationPackage()});

    // Override the package ID when it is "android".
    if (context_->GetCompilationPackage() == "android") {
      context_->SetPackageId(0x01);

      // Verify we're building a regular app.
      if (context_->GetPackageType() != PackageType::kApp) {
        context_->GetDiagnostics()->Error(
            DiagMessage() << "package 'android' can only be built as a regular app");
        return 1;
      }
    }

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

    if (context_->IsVerbose()) {
      context_->GetDiagnostics()->Note(DiagMessage()
                                       << StringPrintf("linking package '%s' using package ID %02x",
                                                       context_->GetCompilationPackage().data(),
                                                       context_->GetPackageId()));
    }

    // Extract symbols from AndroidManifest.xml, since this isn't merged like the other XML files
    // in res/**/*.
    {
      XmlIdCollector collector;
      if (!collector.Consume(context_, manifest_xml.get())) {
        return false;
      }

      if (!MergeExportedSymbols(manifest_xml->file.source, manifest_xml->file.exported_symbols)) {
        return false;
      }
    }

    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 (context_->GetPackageType() != PackageType::kStaticLib) {
      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_));

    // Workaround for pre-O runtime that would treat negative resource IDs
    // (any ID with a package ID > 7f) as invalid. Intercept any ID (PPTTEEEE) with PP > 0x7f
    // and type == 'id', and return the ID 0x7fPPEEEE. IDs don't need to be real resources, they
    // are just identifiers.
    if (context_->GetMinSdkVersion() < SDK_O && context_->GetPackageType() == PackageType::kApp) {
      if (context_->IsVerbose()) {
        context_->GetDiagnostics()->Note(DiagMessage()
                                         << "enabling pre-O feature split ID rewriting");
      }
      context_->GetExternalSymbols()->SetDelegate(
          util::make_unique<FeatureSplitSymbolTableDelegate>(context_));
    }

    // Before we process anything, remove the resources whose default values don't exist.
    // We want to force any references to these to fail the build.
    if (!NoDefaultResourceRemover{}.Consume(context_, &final_table_)) {
      context_->GetDiagnostics()->Error(DiagMessage()
                                        << "failed removing resources with no defaults");
      return 1;
    }

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

    if (context_->GetPackageType() == PackageType::kStaticLib) {
      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 (context_->GetPackageType() != PackageType::kStaticLib && 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(options_.generate_conditional_proguard_rules);
    proguard::KeepSet proguard_main_dex_keep_set;

    if (context_->GetPackageType() == PackageType::kStaticLib) {
      if (options_.table_splitter_options.config_filter != nullptr ||
          !options_.table_splitter_options.preferred_densities.empty()) {
        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.
      options_.split_constraints =
          AdjustSplitConstraintsForMinSdk(context_->GetMinSdkVersion(), options_.split_constraints);

      TableSplitter table_splitter(options_.split_constraints, 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 = options_.split_constraints.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(manifest_xml.get(), &proguard_keep_set)) {
          error = true;
        }

        if (options_.generate_main_dex_proguard_rules_path &&
            !proguard::CollectProguardRulesForManifest(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 (!CopyAssetsDirsToApk(archive_writer.get())) {
      return 1;
    }

    if (options_.generate_java_class_path || options_.generate_text_symbols_path) {
      if (!GenerateJavaClasses()) {
        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;
    }
    return 0;
  }

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

  AppInfo app_info_;

  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 retain ownership of the
  // collections.
  std::vector<std::unique_ptr<io::IFileCollection>> collections_;

  // The set of merged APKs. This is mainly here to retain ownership of the APKs.
  std::vector<std::unique_ptr<LoadedApk>> merged_apks_;

  // The set of included APKs (not merged). This is mainly here to retain ownership of the APKs.
  std::vector<std::unique_ptr<LoadedApk>> static_library_includes_;

  // The set of shared libraries being used, mapping their assigned package ID to package name.
  std::map<size_t, std::string> shared_libs_;

  // The package name of the base application, if it is included.
  Maybe<std::string> included_feature_base_;
};

int LinkCommand::Action(const std::vector<std::string>& args) {
  LinkContext context(diag_);

  // Expand all argument-files passed into the command line. These start with '@'.
  std::vector<std::string> arg_list;
  for (const std::string& arg : args) {
    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_);
  }

  if (int{shared_lib_} + int{static_lib_} + int{proto_format_} > 1) {
    context.GetDiagnostics()->Error(
        DiagMessage()
            << "only one of --shared-lib, --static-lib, or --proto_format can be defined");
    return 1;
  }

  // The default build type.
  context.SetPackageType(PackageType::kApp);
  context.SetPackageId(kAppPackageId);

  if (shared_lib_) {
    context.SetPackageType(PackageType::kSharedLib);
    context.SetPackageId(0x00);
  } else if (static_lib_) {
    context.SetPackageType(PackageType::kStaticLib);
    options_.output_format = OutputFormat::kProto;
  } else if (proto_format_) {
    options_.output_format = OutputFormat::kProto;
  }

  if (package_id_) {
    if (context.GetPackageType() != PackageType::kApp) {
      context.GetDiagnostics()->Error(
          DiagMessage() << "can't specify --package-id when not building a regular app");
      return 1;
    }

    const Maybe<uint32_t> maybe_package_id_int = ResourceUtils::ParseInt(package_id_.value());
    if (!maybe_package_id_int) {
      context.GetDiagnostics()->Error(DiagMessage() << "package ID '" << package_id_.value()
                                                    << "' is not a valid integer");
      return 1;
    }

    const uint32_t package_id_int = maybe_package_id_int.value();
    if (package_id_int > std::numeric_limits<uint8_t>::max()
        || package_id_int == kFrameworkPackageId
        || (!options_.allow_reserved_package_id && package_id_int < kAppPackageId)) {
      context.GetDiagnostics()->Error(
          DiagMessage() << StringPrintf(
              "invalid package ID 0x%02x. Must be in the range 0x7f-0xff.", package_id_int));
      return 1;
    }
    context.SetPackageId(static_cast<uint8_t>(package_id_int));
  }

  // 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());
      }
    }
  }

  std::unique_ptr<IConfigFilter> filter;
  if (!configs_.empty()) {
    filter = ParseConfigFilterParameters(configs_, context.GetDiagnostics());
    if (filter == nullptr) {
      return 1;
    }
    options_.table_splitter_options.config_filter = filter.get();
  }

  if (preferred_density_) {
    Maybe<uint16_t> density =
        ParseTargetDensityParameter(preferred_density_.value(), context.GetDiagnostics());
    if (!density) {
      return 1;
    }
    options_.table_splitter_options.preferred_densities.push_back(density.value());
  }

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

  if (context.GetPackageType() != PackageType::kStaticLib && 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"});

  // Turn off auto versioning for static-libs.
  if (context.GetPackageType() == PackageType::kStaticLib) {
    options_.no_auto_version = true;
    options_.no_version_vectors = true;
    options_.no_version_transitions = true;
  }

  Linker cmd(&context, options_);
  return cmd.Run(arg_list);
}

}  // namespace aapt
