/*
 * Copyright (C) 2016 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.
 */

#define ATRACE_TAG ATRACE_TAG_RESOURCES

#include "androidfw/LoadedArsc.h"

#include <algorithm>
#include <cstddef>
#include <limits>

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "utils/ByteOrder.h"
#include "utils/Trace.h"

#ifdef _WIN32
#ifdef ERROR
#undef ERROR
#endif
#endif

#include "androidfw/Chunk.h"
#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"

using android::base::StringPrintf;

namespace android {

constexpr const static int kFrameworkPackageId = 0x01;
constexpr const static int kAppPackageId = 0x7f;

namespace {

// Builder that helps accumulate Type structs and then create a single
// contiguous block of memory to store both the TypeSpec struct and
// the Type structs.
struct TypeSpecBuilder {
  explicit TypeSpecBuilder(incfs::verified_map_ptr<ResTable_typeSpec> header) : header_(header) {}

  void AddType(incfs::verified_map_ptr<ResTable_type> type) {
    TypeSpec::TypeEntry& entry = type_entries.emplace_back();
    entry.config.copyFromDtoH(type->config);
    entry.type = type;
  }

  TypeSpec Build() {
    return {header_, std::move(type_entries)};
  }

 private:
  DISALLOW_COPY_AND_ASSIGN(TypeSpecBuilder);

  incfs::verified_map_ptr<ResTable_typeSpec> header_;
  std::vector<TypeSpec::TypeEntry> type_entries;
};

}  // namespace

// Precondition: The header passed in has already been verified, so reading any fields and trusting
// the ResChunk_header is safe.
static bool VerifyResTableType(incfs::map_ptr<ResTable_type> header) {
  if (header->id == 0) {
    LOG(ERROR) << "RES_TABLE_TYPE_TYPE has invalid ID 0.";
    return false;
  }

  const size_t entry_count = dtohl(header->entryCount);
  if (entry_count > std::numeric_limits<uint16_t>::max()) {
    LOG(ERROR) << "RES_TABLE_TYPE_TYPE has too many entries (" << entry_count << ").";
    return false;
  }

  // Make sure that there is enough room for the entry offsets.
  const size_t offsets_offset = dtohs(header->header.headerSize);
  const size_t entries_offset = dtohl(header->entriesStart);
  const size_t offsets_length = sizeof(uint32_t) * entry_count;

  if (offsets_offset > entries_offset || entries_offset - offsets_offset < offsets_length) {
    LOG(ERROR) << "RES_TABLE_TYPE_TYPE entry offsets overlap actual entry data.";
    return false;
  }

  if (entries_offset > dtohl(header->header.size)) {
    LOG(ERROR) << "RES_TABLE_TYPE_TYPE entry offsets extend beyond chunk.";
    return false;
  }

  if (entries_offset & 0x03U) {
    LOG(ERROR) << "RES_TABLE_TYPE_TYPE entries start at unaligned address.";
    return false;
  }
  return true;
}

static base::expected<std::monostate, NullOrIOError> VerifyResTableEntry(
    incfs::verified_map_ptr<ResTable_type> type, uint32_t entry_offset) {
  // Check that the offset is aligned.
  if (UNLIKELY(entry_offset & 0x03U)) {
    LOG(ERROR) << "Entry at offset " << entry_offset << " is not 4-byte aligned.";
    return base::unexpected(std::nullopt);
  }

  // Check that the offset doesn't overflow.
  if (UNLIKELY(entry_offset > std::numeric_limits<uint32_t>::max() - dtohl(type->entriesStart))) {
    // Overflow in offset.
    LOG(ERROR) << "Entry at offset " << entry_offset << " is too large.";
    return base::unexpected(std::nullopt);
  }

  const size_t chunk_size = dtohl(type->header.size);

  entry_offset += dtohl(type->entriesStart);
  if (UNLIKELY(entry_offset > chunk_size - sizeof(ResTable_entry))) {
    LOG(ERROR) << "Entry at offset " << entry_offset
               << " is too large. No room for ResTable_entry.";
    return base::unexpected(std::nullopt);
  }

  auto entry = type.offset(entry_offset).convert<ResTable_entry>();
  if (UNLIKELY(!entry)) {
    return base::unexpected(IOError::PAGES_MISSING);
  }

  const size_t entry_size = dtohs(entry->size);
  if (UNLIKELY(entry_size < sizeof(entry.value()))) {
    LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
               << " is too small.";
    return base::unexpected(std::nullopt);
  }

  if (UNLIKELY(entry_size > chunk_size || entry_offset > chunk_size - entry_size)) {
    LOG(ERROR) << "ResTable_entry size " << entry_size << " at offset " << entry_offset
               << " is too large.";
    return base::unexpected(std::nullopt);
  }

  if (entry_size < sizeof(ResTable_map_entry)) {
    // There needs to be room for one Res_value struct.
    if (UNLIKELY(entry_offset + entry_size > chunk_size - sizeof(Res_value))) {
      LOG(ERROR) << "No room for Res_value after ResTable_entry at offset " << entry_offset
                 << " for type " << (int)type->id << ".";
      return base::unexpected(std::nullopt);
    }

    auto value = entry.offset(entry_size).convert<Res_value>();
    if (UNLIKELY(!value)) {
       return base::unexpected(IOError::PAGES_MISSING);
    }

    const size_t value_size = dtohs(value->size);
    if (UNLIKELY(value_size < sizeof(Res_value))) {
      LOG(ERROR) << "Res_value at offset " << entry_offset << " is too small.";
      return base::unexpected(std::nullopt);
    }

    if (UNLIKELY(value_size > chunk_size || entry_offset + entry_size > chunk_size - value_size)) {
      LOG(ERROR) << "Res_value size " << value_size << " at offset " << entry_offset
                 << " is too large.";
      return base::unexpected(std::nullopt);
    }
  } else {
    auto map = entry.convert<ResTable_map_entry>();
    if (UNLIKELY(!map)) {
      return base::unexpected(IOError::PAGES_MISSING);
    }

    const size_t map_entry_count = dtohl(map->count);
    size_t map_entries_start = entry_offset + entry_size;
    if (UNLIKELY(map_entries_start & 0x03U)) {
      LOG(ERROR) << "Map entries at offset " << entry_offset << " start at unaligned offset.";
      return base::unexpected(std::nullopt);
    }

    // Each entry is sizeof(ResTable_map) big.
    if (UNLIKELY(map_entry_count > ((chunk_size - map_entries_start) / sizeof(ResTable_map)))) {
      LOG(ERROR) << "Too many map entries in ResTable_map_entry at offset " << entry_offset << ".";
      return base::unexpected(std::nullopt);
    }
  }
  return {};
}

LoadedPackage::iterator::iterator(const LoadedPackage* lp, size_t ti, size_t ei)
    : loadedPackage_(lp),
      typeIndex_(ti),
      entryIndex_(ei),
      typeIndexEnd_(lp->resource_ids_.size() + 1) {
  while (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] == 0) {
    typeIndex_++;
  }
}

LoadedPackage::iterator& LoadedPackage::iterator::operator++() {
  while (typeIndex_ < typeIndexEnd_) {
    if (entryIndex_ + 1 < loadedPackage_->resource_ids_[typeIndex_]) {
      entryIndex_++;
      break;
    }
    entryIndex_ = 0;
    typeIndex_++;
    if (typeIndex_ < typeIndexEnd_ && loadedPackage_->resource_ids_[typeIndex_] != 0) {
      break;
    }
  }
  return *this;
}

uint32_t LoadedPackage::iterator::operator*() const {
  if (typeIndex_ >= typeIndexEnd_) {
    return 0;
  }
  return make_resid(loadedPackage_->package_id_, typeIndex_ + loadedPackage_->type_id_offset_,
          entryIndex_);
}

base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntry(
    incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index) {
  base::expected<uint32_t, NullOrIOError> entry_offset = GetEntryOffset(type_chunk, entry_index);
  if (UNLIKELY(!entry_offset.has_value())) {
    return base::unexpected(entry_offset.error());
  }
  return GetEntryFromOffset(type_chunk, entry_offset.value());
}

base::expected<uint32_t, NullOrIOError> LoadedPackage::GetEntryOffset(
    incfs::verified_map_ptr<ResTable_type> type_chunk, uint16_t entry_index) {
  // The configuration matches and is better than the previous selection.
  // Find the entry value if it exists for this configuration.
  const size_t entry_count = dtohl(type_chunk->entryCount);
  const size_t offsets_offset = dtohs(type_chunk->header.headerSize);

  // Check if there is the desired entry in this type.
  if (type_chunk->flags & ResTable_type::FLAG_SPARSE) {
    // This is encoded as a sparse map, so perform a binary search.
    bool error = false;
    auto sparse_indices = type_chunk.offset(offsets_offset)
                                    .convert<ResTable_sparseTypeEntry>().iterator();
    auto sparse_indices_end = sparse_indices + entry_count;
    auto result = std::lower_bound(sparse_indices, sparse_indices_end, entry_index,
                                   [&error](const incfs::map_ptr<ResTable_sparseTypeEntry>& entry,
                                            uint16_t entry_idx) {
      if (UNLIKELY(!entry)) {
        return error = true;
      }
      return dtohs(entry->idx) < entry_idx;
    });

    if (result == sparse_indices_end) {
      // No entry found.
      return base::unexpected(std::nullopt);
    }

    const incfs::verified_map_ptr<ResTable_sparseTypeEntry> entry = (*result).verified();
    if (dtohs(entry->idx) != entry_index) {
      if (error) {
        return base::unexpected(IOError::PAGES_MISSING);
      }
      return base::unexpected(std::nullopt);
    }

    // Extract the offset from the entry. Each offset must be a multiple of 4 so we store it as
    // the real offset divided by 4.
    return uint32_t{dtohs(entry->offset)} * 4u;
  }

  // This type is encoded as a dense array.
  if (entry_index >= entry_count) {
    // This entry cannot be here.
    return base::unexpected(std::nullopt);
  }

  const auto entry_offset_ptr = type_chunk.offset(offsets_offset).convert<uint32_t>() + entry_index;
  if (UNLIKELY(!entry_offset_ptr)) {
    return base::unexpected(IOError::PAGES_MISSING);
  }

  const uint32_t value = dtohl(entry_offset_ptr.value());
  if (value == ResTable_type::NO_ENTRY) {
    return base::unexpected(std::nullopt);
  }

  return value;
}

base::expected<incfs::map_ptr<ResTable_entry>, NullOrIOError> LoadedPackage::GetEntryFromOffset(
    incfs::verified_map_ptr<ResTable_type> type_chunk, uint32_t offset) {
  auto valid = VerifyResTableEntry(type_chunk, offset);
  if (UNLIKELY(!valid.has_value())) {
    return base::unexpected(valid.error());
  }
  return type_chunk.offset(offset + dtohl(type_chunk->entriesStart)).convert<ResTable_entry>();
}

base::expected<std::monostate, IOError> LoadedPackage::CollectConfigurations(
    bool exclude_mipmap, std::set<ResTable_config>* out_configs) const {\
  for (const auto& type_spec : type_specs_) {
    if (exclude_mipmap) {
      const int type_idx = type_spec.first - 1;
      const auto type_name16 = type_string_pool_.stringAt(type_idx);
      if (UNLIKELY(IsIOError(type_name16))) {
        return base::unexpected(GetIOError(type_name16.error()));
      }
      if (type_name16.has_value()) {
        if (strncmp16(type_name16->data(), u"mipmap", type_name16->size()) == 0) {
          // This is a mipmap type, skip collection.
          continue;
        }
      }

      const auto type_name = type_string_pool_.string8At(type_idx);
      if (UNLIKELY(IsIOError(type_name))) {
        return base::unexpected(GetIOError(type_name.error()));
      }
      if (type_name.has_value()) {
        if (strncmp(type_name->data(), "mipmap", type_name->size()) == 0) {
          // This is a mipmap type, skip collection.
          continue;
        }
      }
    }

    for (const auto& type_entry : type_spec.second.type_entries) {
      out_configs->insert(type_entry.config);
    }
  }
  return {};
}

void LoadedPackage::CollectLocales(bool canonicalize, std::set<std::string>* out_locales) const {
  char temp_locale[RESTABLE_MAX_LOCALE_LEN];
  for (const auto& type_spec : type_specs_) {
    for (const auto& type_entry : type_spec.second.type_entries) {
      if (type_entry.config.locale != 0) {
        type_entry.config.getBcp47Locale(temp_locale, canonicalize);
        std::string locale(temp_locale);
        out_locales->insert(std::move(locale));
      }
    }
  }
}

base::expected<uint32_t, NullOrIOError> LoadedPackage::FindEntryByName(
    const std::u16string& type_name, const std::u16string& entry_name) const {
  const base::expected<size_t, NullOrIOError> type_idx = type_string_pool_.indexOfString(
      type_name.data(), type_name.size());
  if (!type_idx.has_value()) {
    return base::unexpected(type_idx.error());
  }

  const base::expected<size_t, NullOrIOError> key_idx = key_string_pool_.indexOfString(
      entry_name.data(), entry_name.size());
  if (!key_idx.has_value()) {
    return base::unexpected(key_idx.error());
  }

  const TypeSpec* type_spec = GetTypeSpecByTypeIndex(*type_idx);
  if (type_spec == nullptr) {
    return base::unexpected(std::nullopt);
  }

  for (const auto& type_entry : type_spec->type_entries) {
    const incfs::verified_map_ptr<ResTable_type>& type = type_entry.type;

    size_t entry_count = dtohl(type->entryCount);
    for (size_t entry_idx = 0; entry_idx < entry_count; entry_idx++) {
      auto entry_offset_ptr = type.offset(dtohs(type->header.headerSize)).convert<uint32_t>() +
          entry_idx;
      if (!entry_offset_ptr) {
        return base::unexpected(IOError::PAGES_MISSING);
      }

      auto offset = dtohl(entry_offset_ptr.value());
      if (offset != ResTable_type::NO_ENTRY) {
        auto entry = type.offset(dtohl(type->entriesStart) + offset).convert<ResTable_entry>();
        if (!entry) {
          return base::unexpected(IOError::PAGES_MISSING);
        }

        if (dtohl(entry->key.index) == static_cast<uint32_t>(*key_idx)) {
          // The package ID will be overridden by the caller (due to runtime assignment of package
          // IDs for shared libraries).
          return make_resid(0x00, *type_idx + type_id_offset_ + 1, entry_idx);
        }
      }
    }
  }
  return base::unexpected(std::nullopt);
}

const LoadedPackage* LoadedArsc::GetPackageById(uint8_t package_id) const {
  for (const auto& loaded_package : packages_) {
    if (loaded_package->GetPackageId() == package_id) {
      return loaded_package.get();
    }
  }
  return nullptr;
}

std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk,
                                                         package_property_t property_flags) {
  ATRACE_NAME("LoadedPackage::Load");
  std::unique_ptr<LoadedPackage> loaded_package(new LoadedPackage());

  // typeIdOffset was added at some point, but we still must recognize apps built before this
  // was added.
  constexpr size_t kMinPackageSize =
      sizeof(ResTable_package) - sizeof(ResTable_package::typeIdOffset);
  const incfs::map_ptr<ResTable_package> header = chunk.header<ResTable_package, kMinPackageSize>();
  if (!header) {
    LOG(ERROR) << "RES_TABLE_PACKAGE_TYPE too small.";
    return {};
  }

  if ((property_flags & PROPERTY_SYSTEM) != 0) {
    loaded_package->property_flags_ |= PROPERTY_SYSTEM;
  }

  if ((property_flags & PROPERTY_LOADER) != 0) {
    loaded_package->property_flags_ |= PROPERTY_LOADER;
  }

  if ((property_flags & PROPERTY_OVERLAY) != 0) {
    // Overlay resources must have an exclusive resource id space for referencing internal
    // resources.
    loaded_package->property_flags_ |= PROPERTY_OVERLAY | PROPERTY_DYNAMIC;
  }

  loaded_package->package_id_ = dtohl(header->id);
  if (loaded_package->package_id_ == 0 ||
      (loaded_package->package_id_ == kAppPackageId && (property_flags & PROPERTY_DYNAMIC) != 0)) {
    loaded_package->property_flags_ |= PROPERTY_DYNAMIC;
  }

  if (header->header.headerSize >= sizeof(ResTable_package)) {
    uint32_t type_id_offset = dtohl(header->typeIdOffset);
    if (type_id_offset > std::numeric_limits<uint8_t>::max()) {
      LOG(ERROR) << "RES_TABLE_PACKAGE_TYPE type ID offset too large.";
      return {};
    }
    loaded_package->type_id_offset_ = static_cast<int>(type_id_offset);
  }

  util::ReadUtf16StringFromDevice(header->name, arraysize(header->name),
                                  &loaded_package->package_name_);

  // A map of TypeSpec builders, each associated with an type index.
  // We use these to accumulate the set of Types available for a TypeSpec, and later build a single,
  // contiguous block of memory that holds all the Types together with the TypeSpec.
  std::unordered_map<int, std::unique_ptr<TypeSpecBuilder>> type_builder_map;

  ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
  while (iter.HasNext()) {
    const Chunk child_chunk = iter.Next();
    switch (child_chunk.type()) {
      case RES_STRING_POOL_TYPE: {
        const auto pool_address = child_chunk.header<ResChunk_header>();
        if (!pool_address) {
          LOG(ERROR) << "RES_STRING_POOL_TYPE is incomplete due to incremental installation.";
          return {};
        }

        if (pool_address == header.offset(dtohl(header->typeStrings)).convert<ResChunk_header>()) {
          // This string pool is the type string pool.
          status_t err = loaded_package->type_string_pool_.setTo(
              child_chunk.header<ResStringPool_header>(), child_chunk.size());
          if (err != NO_ERROR) {
            LOG(ERROR) << "RES_STRING_POOL_TYPE for types corrupt.";
            return {};
          }
        } else if (pool_address == header.offset(dtohl(header->keyStrings))
                                         .convert<ResChunk_header>()) {
          // This string pool is the key string pool.
          status_t err = loaded_package->key_string_pool_.setTo(
              child_chunk.header<ResStringPool_header>(), child_chunk.size());
          if (err != NO_ERROR) {
            LOG(ERROR) << "RES_STRING_POOL_TYPE for keys corrupt.";
            return {};
          }
        } else {
          LOG(WARNING) << "Too many RES_STRING_POOL_TYPEs found in RES_TABLE_PACKAGE_TYPE.";
        }
      } break;

      case RES_TABLE_TYPE_SPEC_TYPE: {
        const auto type_spec = child_chunk.header<ResTable_typeSpec>();
        if (!type_spec) {
          LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small.";
          return {};
        }

        if (type_spec->id == 0) {
          LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE has invalid ID 0.";
          return {};
        }

        if (loaded_package->type_id_offset_ + static_cast<int>(type_spec->id) >
            std::numeric_limits<uint8_t>::max()) {
          LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE has out of range ID.";
          return {};
        }

        // The data portion of this chunk contains entry_count 32bit entries,
        // each one representing a set of flags.
        // Here we only validate that the chunk is well formed.
        const size_t entry_count = dtohl(type_spec->entryCount);

        // There can only be 2^16 entries in a type, because that is the ID
        // space for entries (EEEE) in the resource ID 0xPPTTEEEE.
        if (entry_count > std::numeric_limits<uint16_t>::max()) {
          LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE has too many entries (" << entry_count << ").";
          return {};
        }

        if (entry_count * sizeof(uint32_t) > chunk.data_size()) {
          LOG(ERROR) << "RES_TABLE_TYPE_SPEC_TYPE too small to hold entries.";
          return {};
        }

        std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type_spec->id];
        if (builder_ptr == nullptr) {
          builder_ptr = util::make_unique<TypeSpecBuilder>(type_spec.verified());
          loaded_package->resource_ids_.set(type_spec->id, entry_count);
        } else {
          LOG(WARNING) << StringPrintf("RES_TABLE_TYPE_SPEC_TYPE already defined for ID %02x",
                                       type_spec->id);
        }
      } break;

      case RES_TABLE_TYPE_TYPE: {
        const auto type = child_chunk.header<ResTable_type, kResTableTypeMinSize>();
        if (!type) {
          LOG(ERROR) << "RES_TABLE_TYPE_TYPE too small.";
          return {};
        }

        if (!VerifyResTableType(type)) {
          return {};
        }

        // Type chunks must be preceded by their TypeSpec chunks.
        std::unique_ptr<TypeSpecBuilder>& builder_ptr = type_builder_map[type->id];
        if (builder_ptr != nullptr) {
          builder_ptr->AddType(type.verified());
        } else {
          LOG(ERROR) << StringPrintf(
              "RES_TABLE_TYPE_TYPE with ID %02x found without preceding RES_TABLE_TYPE_SPEC_TYPE.",
              type->id);
          return {};
        }
      } break;

      case RES_TABLE_LIBRARY_TYPE: {
        const auto lib = child_chunk.header<ResTable_lib_header>();
        if (!lib) {
          LOG(ERROR) << "RES_TABLE_LIBRARY_TYPE too small.";
          return {};
        }

        if (child_chunk.data_size() / sizeof(ResTable_lib_entry) < dtohl(lib->count)) {
          LOG(ERROR) << "RES_TABLE_LIBRARY_TYPE too small to hold entries.";
          return {};
        }

        loaded_package->dynamic_package_map_.reserve(dtohl(lib->count));

        const auto entry_begin = child_chunk.data_ptr().convert<ResTable_lib_entry>();
        const auto entry_end = entry_begin + dtohl(lib->count);
        for (auto entry_iter = entry_begin; entry_iter != entry_end; ++entry_iter) {
          if (!entry_iter) {
            return {};
          }

          std::string package_name;
          util::ReadUtf16StringFromDevice(entry_iter->packageName,
                                          arraysize(entry_iter->packageName), &package_name);

          if (dtohl(entry_iter->packageId) >= std::numeric_limits<uint8_t>::max()) {
            LOG(ERROR) << StringPrintf(
                "Package ID %02x in RES_TABLE_LIBRARY_TYPE too large for package '%s'.",
                dtohl(entry_iter->packageId), package_name.c_str());
            return {};
          }

          loaded_package->dynamic_package_map_.emplace_back(std::move(package_name),
                                                            dtohl(entry_iter->packageId));
        }
      } break;

      case RES_TABLE_OVERLAYABLE_TYPE: {
        const auto overlayable = child_chunk.header<ResTable_overlayable_header>();
        if (!overlayable) {
          LOG(ERROR) << "RES_TABLE_OVERLAYABLE_TYPE too small.";
          return {};
        }

        std::string name;
        util::ReadUtf16StringFromDevice(overlayable->name, arraysize(overlayable->name), &name);
        std::string actor;
        util::ReadUtf16StringFromDevice(overlayable->actor, arraysize(overlayable->actor), &actor);

        if (loaded_package->overlayable_map_.find(name) !=
            loaded_package->overlayable_map_.end()) {
          LOG(ERROR) << "Multiple <overlayable> blocks with the same name '" << name << "'.";
          return {};
        }
        loaded_package->overlayable_map_.emplace(name, actor);

        // Iterate over the overlayable policy chunks contained within the overlayable chunk data
        ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size());
        while (overlayable_iter.HasNext()) {
          const Chunk overlayable_child_chunk = overlayable_iter.Next();

          switch (overlayable_child_chunk.type()) {
            case RES_TABLE_OVERLAYABLE_POLICY_TYPE: {
              const auto policy_header =
                  overlayable_child_chunk.header<ResTable_overlayable_policy_header>();
              if (!policy_header) {
                LOG(ERROR) << "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small.";
                return {};
              }

              if ((overlayable_child_chunk.data_size() / sizeof(ResTable_ref))
                  < dtohl(policy_header->entry_count)) {
                LOG(ERROR) <<  "RES_TABLE_OVERLAYABLE_POLICY_TYPE too small to hold entries.";
                return {};
              }

              // Retrieve all the resource ids belonging to this policy chunk
              std::unordered_set<uint32_t> ids;
              const auto ids_begin = overlayable_child_chunk.data_ptr().convert<ResTable_ref>();
              const auto ids_end = ids_begin + dtohl(policy_header->entry_count);
              for (auto id_iter = ids_begin; id_iter != ids_end; ++id_iter) {
                if (!id_iter) {
                  return {};
                }
                ids.insert(dtohl(id_iter->ident));
              }

              // Add the pairing of overlayable properties and resource ids to the package
              OverlayableInfo overlayable_info{};
              overlayable_info.name = name;
              overlayable_info.actor = actor;
              overlayable_info.policy_flags = policy_header->policy_flags;
              loaded_package->overlayable_infos_.emplace_back(overlayable_info, ids);
              loaded_package->defines_overlayable_ = true;
              break;
            }

            default:
              LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
              break;
          }
        }

        if (overlayable_iter.HadError()) {
          LOG(ERROR) << StringPrintf("Error parsing RES_TABLE_OVERLAYABLE_TYPE: %s",
                                     overlayable_iter.GetLastError().c_str());
          if (overlayable_iter.HadFatalError()) {
            return {};
          }
        }
      } break;

      case RES_TABLE_STAGED_ALIAS_TYPE: {
        if (loaded_package->package_id_ != kFrameworkPackageId) {
          LOG(WARNING) << "Alias chunk ignored for non-framework package '"
                       << loaded_package->package_name_ << "'";
          break;
        }

        std::unordered_set<uint32_t> finalized_ids;
        const auto lib_alias = child_chunk.header<ResTable_staged_alias_header>();
        if (!lib_alias) {
          LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small.";
          return {};
        }
        if ((child_chunk.data_size() / sizeof(ResTable_staged_alias_entry))
            < dtohl(lib_alias->count)) {
          LOG(ERROR) << "RES_TABLE_STAGED_ALIAS_TYPE is too small to hold entries.";
          return {};
        }
        const auto entry_begin = child_chunk.data_ptr().convert<ResTable_staged_alias_entry>();
        const auto entry_end = entry_begin + dtohl(lib_alias->count);
        for (auto entry_iter = entry_begin; entry_iter != entry_end; ++entry_iter) {
          if (!entry_iter) {
            return {};
          }
          auto finalized_id = dtohl(entry_iter->finalizedResId);
          if (!finalized_ids.insert(finalized_id).second) {
            LOG(ERROR) << StringPrintf("Repeated finalized resource id '%08x' in staged aliases.",
                                       finalized_id);
            return {};
          }

          auto staged_id = dtohl(entry_iter->stagedResId);
          auto [_, success] = loaded_package->alias_id_map_.insert(std::make_pair(staged_id,
                                                                                  finalized_id));
          if (!success) {
            LOG(ERROR) << StringPrintf("Repeated staged resource id '%08x' in staged aliases.",
                                       staged_id);
            return {};
          }
        }
      } break;

      default:
        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
        break;
    }
  }

  if (iter.HadError()) {
    LOG(ERROR) << iter.GetLastError();
    if (iter.HadFatalError()) {
      return {};
    }
  }

  // Flatten and construct the TypeSpecs.
  for (auto& entry : type_builder_map) {
    TypeSpec type_spec = entry.second->Build();
    uint8_t type_id = static_cast<uint8_t>(entry.first);
    loaded_package->type_specs_[type_id] = std::move(type_spec);
  }

  return std::move(loaded_package);
}

bool LoadedArsc::LoadTable(const Chunk& chunk, const LoadedIdmap* loaded_idmap,
                           package_property_t property_flags) {
  incfs::map_ptr<ResTable_header> header = chunk.header<ResTable_header>();
  if (!header) {
    LOG(ERROR) << "RES_TABLE_TYPE too small.";
    return false;
  }

  if (loaded_idmap != nullptr) {
    global_string_pool_ = util::make_unique<OverlayStringPool>(loaded_idmap);
  }

  const size_t package_count = dtohl(header->packageCount);
  size_t packages_seen = 0;

  packages_.reserve(package_count);

  ChunkIterator iter(chunk.data_ptr(), chunk.data_size());
  while (iter.HasNext()) {
    const Chunk child_chunk = iter.Next();
    switch (child_chunk.type()) {
      case RES_STRING_POOL_TYPE:
        // Only use the first string pool. Ignore others.
        if (global_string_pool_->getError() == NO_INIT) {
          status_t err = global_string_pool_->setTo(child_chunk.header<ResStringPool_header>(),
                                                    child_chunk.size());
          if (err != NO_ERROR) {
            LOG(ERROR) << "RES_STRING_POOL_TYPE corrupt.";
            return false;
          }
        } else {
          LOG(WARNING) << "Multiple RES_STRING_POOL_TYPEs found in RES_TABLE_TYPE.";
        }
        break;

      case RES_TABLE_PACKAGE_TYPE: {
        if (packages_seen + 1 > package_count) {
          LOG(ERROR) << "More package chunks were found than the " << package_count
                     << " declared in the header.";
          return false;
        }
        packages_seen++;

        std::unique_ptr<const LoadedPackage> loaded_package =
            LoadedPackage::Load(child_chunk, property_flags);
        if (!loaded_package) {
          return false;
        }
        packages_.push_back(std::move(loaded_package));
      } break;

      default:
        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
        break;
    }
  }

  if (iter.HadError()) {
    LOG(ERROR) << iter.GetLastError();
    if (iter.HadFatalError()) {
      return false;
    }
  }
  return true;
}

std::unique_ptr<LoadedArsc> LoadedArsc::Load(incfs::map_ptr<void> data,
                                             const size_t length,
                                             const LoadedIdmap* loaded_idmap,
                                             const package_property_t property_flags) {
  ATRACE_NAME("LoadedArsc::Load");

  // Not using make_unique because the constructor is private.
  std::unique_ptr<LoadedArsc> loaded_arsc(new LoadedArsc());

  ChunkIterator iter(data, length);
  while (iter.HasNext()) {
    const Chunk chunk = iter.Next();
    switch (chunk.type()) {
      case RES_TABLE_TYPE:
        if (!loaded_arsc->LoadTable(chunk, loaded_idmap, property_flags)) {
          return {};
        }
        break;

      default:
        LOG(WARNING) << StringPrintf("Unknown chunk type '%02x'.", chunk.type());
        break;
    }
  }

  if (iter.HadError()) {
    LOG(ERROR) << iter.GetLastError();
    if (iter.HadFatalError()) {
      return {};
    }
  }

  return loaded_arsc;
}

std::unique_ptr<LoadedArsc> LoadedArsc::CreateEmpty() {
  return std::unique_ptr<LoadedArsc>(new LoadedArsc());
}

}  // namespace android
