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

#include <algorithm>
#include <iterator>
#include <map>
#include <set>
#include <span>

#include "android-base/logging.h"
#include "android-base/stringprintf.h"
#include "androidfw/ResourceTypes.h"
#include "androidfw/ResourceUtils.h"
#include "androidfw/Util.h"
#include "utils/ByteOrder.h"
#include "utils/Trace.h"

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

namespace android {

namespace {

using EntryValue = std::variant<Res_value, incfs::verified_map_ptr<ResTable_map_entry>>;

/* NOTE: table_entry has been verified in LoadedPackage::GetEntryFromOffset(),
 * and so access to ->value() and ->map_entry() are safe here
 */
base::expected<EntryValue, IOError> GetEntryValue(
    incfs::verified_map_ptr<ResTable_entry> table_entry) {
  const uint16_t entry_size = table_entry->size();

  // Check if the entry represents a bag value.
  if (entry_size >= sizeof(ResTable_map_entry) && table_entry->is_complex()) {
    return table_entry.convert<ResTable_map_entry>().verified();
  }

  return table_entry->value();
}

} // namespace

struct FindEntryResult {
  // The cookie representing the ApkAssets in which the value resides.
  ApkAssetsCookie cookie;

  // The value of the resource table entry. Either an android::Res_value for non-bag types or an
  // incfs::verified_map_ptr<ResTable_map_entry> for bag types.
  EntryValue entry;

  // The configuration for which the resulting entry was defined. This is already swapped to host
  // endianness.
  ResTable_config config;

  // The bitmask of configuration axis with which the resource value varies.
  uint32_t type_flags;

  // The dynamic package ID map for the package from which this resource came from.
  const DynamicRefTable* dynamic_ref_table;

  // The package name of the resource.
  const std::string* package_name;

  // The string pool reference to the type's name. This uses a different string pool than
  // the global string pool, but this is hidden from the caller.
  StringPoolRef type_string_ref;

  // The string pool reference to the entry's name. This uses a different string pool than
  // the global string pool, but this is hidden from the caller.
  StringPoolRef entry_string_ref;
};

AssetManager2::AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration) {
  configurations_.push_back(configuration);

  // Don't invalidate caches here as there's nothing cached yet.
  SetApkAssets(apk_assets, false);
}

AssetManager2::AssetManager2() {
  configurations_.resize(1);
}

bool AssetManager2::SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches) {
  BuildDynamicRefTable(apk_assets);
  RebuildFilterList();
  if (invalidate_caches) {
    InvalidateCaches(static_cast<uint32_t>(-1));
  }
  return true;
}

bool AssetManager2::SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets,
                                 bool invalidate_caches) {
  return SetApkAssets(ApkAssetsList(apk_assets.begin(), apk_assets.size()), invalidate_caches);
}

void AssetManager2::BuildDynamicRefTable(ApkAssetsList apk_assets) {
  auto op = StartOperation();

  apk_assets_.resize(apk_assets.size());
  for (size_t i = 0; i != apk_assets.size(); ++i) {
    apk_assets_[i].first = apk_assets[i];
    // Let's populate the locked assets right away as we're going to need them here later.
    apk_assets_[i].second = apk_assets[i];
  }

  package_groups_.clear();
  package_ids_.fill(0xff);

  // A mapping from path of apk assets that could be target packages of overlays to the runtime
  // package id of its first loaded package. Overlays currently can only override resources in the
  // first package in the target resource table.
  std::unordered_map<std::string_view, uint8_t> target_assets_package_ids;

  // Overlay resources are not directly referenced by an application so their resource ids
  // can change throughout the application's lifetime. Assign overlay package ids last.
  std::vector<const ApkAssets*> sorted_apk_assets;
  sorted_apk_assets.reserve(apk_assets.size());
  for (auto& asset : apk_assets) {
    sorted_apk_assets.push_back(asset.get());
  }
  std::stable_partition(sorted_apk_assets.begin(), sorted_apk_assets.end(),
                        [](auto a) { return !a->IsOverlay(); });

  // The assets cookie must map to the position of the apk assets in the unsorted apk assets list.
  std::unordered_map<const ApkAssets*, ApkAssetsCookie> apk_assets_cookies;
  apk_assets_cookies.reserve(apk_assets.size());
  for (size_t i = 0, n = apk_assets.size(); i < n; i++) {
    apk_assets_cookies[apk_assets[i].get()] = static_cast<ApkAssetsCookie>(i);
  }

  // 0x01 is reserved for the android package.
  int next_package_id = 0x02;
  for (const ApkAssets* apk_assets : sorted_apk_assets) {
    std::shared_ptr<OverlayDynamicRefTable> overlay_ref_table;
    if (auto loaded_idmap = apk_assets->GetLoadedIdmap(); loaded_idmap != nullptr) {
      // The target package must precede the overlay package in the apk assets paths in order
      // to take effect.
      auto iter = target_assets_package_ids.find(loaded_idmap->TargetApkPath());
      if (iter == target_assets_package_ids.end()) {
         LOG(INFO) << "failed to find target package for overlay "
                   << loaded_idmap->OverlayApkPath();
      } else {
        uint8_t target_package_id = iter->second;

        // Create a special dynamic reference table for the overlay to rewrite references to
        // overlay resources as references to the target resources they overlay.
        overlay_ref_table = std::make_shared<OverlayDynamicRefTable>(
            loaded_idmap->GetOverlayDynamicRefTable(target_package_id));

        // Add the overlay resource map to the target package's set of overlays.
        const uint8_t target_idx = package_ids_[target_package_id];
        CHECK(target_idx != 0xff) << "overlay target '" << loaded_idmap->TargetApkPath()
                                  << "'added to apk_assets_package_ids but does not have an"
                                  << " assigned package group";

        PackageGroup& target_package_group = package_groups_[target_idx];
        target_package_group.overlays_.push_back(
            ConfiguredOverlay{loaded_idmap->GetTargetResourcesMap(target_package_id,
                                                                  overlay_ref_table.get()),
                              apk_assets_cookies[apk_assets]});
      }
    }

    const LoadedArsc* loaded_arsc = apk_assets->GetLoadedArsc();
    for (const std::unique_ptr<const LoadedPackage>& package : loaded_arsc->GetPackages()) {
      // Get the package ID or assign one if a shared library.
      int package_id;
      if (package->IsDynamic()) {
        package_id = next_package_id++;
      } else {
        package_id = package->GetPackageId();
      }

      uint8_t idx = package_ids_[package_id];
      if (idx == 0xff) {
        // Add the mapping for package ID to index if not present.
        package_ids_[package_id] = idx = static_cast<uint8_t>(package_groups_.size());
        PackageGroup& new_group = package_groups_.emplace_back();

        if (overlay_ref_table != nullptr) {
          // If this package is from an overlay, use a dynamic reference table that can rewrite
          // overlay resource ids to their corresponding target resource ids.
          new_group.dynamic_ref_table = std::move(overlay_ref_table);
        }

        DynamicRefTable* ref_table = new_group.dynamic_ref_table.get();
        ref_table->mAssignedPackageId = package_id;
        ref_table->mAppAsLib = package->IsDynamic() && package->GetPackageId() == 0x7f;
      }

      // Add the package to the set of packages with the same ID.
      PackageGroup* package_group = &package_groups_[idx];
      package_group->packages_.emplace_back().loaded_package_ = package.get();
      package_group->cookies_.push_back(apk_assets_cookies[apk_assets]);

      // Add the package name -> build time ID mappings.
      for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
        String16 package_name(entry.package_name.c_str(), entry.package_name.size());
        package_group->dynamic_ref_table->mEntries.replaceValueFor(
            package_name, static_cast<uint8_t>(entry.package_id));
      }

      if (auto apk_assets_path = apk_assets->GetPath()) {
        // Overlay target ApkAssets must have been created using path based load apis.
        target_assets_package_ids.emplace(*apk_assets_path, package_id);
      }
    }
  }

  // Now assign the runtime IDs so that we have a build-time to runtime ID map.
  DynamicRefTable::AliasMap aliases;
  for (const auto& group : package_groups_) {
    const std::string& package_name = group.packages_[0].loaded_package_->GetPackageName();
    const auto name_16 = String16(package_name.c_str(), package_name.size());
    for (auto&& inner_group : package_groups_) {
      inner_group.dynamic_ref_table->addMapping(name_16,
                                                group.dynamic_ref_table->mAssignedPackageId);
    }

    for (const auto& package : group.packages_) {
      const auto& package_aliases = package.loaded_package_->GetAliasResourceIdMap();
      aliases.insert(aliases.end(), package_aliases.begin(), package_aliases.end());
    }
  }

  if (!aliases.empty()) {
    std::sort(aliases.begin(), aliases.end(), [](auto&& l, auto&& r) { return l.first < r.first; });

    // Add the alias resources to the dynamic reference table of every package group. Since
    // staging aliases can only be defined by the framework package (which is not a shared
    // library), the compile-time package id of the framework is the same across all packages
    // that compile against the framework.
    for (auto& group : std::span(package_groups_.data(), package_groups_.size() - 1)) {
      group.dynamic_ref_table->setAliases(aliases);
    }
    package_groups_.back().dynamic_ref_table->setAliases(std::move(aliases));
  }
}

void AssetManager2::DumpToLog() const {
  LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this);

  auto op = StartOperation();
  std::string list;
  for (size_t i = 0, s = apk_assets_.size(); i < s; ++i) {
    const auto& assets = GetApkAssets(i);
    base::StringAppendF(&list, "%s,", assets ? assets->GetDebugName().c_str() : "nullptr");
  }
  LOG(INFO) << "ApkAssets: " << list;

  list = "";
  for (size_t i = 0; i < package_ids_.size(); i++) {
    if (package_ids_[i] != 0xff) {
      base::StringAppendF(&list, "%02x -> %d, ", (int)i, package_ids_[i]);
    }
  }
  LOG(INFO) << "Package ID map: " << list;

  for (const auto& package_group: package_groups_) {
    list = "";
    for (const auto& package : package_group.packages_) {
      const LoadedPackage* loaded_package = package.loaded_package_;
      base::StringAppendF(&list, "%s(%02x%s), ", loaded_package->GetPackageName().c_str(),
                          loaded_package->GetPackageId(),
                          (loaded_package->IsDynamic() ? " dynamic" : ""));
    }
    LOG(INFO) << base::StringPrintf("PG (%02x): ",
                                    package_group.dynamic_ref_table->mAssignedPackageId)
              << list;

    for (size_t i = 0; i < 256; i++) {
      if (package_group.dynamic_ref_table->mLookupTable[i] != 0) {
        LOG(INFO) << base::StringPrintf("    e[0x%02x] -> 0x%02x", (uint8_t) i,
                                        package_group.dynamic_ref_table->mLookupTable[i]);
      }
    }
  }
}

const ResStringPool* AssetManager2::GetStringPoolForCookie(ApkAssetsCookie cookie) const {
  if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
    return nullptr;
  }
  auto op = StartOperation();
  const auto& assets = GetApkAssets(cookie);
  return assets ? assets->GetLoadedArsc()->GetStringPool() : nullptr;
}

const DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t package_id) const {
  if (package_id >= package_ids_.size()) {
    return nullptr;
  }

  const size_t idx = package_ids_[package_id];
  if (idx == 0xff) {
    return nullptr;
  }
  return package_groups_[idx].dynamic_ref_table.get();
}

std::shared_ptr<const DynamicRefTable> AssetManager2::GetDynamicRefTableForCookie(
    ApkAssetsCookie cookie) const {
  for (const PackageGroup& package_group : package_groups_) {
    for (const ApkAssetsCookie& package_cookie : package_group.cookies_) {
      if (package_cookie == cookie) {
        return package_group.dynamic_ref_table;
      }
    }
  }
  return nullptr;
}

const std::unordered_map<std::string, std::string>*
  AssetManager2::GetOverlayableMapForPackage(uint32_t package_id) const {

  if (package_id >= package_ids_.size()) {
    return nullptr;
  }

  const size_t idx = package_ids_[package_id];
  if (idx == 0xff) {
    return nullptr;
  }

  const PackageGroup& package_group = package_groups_[idx];
  if (package_group.packages_.empty()) {
    return nullptr;
  }

  const auto loaded_package = package_group.packages_[0].loaded_package_;
  return &loaded_package->GetOverlayableMap();
}

bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name,
                                            std::string* out) const {
  auto op = StartOperation();
  uint8_t package_id = 0U;
  for (size_t i = 0, s = apk_assets_.size(); i != s; ++i) {
    const auto& assets = GetApkAssets(i);
    if (!assets) {
      continue;
    }
    const LoadedArsc* loaded_arsc = assets->GetLoadedArsc();
    if (loaded_arsc == nullptr) {
      continue;
    }

    const auto& loaded_packages = loaded_arsc->GetPackages();
    if (loaded_packages.empty()) {
      continue;
    }

    const auto& loaded_package = loaded_packages[0];
    if (loaded_package->GetPackageName() == package_name) {
      package_id = GetAssignedPackageId(loaded_package.get());
      break;
    }
  }

  if (package_id == 0U) {
    ANDROID_LOG(ERROR) << base::StringPrintf("No package with name '%s", package_name.data());
    return false;
  }

  const size_t idx = package_ids_[package_id];
  if (idx == 0xff) {
    return false;
  }

  std::string output;
  for (const ConfiguredPackage& package : package_groups_[idx].packages_) {
    const LoadedPackage* loaded_package = package.loaded_package_;
    for (auto it = loaded_package->begin(); it != loaded_package->end(); it++) {
      const OverlayableInfo* info = loaded_package->GetOverlayableInfo(*it);
      if (info != nullptr) {
        auto res_name = GetResourceName(*it);
        if (!res_name.has_value()) {
          ANDROID_LOG(ERROR) << base::StringPrintf(
              "Unable to retrieve name of overlayable resource 0x%08x", *it);
          return false;
        }

        const std::string name = ToFormattedResourceString(*res_name);
        output.append(base::StringPrintf(
            "resource='%s' overlayable='%s' actor='%s' policy='0x%08x'\n",
            name.c_str(), info->name.data(), info->actor.data(), info->policy_flags));
      }
    }
  }

  *out = std::move(output);
  return true;
}

bool AssetManager2::ContainsAllocatedTable() const {
  auto op = StartOperation();
  for (size_t i = 0, s = apk_assets_.size(); i != s; ++i) {
    const auto& assets = GetApkAssets(i);
    if (assets && assets->IsTableAllocated()) {
      return true;
    }
  }
  return false;
}

void AssetManager2::SetConfigurations(std::vector<ResTable_config> configurations) {
  int diff = 0;
  if (configurations_.size() != configurations.size()) {
    diff = -1;
  } else {
    for (int i = 0; i < configurations_.size(); i++) {
      diff |= configurations_[i].diff(configurations[i]);
    }
  }
  configurations_ = std::move(configurations);

  if (diff) {
    RebuildFilterList();
    InvalidateCaches(static_cast<uint32_t>(diff));
  }
}

std::set<AssetManager2::ApkAssetsPtr> AssetManager2::GetNonSystemOverlays() const {
  std::set<ApkAssetsPtr> non_system_overlays;
  for (const PackageGroup& package_group : package_groups_) {
    bool found_system_package = false;
    for (const ConfiguredPackage& package : package_group.packages_) {
      if (package.loaded_package_->IsSystem()) {
        found_system_package = true;
        break;
      }
    }

    if (!found_system_package) {
      auto op = StartOperation();
      for (const ConfiguredOverlay& overlay : package_group.overlays_) {
        if (const auto& asset = GetApkAssets(overlay.cookie)) {
          non_system_overlays.insert(std::move(asset));
        }
      }
    }
  }

  return non_system_overlays;
}

base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceConfigurations(
    bool exclude_system, bool exclude_mipmap) const {
  ATRACE_NAME("AssetManager::GetResourceConfigurations");
  auto op = StartOperation();

  const auto non_system_overlays =
      exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>();

  std::set<ResTable_config> configurations;
  for (const PackageGroup& package_group : package_groups_) {
    for (size_t i = 0; i < package_group.packages_.size(); i++) {
      const ConfiguredPackage& package = package_group.packages_[i];
      if (exclude_system) {
        if (package.loaded_package_->IsSystem()) {
          continue;
        }
        if (!non_system_overlays.empty()) {
          // Exclude overlays that target only system resources.
          const auto& apk_assets = GetApkAssets(package_group.cookies_[i]);
          if (apk_assets && apk_assets->IsOverlay() &&
              non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
            continue;
          }
        }
      }

      auto result = package.loaded_package_->CollectConfigurations(exclude_mipmap, &configurations);
      if (UNLIKELY(!result.has_value())) {
        return base::unexpected(result.error());
      }
    }
  }
  return configurations;
}

std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
                                                        bool merge_equivalent_languages) const {
  ATRACE_NAME("AssetManager::GetResourceLocales");
  auto op = StartOperation();

  std::set<std::string> locales;
  const auto non_system_overlays =
      exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>();

  for (const PackageGroup& package_group : package_groups_) {
    for (size_t i = 0; i < package_group.packages_.size(); i++) {
      const ConfiguredPackage& package = package_group.packages_[i];
      if (exclude_system) {
        if (package.loaded_package_->IsSystem()) {
          continue;
        }
        if (!non_system_overlays.empty()) {
          // Exclude overlays that target only system resources.
          const auto& apk_assets = GetApkAssets(package_group.cookies_[i]);
          if (apk_assets && apk_assets->IsOverlay() &&
              non_system_overlays.find(apk_assets) == non_system_overlays.end()) {
            continue;
          }
        }
      }

      package.loaded_package_->CollectLocales(merge_equivalent_languages, &locales);
    }
  }
  return locales;
}

std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename,
                                           Asset::AccessMode mode) const {
  const std::string new_path = "assets/" + filename;
  return OpenNonAsset(new_path, mode);
}

std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAssetsCookie cookie,
                                           Asset::AccessMode mode) const {
  const std::string new_path = "assets/" + filename;
  return OpenNonAsset(new_path, cookie, mode);
}

std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const {
  ATRACE_NAME("AssetManager::OpenDir");
  auto op = StartOperation();

  std::string full_path = "assets/" + dirname;
  auto files = util::make_unique<SortedVector<AssetDir::FileInfo>>();

  // Start from the back.
  for (size_t i = apk_assets_.size(); i > 0; --i) {
    const auto& apk_assets = GetApkAssets(i - 1);
    if (!apk_assets || apk_assets->IsOverlay()) {
      continue;
    }

    auto func = [&](StringPiece name, FileType type) {
      AssetDir::FileInfo info;
      info.setFileName(String8(name.data(), name.size()));
      info.setFileType(type);
      info.setSourceName(String8(apk_assets->GetDebugName().c_str()));
      files->add(info);
    };

    if (!apk_assets->GetAssetsProvider()->ForEachFile(full_path, func)) {
      return {};
    }
  }

  std::unique_ptr<AssetDir> asset_dir = util::make_unique<AssetDir>();
  asset_dir->setFileList(files.release());
  return asset_dir;
}

// Search in reverse because that's how we used to do it and we need to preserve behaviour.
// This is unfortunate, because ClassLoaders delegate to the parent first, so the order
// is inconsistent for split APKs.
std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
                                                   Asset::AccessMode mode,
                                                   ApkAssetsCookie* out_cookie) const {
  auto op = StartOperation();
  for (size_t i = apk_assets_.size(); i > 0; i--) {
    const auto& assets = GetApkAssets(i - 1);
    // Prevent RRO from modifying assets and other entries accessed by file
    // path. Explicitly asking for a path in a given package (denoted by a
    // cookie) is still OK.
    if (!assets || assets->IsOverlay()) {
      continue;
    }

    std::unique_ptr<Asset> asset = assets->GetAssetsProvider()->Open(filename, mode);
    if (asset) {
      if (out_cookie != nullptr) {
        *out_cookie = i;
      }
      return asset;
    }
  }

  if (out_cookie != nullptr) {
    *out_cookie = kInvalidCookie;
  }
  return {};
}

std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
                                                   ApkAssetsCookie cookie,
                                                   Asset::AccessMode mode) const {
  if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
    return {};
  }
  auto op = StartOperation();
  const auto& assets = GetApkAssets(cookie);
  return assets ? assets->GetAssetsProvider()->Open(filename, mode) : nullptr;
}

base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry(
    uint32_t resid, uint16_t density_override, bool stop_at_first_match,
    bool ignore_configuration) const {
  const bool logging_enabled = resource_resolution_logging_enabled_;
  if (UNLIKELY(logging_enabled)) {
    // Clear the last logged resource resolution.
    ResetResourceResolution();
    last_resolution_.resid = resid;
  }

  auto op = StartOperation();


  // Retrieve the package group from the package id of the resource id.
  if (UNLIKELY(!is_valid_resid(resid))) {
    LOG(ERROR) << base::StringPrintf("Invalid resource ID 0x%08x.", resid);
    return base::unexpected(std::nullopt);
  }

  const uint32_t package_id = get_package_id(resid);
  const uint8_t type_idx = get_type_id(resid) - 1;
  const uint16_t entry_idx = get_entry_id(resid);
  uint8_t package_idx = package_ids_[package_id];
  if (UNLIKELY(package_idx == 0xff)) {
    ANDROID_LOG(ERROR) << base::StringPrintf("No package ID %02x found for resource ID 0x%08x.",
                                             package_id, resid);
    return base::unexpected(std::nullopt);
  }

  const PackageGroup& package_group = package_groups_[package_idx];
  std::optional<FindEntryResult> final_result;
  bool final_has_locale = false;
  bool final_overlaid = false;
  for (auto & config : configurations_) {
    // Might use this if density_override != 0.
    ResTable_config density_override_config;

    // Select our configuration or generate a density override configuration.
    const ResTable_config* desired_config = &config;
    if (density_override != 0 && density_override != config.density) {
      density_override_config = config;
      density_override_config.density = density_override;
      desired_config = &density_override_config;
    }

    auto result = FindEntryInternal(package_group, type_idx, entry_idx, *desired_config,
                                    stop_at_first_match, ignore_configuration);
    if (UNLIKELY(!result.has_value())) {
      return base::unexpected(result.error());
    }
    bool overlaid = false;
    if (!stop_at_first_match && !ignore_configuration) {
      const auto& assets = GetApkAssets(result->cookie);
      if (!assets) {
        ALOGE("Found expired ApkAssets #%d for resource ID 0x%08x.", result->cookie, resid);
        return base::unexpected(std::nullopt);
      }
      if (!assets->IsLoader()) {
        for (const auto& id_map : package_group.overlays_) {
          auto overlay_entry = id_map.overlay_res_maps_.Lookup(resid);
          if (!overlay_entry) {
            // No id map entry exists for this target resource.
            continue;
          }
          if (overlay_entry.IsInlineValue()) {
            // The target resource is overlaid by an inline value not represented by a resource.
            ConfigDescription best_frro_config;
            Res_value best_frro_value;
            bool frro_found = false;
            for( const auto& [config, value] : overlay_entry.GetInlineValue()) {
              if ((!frro_found || config.isBetterThan(best_frro_config, desired_config))
                  && config.match(*desired_config)) {
                frro_found = true;
                best_frro_config = config;
                best_frro_value = value;
              }
            }
            if (!frro_found) {
              continue;
            }
            result->entry = best_frro_value;
            result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();
            result->cookie = id_map.cookie;

            if (UNLIKELY(logging_enabled)) {
              last_resolution_.steps.push_back(Resolution::Step{
                  Resolution::Step::Type::OVERLAID_INLINE, result->cookie, String8()});
              if (auto path = assets->GetPath()) {
                const std::string overlay_path = path->data();
                if (IsFabricatedOverlay(overlay_path)) {
                  // FRRO don't have package name so we use the creating package here.
                  String8 frro_name = String8("FRRO");
                  // Get the first part of it since the expected one should be like
                  // {overlayPackageName}-{overlayName}-{4 alphanumeric chars}.frro
                  // under /data/resource-cache/.
                  const std::string name = overlay_path.substr(overlay_path.rfind('/') + 1);
                  const size_t end = name.find('-');
                  if (frro_name.size() != overlay_path.size() && end != std::string::npos) {
                    frro_name.append(base::StringPrintf(" created by %s",
                                                        name.substr(0 /* pos */,
                                                                    end).c_str()).c_str());
                  }
                  last_resolution_.best_package_name = frro_name;
                } else {
                  last_resolution_.best_package_name = result->package_name->c_str();
                }
              }
              overlaid = true;
            }
            continue;
          }

          auto overlay_result = FindEntry(overlay_entry.GetResourceId(), density_override,
                                          false /* stop_at_first_match */,
                                          false /* ignore_configuration */);
          if (UNLIKELY(IsIOError(overlay_result))) {
            return base::unexpected(overlay_result.error());
          }
          if (!overlay_result.has_value()) {
            continue;
          }

          if (!overlay_result->config.isBetterThan(result->config, desired_config)
              && overlay_result->config.compare(result->config) != 0) {
            // The configuration of the entry for the overlay must be equal to or better than the
            // target configuration to be chosen as the better value.
            continue;
          }

          result->cookie = overlay_result->cookie;
          result->entry = overlay_result->entry;
          result->config = overlay_result->config;
          result->dynamic_ref_table = id_map.overlay_res_maps_.GetOverlayDynamicRefTable();

          if (UNLIKELY(logging_enabled)) {
            last_resolution_.steps.push_back(
                Resolution::Step{Resolution::Step::Type::OVERLAID, overlay_result->cookie,
                                 overlay_result->config.toString()});
            last_resolution_.best_package_name =
                overlay_result->package_name->c_str();
            overlaid = true;
          }
        }
      }
    }

    bool has_locale = false;
    if (result->config.locale == 0) {
      if (default_locale_ != 0) {
        ResTable_config conf;
        conf.locale = default_locale_;
        // Since we know conf has a locale and only a locale, match will tell us if that locale
        // matches
        has_locale = conf.match(config);
      }
    } else {
      has_locale = true;
    }

    // if we don't have a result yet
    if (!final_result ||
        // or this config is better before the locale than the existing result
        result->config.isBetterThanBeforeLocale(final_result->config, desired_config) ||
        // or the existing config isn't better before locale and this one specifies a locale
        // whereas the existing one doesn't
        (!final_result->config.isBetterThanBeforeLocale(result->config, desired_config)
            && has_locale && !final_has_locale)) {
      final_result = result.value();
      final_overlaid = overlaid;
      final_has_locale = has_locale;
    }
  }

  if (UNLIKELY(logging_enabled)) {
    last_resolution_.cookie = final_result->cookie;
    last_resolution_.type_string_ref = final_result->type_string_ref;
    last_resolution_.entry_string_ref = final_result->entry_string_ref;
    last_resolution_.best_config_name = final_result->config.toString();
    if (!final_overlaid) {
      last_resolution_.best_package_name = final_result->package_name->c_str();
    }
  }

  return *final_result;
}

base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal(
    const PackageGroup& package_group, uint8_t type_idx, uint16_t entry_idx,
    const ResTable_config& desired_config, bool stop_at_first_match,
    bool ignore_configuration) const {
  const bool logging_enabled = resource_resolution_logging_enabled_;
  ApkAssetsCookie best_cookie = kInvalidCookie;
  const LoadedPackage* best_package = nullptr;
  incfs::verified_map_ptr<ResTable_type> best_type;
  const ResTable_config* best_config = nullptr;
  uint32_t best_offset = 0U;
  uint32_t type_flags = 0U;

  // If `desired_config` is not the same as the set configuration or the caller will accept a value
  // from any configuration, then we cannot use our filtered list of types since it only it contains
  // types matched to the set configuration.
  const bool use_filtered = !ignore_configuration && std::find_if(
      configurations_.begin(), configurations_.end(),
      [&desired_config](auto& value) { return &desired_config == &value; })
      != configurations_.end();
  const size_t package_count = package_group.packages_.size();
  for (size_t pi = 0; pi < package_count; pi++) {
    const ConfiguredPackage& loaded_package_impl = package_group.packages_[pi];
    const LoadedPackage* loaded_package = loaded_package_impl.loaded_package_;
    const ApkAssetsCookie cookie = package_group.cookies_[pi];

    // If the type IDs are offset in this package, we need to take that into account when searching
    // for a type.
    const TypeSpec* type_spec = loaded_package->GetTypeSpecByTypeIndex(type_idx);
    if (UNLIKELY(type_spec == nullptr)) {
      continue;
    }

    // Allow custom loader packages to overlay resource values with configurations equivalent to the
    // current best configuration.
    const bool package_is_loader = loaded_package->IsCustomLoader();

    auto entry_flags = type_spec->GetFlagsForEntryIndex(entry_idx);
    if (UNLIKELY(!entry_flags.has_value())) {
      return base::unexpected(entry_flags.error());
    }
    type_flags |= entry_flags.value();

    const FilteredConfigGroup& filtered_group = loaded_package_impl.filtered_configs_[type_idx];
    const size_t type_entry_count = (use_filtered) ? filtered_group.type_entries.size()
                                                   : type_spec->type_entries.size();
    for (size_t i = 0; i < type_entry_count; i++) {
      const TypeSpec::TypeEntry* type_entry = (use_filtered) ? filtered_group.type_entries[i]
                                                             : &type_spec->type_entries[i];

      // We can skip calling ResTable_config::match() if the caller does not care for the
      // configuration to match or if we're using the list of types that have already had their
      // configuration matched.
      const ResTable_config& this_config = type_entry->config;
      if (!(use_filtered || ignore_configuration || this_config.match(desired_config))) {
        continue;
      }

      Resolution::Step::Type resolution_type;
      if (best_config == nullptr) {
        resolution_type = Resolution::Step::Type::INITIAL;
      } else if (this_config.isBetterThan(*best_config, &desired_config)) {
        resolution_type = Resolution::Step::Type::BETTER_MATCH;
      } else if (package_is_loader && this_config.compare(*best_config) == 0) {
        resolution_type = Resolution::Step::Type::OVERLAID;
      } else {
        if (UNLIKELY(logging_enabled)) {
          last_resolution_.steps.push_back(Resolution::Step{Resolution::Step::Type::SKIPPED,
                                                            cookie, this_config.toString()});
        }
        continue;
      }

      // The configuration matches and is better than the previous selection.
      // Find the entry value if it exists for this configuration.
      const auto& type = type_entry->type;
      const auto offset = LoadedPackage::GetEntryOffset(type, entry_idx);
      if (UNLIKELY(IsIOError(offset))) {
        return base::unexpected(offset.error());
      }

      if (!offset.has_value()) {
        if (UNLIKELY(logging_enabled)) {
          last_resolution_.steps.push_back(Resolution::Step{Resolution::Step::Type::NO_ENTRY,
                                                            cookie, this_config.toString()});
        }
        continue;
      }

      best_cookie = cookie;
      best_package = loaded_package;
      best_type = type;
      best_config = &this_config;
      best_offset = offset.value();

      if (UNLIKELY(logging_enabled)) {
        last_resolution_.steps.push_back(Resolution::Step{resolution_type,
                                                          cookie, this_config.toString()});
      }

      // Any configuration will suffice, so break.
      if (stop_at_first_match) {
        break;
      }
    }
  }

  if (UNLIKELY(best_cookie == kInvalidCookie)) {
    return base::unexpected(std::nullopt);
  }

  auto best_entry_verified = LoadedPackage::GetEntryFromOffset(best_type, best_offset);
  if (!best_entry_verified.has_value()) {
    return base::unexpected(best_entry_verified.error());
  }

  const auto entry = GetEntryValue(*best_entry_verified);
  if (!entry.has_value()) {
    return base::unexpected(entry.error());
  }

  return FindEntryResult{
    .cookie = best_cookie,
    .entry = *entry,
    .config = *best_config,
    .type_flags = type_flags,
    .package_name = &best_package->GetPackageName(),
    .type_string_ref = StringPoolRef(best_package->GetTypeStringPool(), best_type->id - 1),
    .entry_string_ref = StringPoolRef(best_package->GetKeyStringPool(),
                                      (*best_entry_verified)->key()),
    .dynamic_ref_table = package_group.dynamic_ref_table.get(),
  };
}

void AssetManager2::ResetResourceResolution() const {
  last_resolution_ = Resolution{};
}

void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) {
  resource_resolution_logging_enabled_ = enabled;
  if (!enabled) {
    ResetResourceResolution();
  }
}

std::string AssetManager2::GetLastResourceResolution() const {
  if (!resource_resolution_logging_enabled_) {
    LOG(ERROR) << "Must enable resource resolution logging before getting path.";
    return {};
  }

  const ApkAssetsCookie cookie = last_resolution_.cookie;
  if (cookie == kInvalidCookie) {
    LOG(ERROR) << "AssetManager hasn't resolved a resource to read resolution path.";
    return {};
  }

  auto op = StartOperation();

  const uint32_t resid = last_resolution_.resid;
  const auto& assets = GetApkAssets(cookie);
  const auto package =
      assets ? assets->GetLoadedArsc()->GetPackageById(get_package_id(resid)) : nullptr;

  std::string resource_name_string;
  if (package != nullptr) {
    auto resource_name = ToResourceName(last_resolution_.type_string_ref,
                                        last_resolution_.entry_string_ref,
                                        package->GetPackageName());
    resource_name_string = resource_name.has_value() ?
        ToFormattedResourceString(resource_name.value()) : "<unknown>";
  }

  std::stringstream log_stream;
  if (configurations_.size() == 1) {
    log_stream << base::StringPrintf("Resolution for 0x%08x %s\n"
                                     "\tFor config - %s", resid, resource_name_string.c_str(),
                                     configurations_[0].toString().c_str());
  } else {
    ResTable_config conf = configurations_[0];
    conf.clearLocale();
    log_stream << base::StringPrintf("Resolution for 0x%08x %s\n\tFor config - %s and locales",
                                     resid, resource_name_string.c_str(), conf.toString().c_str());
    char str[40];
    str[0] = '\0';
    for(auto iter = configurations_.begin(); iter < configurations_.end(); iter++) {
      iter->getBcp47Locale(str);
      log_stream << base::StringPrintf(" %s%s", str, iter < configurations_.end() ? "," : "");
    }
  }
  for (const Resolution::Step& step : last_resolution_.steps) {
    constexpr static std::array kStepStrings = {
        "Found initial",
        "Found better",
        "Overlaid",
        "Overlaid inline",
        "Skipped",
        "No entry"
    };

    if (step.type < Resolution::Step::Type::INITIAL
        || step.type > Resolution::Step::Type::NO_ENTRY) {
      continue;
    }
    const auto prefix = kStepStrings[int(step.type) - int(Resolution::Step::Type::INITIAL)];
    const auto& assets = GetApkAssets(step.cookie);
    log_stream << "\n\t" << prefix << ": " << (assets ? assets->GetDebugName() : "<null>")
               << " #" << step.cookie;
    if (!step.config_name.isEmpty()) {
      log_stream << " - " << step.config_name;
    }
  }

  log_stream << "\nBest matching is from "
             << (last_resolution_.best_config_name.isEmpty() ? "default"
                                                   : last_resolution_.best_config_name)
             << " configuration of " << last_resolution_.best_package_name;
  return log_stream.str();
}

base::expected<uint32_t, NullOrIOError> AssetManager2::GetParentThemeResourceId(uint32_t resid)
const {
  auto entry = FindEntry(resid, 0u /* density_override */,
                         false /* stop_at_first_match */,
                         false /* ignore_configuration */);
  if (!entry.has_value()) {
    return base::unexpected(entry.error());
  }

  auto entry_map = std::get_if<incfs::verified_map_ptr<ResTable_map_entry>>(&entry->entry);
  if (entry_map == nullptr) {
    // Not a bag, nothing to do.
    return base::unexpected(std::nullopt);
  }

  auto map = *entry_map;
  const uint32_t parent_resid = dtohl(map->parent.ident);

  return parent_resid;
}

base::expected<AssetManager2::ResourceName, NullOrIOError> AssetManager2::GetResourceName(
    uint32_t resid) const {
  auto result = FindEntry(resid, 0u /* density_override */, true /* stop_at_first_match */,
                          true /* ignore_configuration */);
  if (!result.has_value()) {
    return base::unexpected(result.error());
  }

  return ToResourceName(result->type_string_ref,
                        result->entry_string_ref,
                        *result->package_name);
}

base::expected<uint32_t, NullOrIOError> AssetManager2::GetResourceTypeSpecFlags(
    uint32_t resid) const {
  auto result = FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */,
                          true /* ignore_configuration */);
  if (!result.has_value()) {
    return base::unexpected(result.error());
  }
  return result->type_flags;
}

base::expected<AssetManager2::SelectedValue, NullOrIOError> AssetManager2::GetResource(
    uint32_t resid, bool may_be_bag, uint16_t density_override) const {
  auto result = FindEntry(resid, density_override, false /* stop_at_first_match */,
                          false /* ignore_configuration */);
  if (!result.has_value()) {
    return base::unexpected(result.error());
  }

  auto result_map_entry = std::get_if<incfs::verified_map_ptr<ResTable_map_entry>>(&result->entry);
  if (result_map_entry != nullptr) {
    if (!may_be_bag) {
      LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
      return base::unexpected(std::nullopt);
    }

    // Create a reference since we can't represent this complex type as a Res_value.
    return SelectedValue(Res_value::TYPE_REFERENCE, resid, result->cookie, result->type_flags,
                         resid, result->config);
  }

  // Convert the package ID to the runtime assigned package ID.
  Res_value value = std::get<Res_value>(result->entry);
  result->dynamic_ref_table->lookupResourceValue(&value);

  return SelectedValue(value.dataType, value.data, result->cookie, result->type_flags,
                       resid, result->config);
}

base::expected<std::monostate, NullOrIOError> AssetManager2::ResolveReference(
    AssetManager2::SelectedValue& value, bool cache_value) const {
  if (value.type != Res_value::TYPE_REFERENCE || value.data == 0U) {
    // Not a reference. Nothing to do.
    return {};
  }

  const uint32_t original_flags = value.flags;
  const uint32_t original_resid = value.data;
  if (cache_value) {
    auto cached_value = cached_resolved_values_.find(value.data);
    if (cached_value != cached_resolved_values_.end()) {
      value = cached_value->second;
      value.flags |= original_flags;
      return {};
    }
  }

  uint32_t combined_flags = 0U;
  uint32_t resolve_resid = original_resid;
  constexpr const uint32_t kMaxIterations = 20;
  for (uint32_t i = 0U;; i++) {
    auto result = GetResource(resolve_resid, true /*may_be_bag*/);
    if (!result.has_value()) {
      value.resid = resolve_resid;
      return base::unexpected(result.error());
    }

    // If resource resolution fails, the value should be set to the last reference that was able to
    // be resolved successfully.
    value = *result;
    value.flags |= combined_flags;

    if (result->type != Res_value::TYPE_REFERENCE ||
        result->data == Res_value::DATA_NULL_UNDEFINED ||
        result->data == resolve_resid || i == kMaxIterations) {
      // This reference can't be resolved, so exit now and let the caller deal with it.
      if (cache_value) {
        cached_resolved_values_[original_resid] = value;
      }

      // Above value is cached without original_flags to ensure they don't get included in future
      // queries that hit the cache
      value.flags |= original_flags;
      return {};
    }

    combined_flags = result->flags;
    resolve_resid = result->data;
  }
}

base::expected<const std::vector<uint32_t>*, NullOrIOError> AssetManager2::GetBagResIdStack(
    uint32_t resid) const {
  auto [it, inserted] = cached_bag_resid_stacks_.try_emplace(resid);
  if (inserted) {
    // This is a new entry in the cache, need to populate it.
    if (auto maybe_bag = GetBag(resid, it->second); UNLIKELY(IsIOError(maybe_bag))) {
      cached_bag_resid_stacks_.erase(it);
      return base::unexpected(maybe_bag.error());
    }
  }
  return &it->second;
}

base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::ResolveBag(
    AssetManager2::SelectedValue& value) const {
  if (UNLIKELY(value.type != Res_value::TYPE_REFERENCE)) {
    return base::unexpected(std::nullopt);
  }

  auto bag = GetBag(value.data);
  if (bag.has_value()) {
    value.flags |= (*bag)->type_spec_flags;
  }
  return bag;
}

base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::GetBag(uint32_t resid) const {
  auto [resid_stacks_it, _] = cached_bag_resid_stacks_.try_emplace(resid);
  resid_stacks_it->second.clear();
  const auto bag = GetBag(resid, resid_stacks_it->second);
  if (UNLIKELY(IsIOError(bag))) {
    cached_bag_resid_stacks_.erase(resid_stacks_it);
    return base::unexpected(bag.error());
  }
  return bag;
}

base::expected<const ResolvedBag*, NullOrIOError> AssetManager2::GetBag(
    uint32_t resid, std::vector<uint32_t>& child_resids) const {
  if (auto cached_iter = cached_bags_.find(resid); cached_iter != cached_bags_.end()) {
    return cached_iter->second.get();
  }

  auto entry = FindEntry(resid, 0u /* density_override */, false /* stop_at_first_match */,
                         false /* ignore_configuration */);
  if (!entry.has_value()) {
    return base::unexpected(entry.error());
  }

  auto entry_map = std::get_if<incfs::verified_map_ptr<ResTable_map_entry>>(&entry->entry);
  if (entry_map == nullptr) {
    // Not a bag, nothing to do.
    return base::unexpected(std::nullopt);
  }

  auto map = *entry_map;
  auto map_entry = map.offset(dtohs(map->size)).convert<ResTable_map>();
  const auto map_entry_end = map_entry + dtohl(map->count);

  // Keep track of ids that have already been seen to prevent infinite loops caused by circular
  // dependencies between bags.
  child_resids.push_back(resid);

  uint32_t parent_resid = dtohl(map->parent.ident);
  if (parent_resid == 0U ||
      std::find(child_resids.begin(), child_resids.end(), parent_resid) != child_resids.end()) {
    // There is no parent or a circular parental dependency exist, meaning there is nothing to
    // inherit and we can do a simple copy of the entries in the map.
    const size_t entry_count = map_entry_end - map_entry;
    util::unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
        malloc(sizeof(ResolvedBag) + (entry_count * sizeof(ResolvedBag::Entry))))};

    bool sort_entries = false;
    for (auto new_entry = new_bag->entries; map_entry != map_entry_end; ++map_entry) {
      if (UNLIKELY(!map_entry)) {
        return base::unexpected(IOError::PAGES_MISSING);
      }

      uint32_t new_key = dtohl(map_entry->name.ident);
      if (!is_internal_resid(new_key)) {
        // Attributes, arrays, etc don't have a resource id as the name. They specify
        // other data, which would be wrong to change via a lookup.
        if (UNLIKELY(entry->dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR)) {
          LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
                                           resid);
          return base::unexpected(std::nullopt);
        }
      }

      new_entry->cookie = entry->cookie;
      new_entry->key = new_key;
      new_entry->key_pool = nullptr;
      new_entry->type_pool = nullptr;
      new_entry->style = resid;
      new_entry->value.copyFrom_dtoh(map_entry->value);
      status_t err = entry->dynamic_ref_table->lookupResourceValue(&new_entry->value);
      if (UNLIKELY(err != NO_ERROR)) {
        LOG(ERROR) << base::StringPrintf(
            "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.", new_entry->value.dataType,
            new_entry->value.data, new_key);
        return base::unexpected(std::nullopt);
      }

      sort_entries = sort_entries ||
          (new_entry != new_bag->entries && (new_entry->key < (new_entry - 1U)->key));
      ++new_entry;
    }

    if (sort_entries) {
      std::sort(new_bag->entries, new_bag->entries + entry_count,
                [](auto&& lhs, auto&& rhs) { return lhs.key < rhs.key; });
    }

    new_bag->type_spec_flags = entry->type_flags;
    new_bag->entry_count = static_cast<uint32_t>(entry_count);
    ResolvedBag* result = new_bag.get();
    cached_bags_[resid] = std::move(new_bag);
    return result;
  }

  // In case the parent is a dynamic reference, resolve it.
  entry->dynamic_ref_table->lookupResourceId(&parent_resid);

  // Get the parent and do a merge of the keys.
  const auto parent_bag = GetBag(parent_resid, child_resids);
  if (UNLIKELY(!parent_bag.has_value())) {
    // Failed to get the parent that should exist.
    LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid,
                                     resid);
    return base::unexpected(parent_bag.error());
  }

  // Create the max possible entries we can make. Once we construct the bag,
  // we will realloc to fit to size.
  const size_t max_count = (*parent_bag)->entry_count + dtohl(map->count);
  util::unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
      malloc(sizeof(ResolvedBag) + (max_count * sizeof(ResolvedBag::Entry))))};
  ResolvedBag::Entry* new_entry = new_bag->entries;

  const ResolvedBag::Entry* parent_entry = (*parent_bag)->entries;
  const ResolvedBag::Entry* const parent_entry_end = parent_entry + (*parent_bag)->entry_count;

  // The keys are expected to be in sorted order. Merge the two bags.
  bool sort_entries = false;
  while (map_entry != map_entry_end && parent_entry != parent_entry_end) {
    if (UNLIKELY(!map_entry)) {
      return base::unexpected(IOError::PAGES_MISSING);
    }

    uint32_t child_key = dtohl(map_entry->name.ident);
    if (!is_internal_resid(child_key)) {
      if (UNLIKELY(entry->dynamic_ref_table->lookupResourceId(&child_key) != NO_ERROR)) {
        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key,
                                         resid);
        return base::unexpected(std::nullopt);
      }
    }

    if (child_key <= parent_entry->key) {
      // Use the child key if it comes before the parent
      // or is equal to the parent (overrides).
      new_entry->cookie = entry->cookie;
      new_entry->key = child_key;
      new_entry->key_pool = nullptr;
      new_entry->type_pool = nullptr;
      new_entry->value.copyFrom_dtoh(map_entry->value);
      new_entry->style = resid;
      status_t err = entry->dynamic_ref_table->lookupResourceValue(&new_entry->value);
      if (UNLIKELY(err != NO_ERROR)) {
        LOG(ERROR) << base::StringPrintf(
            "Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.", new_entry->value.dataType,
            new_entry->value.data, child_key);
        return base::unexpected(std::nullopt);
      }
      ++map_entry;
    } else {
      // Take the parent entry as-is.
      memcpy(new_entry, parent_entry, sizeof(*new_entry));
    }

    sort_entries = sort_entries ||
        (new_entry != new_bag->entries && (new_entry->key < (new_entry - 1U)->key));
    if (child_key >= parent_entry->key) {
      // Move to the next parent entry if we used it or it was overridden.
      ++parent_entry;
    }
    // Increment to the next entry to fill.
    ++new_entry;
  }

  // Finish the child entries if they exist.
  while (map_entry != map_entry_end) {
    if (UNLIKELY(!map_entry)) {
      return base::unexpected(IOError::PAGES_MISSING);
    }

    uint32_t new_key = dtohl(map_entry->name.ident);
    if (!is_internal_resid(new_key)) {
      if (UNLIKELY(entry->dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR)) {
        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key,
                                         resid);
        return base::unexpected(std::nullopt);
      }
    }
    new_entry->cookie = entry->cookie;
    new_entry->key = new_key;
    new_entry->key_pool = nullptr;
    new_entry->type_pool = nullptr;
    new_entry->value.copyFrom_dtoh(map_entry->value);
    new_entry->style = resid;
    status_t err = entry->dynamic_ref_table->lookupResourceValue(&new_entry->value);
    if (UNLIKELY(err != NO_ERROR)) {
      LOG(ERROR) << base::StringPrintf("Failed to resolve value t=0x%02x d=0x%08x for key 0x%08x.",
                                       new_entry->value.dataType, new_entry->value.data, new_key);
      return base::unexpected(std::nullopt);
    }
    sort_entries = sort_entries ||
        (new_entry != new_bag->entries && (new_entry->key < (new_entry - 1U)->key));
    ++map_entry;
    ++new_entry;
  }

  // Finish the parent entries if they exist.
  if (parent_entry != parent_entry_end) {
    // Take the rest of the parent entries as-is.
    const size_t num_entries_to_copy = parent_entry_end - parent_entry;
    memcpy(new_entry, parent_entry, num_entries_to_copy * sizeof(*new_entry));
    new_entry += num_entries_to_copy;
  }

  // Resize the resulting array to fit.
  const size_t actual_count = new_entry - new_bag->entries;
  if (actual_count != max_count) {
    new_bag.reset(reinterpret_cast<ResolvedBag*>(realloc(
        new_bag.release(), sizeof(ResolvedBag) + (actual_count * sizeof(ResolvedBag::Entry)))));
  }

  if (sort_entries) {
    std::sort(new_bag->entries, new_bag->entries + actual_count,
              [](auto&& lhs, auto&& rhs) { return lhs.key < rhs.key; });
  }

  // Combine flags from the parent and our own bag.
  new_bag->type_spec_flags = entry->type_flags | (*parent_bag)->type_spec_flags;
  new_bag->entry_count = static_cast<uint32_t>(actual_count);
  ResolvedBag* result = new_bag.get();
  cached_bags_[resid] = std::move(new_bag);
  return result;
}

static bool Utf8ToUtf16(StringPiece str, std::u16string* out) {
  ssize_t len =
      utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str.data()), str.size(), false);
  if (len < 0) {
    return false;
  }
  out->resize(static_cast<size_t>(len));
  utf8_to_utf16(reinterpret_cast<const uint8_t*>(str.data()), str.size(), &*out->begin(),
                static_cast<size_t>(len + 1));
  return true;
}

base::expected<uint32_t, NullOrIOError> AssetManager2::GetResourceId(
    const std::string& resource_name, const std::string& fallback_type,
    const std::string& fallback_package) const {
  StringPiece package_name, type, entry;
  if (!ExtractResourceName(resource_name, &package_name, &type, &entry)) {
    return base::unexpected(std::nullopt);
  }

  if (entry.empty()) {
    return base::unexpected(std::nullopt);
  }

  if (package_name.empty()) {
    package_name = fallback_package;
  }

  if (type.empty()) {
    type = fallback_type;
  }

  std::u16string type16;
  if (!Utf8ToUtf16(type, &type16)) {
    return base::unexpected(std::nullopt);
  }

  std::u16string entry16;
  if (!Utf8ToUtf16(entry, &entry16)) {
    return base::unexpected(std::nullopt);
  }

  const StringPiece16 kAttr16 = u"attr";
  const static std::u16string kAttrPrivate16 = u"^attr-private";

  for (const PackageGroup& package_group : package_groups_) {
    for (const ConfiguredPackage& package_impl : package_group.packages_) {
      const LoadedPackage* package = package_impl.loaded_package_;
      if (package_name != package->GetPackageName()) {
        // All packages in the same group are expected to have the same package name.
        break;
      }

      base::expected<uint32_t, NullOrIOError> resid = package->FindEntryByName(type16, entry16);
      if (UNLIKELY(IsIOError(resid))) {
         return base::unexpected(resid.error());
       }

      if (!resid.has_value() && kAttr16 == type16) {
        // Private attributes in libraries (such as the framework) are sometimes encoded
        // under the type '^attr-private' in order to leave the ID space of public 'attr'
        // free for future additions. Check '^attr-private' for the same name.
        resid = package->FindEntryByName(kAttrPrivate16, entry16);
      }

      if (resid.has_value()) {
        return fix_package_id(*resid, package_group.dynamic_ref_table->mAssignedPackageId);
      }
    }
  }
  return base::unexpected(std::nullopt);
}

void AssetManager2::RebuildFilterList() {
  for (PackageGroup& group : package_groups_) {
    for (ConfiguredPackage& package : group.packages_) {
      package.filtered_configs_.forEachItem([](auto, auto& fcg) { fcg.type_entries.clear(); });
      // Create the filters here.
      package.loaded_package_->ForEachTypeSpec([&](const TypeSpec& type_spec, uint8_t type_id) {
        FilteredConfigGroup* group = nullptr;
        for (const auto& type_entry : type_spec.type_entries) {
          for (auto & config : configurations_) {
            if (type_entry.config.match(config)) {
              if (!group) {
                group = &package.filtered_configs_.editItemAt(type_id - 1);
              }
              group->type_entries.push_back(&type_entry);
              break;
            }
          }
        }
      });
      package.filtered_configs_.trimBuckets(
          [](const auto& fcg) { return fcg.type_entries.empty(); });
    }
  }
}

void AssetManager2::InvalidateCaches(uint32_t diff) {
  cached_bag_resid_stacks_.clear();

  if (diff == 0xffffffffu) {
    // Everything must go.
    cached_bags_.clear();
    return;
  }

  // Be more conservative with what gets purged. Only if the bag has other possible
  // variations with respect to what changed (diff) should we remove it.
  for (auto iter = cached_bags_.cbegin(); iter != cached_bags_.cend();) {
    if (diff & iter->second->type_spec_flags) {
      iter = cached_bags_.erase(iter);
    } else {
      ++iter;
    }
  }

  cached_resolved_values_.clear();
}

uint8_t AssetManager2::GetAssignedPackageId(const LoadedPackage* package) const {
  for (auto& package_group : package_groups_) {
    for (auto& package2 : package_group.packages_) {
      if (package2.loaded_package_ == package) {
        return package_group.dynamic_ref_table->mAssignedPackageId;
      }
    }
  }
  return 0;
}

std::unique_ptr<Theme> AssetManager2::NewTheme() {
  constexpr size_t kInitialReserveSize = 32;
  auto theme = std::unique_ptr<Theme>(new Theme(this));
  theme->keys_.reserve(kInitialReserveSize);
  theme->entries_.reserve(kInitialReserveSize);
  return theme;
}

void AssetManager2::ForEachPackage(base::function_ref<bool(const std::string&, uint8_t)> func,
                                   package_property_t excluded_property_flags) const {
  for (const PackageGroup& package_group : package_groups_) {
    const auto loaded_package = package_group.packages_.front().loaded_package_;
    if ((loaded_package->GetPropertyFlags() & excluded_property_flags) == 0U
        && !func(loaded_package->GetPackageName(),
                 package_group.dynamic_ref_table->mAssignedPackageId)) {
      return;
    }
  }
}

AssetManager2::ScopedOperation AssetManager2::StartOperation() const {
  ++number_of_running_scoped_operations_;
  return ScopedOperation(*this);
}

void AssetManager2::FinishOperation() const {
  if (number_of_running_scoped_operations_ < 1) {
    ALOGW("Invalid FinishOperation() call when there's none happening");
    return;
  }
  if (--number_of_running_scoped_operations_ == 0) {
    for (auto&& [_, assets] : apk_assets_) {
      assets.clear();
    }
  }
}

const AssetManager2::ApkAssetsPtr& AssetManager2::GetApkAssets(ApkAssetsCookie cookie) const {
  DCHECK(number_of_running_scoped_operations_ > 0) << "Must have an operation running";

  if (cookie < 0 || cookie >= apk_assets_.size()) {
    static const ApkAssetsPtr empty{};
    return empty;
  }
  auto& [wptr, res] = apk_assets_[cookie];
  if (!res) {
    res = wptr.promote();
  }
  return res;
}

Theme::Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) {
}

Theme::~Theme() = default;

struct Theme::Entry {
  ApkAssetsCookie cookie;
  uint32_t type_spec_flags;
  Res_value value;
};

base::expected<std::monostate, NullOrIOError> Theme::ApplyStyle(uint32_t resid, bool force) {
  ATRACE_NAME("Theme::ApplyStyle");

  auto bag = asset_manager_->GetBag(resid);
  if (!bag.has_value()) {
    return base::unexpected(bag.error());
  }

  // Merge the flags from this style.
  type_spec_flags_ |= (*bag)->type_spec_flags;

  for (auto it = begin(*bag); it != end(*bag); ++it) {
    const uint32_t attr_res_id = it->key;

    // If the resource ID passed in is not a style, the key can be some other identifier that is not
    // a resource ID. We should fail fast instead of operating with strange resource IDs.
    if (!is_valid_resid(attr_res_id)) {
      return base::unexpected(std::nullopt);
    }

    // DATA_NULL_EMPTY (@empty) is a valid resource value and DATA_NULL_UNDEFINED represents
    // an absence of a valid value.
    bool is_undefined = it->value.dataType == Res_value::TYPE_NULL &&
        it->value.data != Res_value::DATA_NULL_EMPTY;
    if (!force && is_undefined) {
      continue;
    }

    const auto key_it = std::lower_bound(keys_.begin(), keys_.end(), attr_res_id);
    const auto entry_it = entries_.begin() + (key_it - keys_.begin());
    if (key_it != keys_.end() && *key_it == attr_res_id) {
      if (is_undefined) {
        // DATA_NULL_UNDEFINED clears the value of the attribute in the theme only when `force` is
        // true.
        keys_.erase(key_it);
        entries_.erase(entry_it);
      } else if (force) {
        *entry_it = Entry{it->cookie, (*bag)->type_spec_flags, it->value};
      }
    } else {
      keys_.insert(key_it, attr_res_id);
      entries_.insert(entry_it, Entry{it->cookie, (*bag)->type_spec_flags, it->value});
    }
  }
  return {};
}

void Theme::Rebase(AssetManager2* am, const uint32_t* style_ids, const uint8_t* force,
                   size_t style_count) {
  ATRACE_NAME("Theme::Rebase");
  // Reset the entries without changing the vector capacity to prevent reallocations during
  // ApplyStyle.
  keys_.clear();
  entries_.clear();
  asset_manager_ = am;
  for (size_t i = 0; i < style_count; i++) {
    ApplyStyle(style_ids[i], force[i]);
  }
}

std::optional<AssetManager2::SelectedValue> Theme::GetAttribute(uint32_t resid) const {
  constexpr const uint32_t kMaxIterations = 20;
  uint32_t type_spec_flags = 0u;
  for (uint32_t i = 0; i <= kMaxIterations; i++) {
    const auto key_it = std::lower_bound(keys_.begin(), keys_.end(), resid);
    if (key_it == keys_.end() || *key_it != resid) {
      return std::nullopt;
    }
    const auto entry_it = entries_.begin() + (key_it - keys_.begin());
    type_spec_flags |= entry_it->type_spec_flags;
    if (entry_it->value.dataType == Res_value::TYPE_ATTRIBUTE) {
      resid = entry_it->value.data;
      continue;
    }

    return AssetManager2::SelectedValue(entry_it->value.dataType, entry_it->value.data,
                                        entry_it->cookie, type_spec_flags, 0U /* resid */,
                                        {} /* config */);
  }
  return std::nullopt;
}

base::expected<std::monostate, NullOrIOError> Theme::ResolveAttributeReference(
      AssetManager2::SelectedValue& value) const {
  if (value.type != Res_value::TYPE_ATTRIBUTE) {
    return asset_manager_->ResolveReference(value);
  }

  std::optional<AssetManager2::SelectedValue> result = GetAttribute(value.data);
  if (!result.has_value()) {
    return base::unexpected(std::nullopt);
  }

  auto resolve_result = asset_manager_->ResolveReference(*result, true /* cache_value */);
  if (resolve_result.has_value()) {
    result->flags |= value.flags;
    value = *result;
  }
  return resolve_result;
}

void Theme::Clear() {
  keys_.clear();
  entries_.clear();
}

base::expected<std::monostate, IOError> Theme::SetTo(const Theme& source) {
  if (this == &source) {
    return {};
  }

  type_spec_flags_ = source.type_spec_flags_;

  if (asset_manager_ == source.asset_manager_) {
    keys_ = source.keys_;
    entries_ = source.entries_;
  } else {
    std::unordered_map<ApkAssetsCookie, ApkAssetsCookie> src_to_dest_asset_cookies;
    using SourceToDestinationRuntimePackageMap = std::unordered_map<int, int>;
    std::unordered_map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map;

    auto op_src = source.asset_manager_->StartOperation();
    auto op_dst = asset_manager_->StartOperation();

    for (size_t i = 0; i < source.asset_manager_->GetApkAssetsCount(); i++) {
      const auto& src_asset = source.asset_manager_->GetApkAssets(i);
      if (!src_asset) {
        continue;
      }
      for (int j = 0; j < asset_manager_->GetApkAssetsCount(); j++) {
        const auto& dest_asset = asset_manager_->GetApkAssets(j);
        if (src_asset != dest_asset) {
          // ResourcesManager caches and reuses ApkAssets when the same apk must be present in
          // multiple AssetManagers. Two ApkAssets point to the same version of the same resources
          // if they are the same instance.
          continue;
        }

        // Map the package ids of the asset in the source AssetManager to the package ids of the
        // asset in th destination AssetManager.
        SourceToDestinationRuntimePackageMap package_map;
        for (const auto& loaded_package : src_asset->GetLoadedArsc()->GetPackages()) {
          const int src_package_id = source.asset_manager_->GetAssignedPackageId(
              loaded_package.get());
          const int dest_package_id = asset_manager_->GetAssignedPackageId(loaded_package.get());
          package_map[src_package_id] = dest_package_id;
        }

        src_to_dest_asset_cookies.insert(std::make_pair(i, j));
        src_asset_cookie_id_map.insert(std::make_pair(i, std::move(package_map)));
        break;
      }
    }

    // Reset the data in the destination theme.
    keys_.clear();
    entries_.clear();

    for (size_t i = 0, size = source.entries_.size(); i != size; ++i) {
      const auto& entry = source.entries_[i];
      bool is_reference = (entry.value.dataType == Res_value::TYPE_ATTRIBUTE
                           || entry.value.dataType == Res_value::TYPE_REFERENCE
                           || entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE
                           || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE)
                          && entry.value.data != 0x0;

      // If the attribute value represents an attribute or reference, the package id of the
      // value needs to be rewritten to the package id of the value in the destination.
      uint32_t attribute_data = entry.value.data;
      if (is_reference) {
        // Determine the package id of the reference in the destination AssetManager.
        auto value_package_map = src_asset_cookie_id_map.find(entry.cookie);
        if (value_package_map == src_asset_cookie_id_map.end()) {
          continue;
        }

        auto value_dest_package = value_package_map->second.find(
            get_package_id(entry.value.data));
        if (value_dest_package == value_package_map->second.end()) {
          continue;
        }

        attribute_data = fix_package_id(entry.value.data, value_dest_package->second);
      }

      // Find the cookie of the value in the destination. If the source apk is not loaded in the
      // destination, only copy resources that do not reference resources in the source.
      ApkAssetsCookie data_dest_cookie;
      auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie);
      if (value_dest_cookie != src_to_dest_asset_cookies.end()) {
        data_dest_cookie = value_dest_cookie->second;
      } else {
        if (is_reference || entry.value.dataType == Res_value::TYPE_STRING) {
          continue;
        } else {
          data_dest_cookie = 0x0;
        }
      }

      const auto source_res_id = source.keys_[i];

      // The package id of the attribute needs to be rewritten to the package id of the
      // attribute in the destination.
      int attribute_dest_package_id = get_package_id(source_res_id);
      if (attribute_dest_package_id != 0x01) {
        // Find the cookie of the attribute resource id in the source AssetManager
        base::expected<FindEntryResult, NullOrIOError> attribute_entry_result =
            source.asset_manager_->FindEntry(source_res_id, 0 /* density_override */ ,
                                             true /* stop_at_first_match */,
                                             true /* ignore_configuration */);
        if (UNLIKELY(IsIOError(attribute_entry_result))) {
          return base::unexpected(GetIOError(attribute_entry_result.error()));
        }
        if (!attribute_entry_result.has_value()) {
          continue;
        }

        // Determine the package id of the attribute in the destination AssetManager.
        auto attribute_package_map = src_asset_cookie_id_map.find(
            attribute_entry_result->cookie);
        if (attribute_package_map == src_asset_cookie_id_map.end()) {
          continue;
        }
        auto attribute_dest_package = attribute_package_map->second.find(
            attribute_dest_package_id);
        if (attribute_dest_package == attribute_package_map->second.end()) {
          continue;
        }
        attribute_dest_package_id = attribute_dest_package->second;
      }

      auto dest_attr_id = make_resid(attribute_dest_package_id, get_type_id(source_res_id),
                                     get_entry_id(source_res_id));
      const auto key_it = std::lower_bound(keys_.begin(), keys_.end(), dest_attr_id);
      const auto entry_it = entries_.begin() + (key_it - keys_.begin());
      // Since the entries were cleared, the attribute resource id has yet been mapped to any value.
      keys_.insert(key_it, dest_attr_id);
      entries_.insert(entry_it, Entry{data_dest_cookie, entry.type_spec_flags,
                                      Res_value{.dataType = entry.value.dataType,
                                                .data = attribute_data}});
    }
  }
  return {};
}

void Theme::Dump() const {
  LOG(INFO) << base::StringPrintf("Theme(this=%p, AssetManager2=%p)", this, asset_manager_);
  for (size_t i = 0, size = keys_.size(); i != size; ++i) {
    auto res_id = keys_[i];
    const auto& entry = entries_[i];
    LOG(INFO) << base::StringPrintf("  entry(0x%08x)=(0x%08x) type=(0x%02x), cookie(%d)",
                                    res_id, entry.value.data, entry.value.dataType,
                                    entry.cookie);
  }
}

AssetManager2::ScopedOperation::ScopedOperation(const AssetManager2& am) : am_(am) {
}

AssetManager2::ScopedOperation::~ScopedOperation() {
  am_.FinishOperation();
}

}  // namespace android
