17ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski/*
27ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Copyright (C) 2016 The Android Open Source Project
37ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *
47ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Licensed under the Apache License, Version 2.0 (the "License");
57ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * you may not use this file except in compliance with the License.
67ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * You may obtain a copy of the License at
77ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *
87ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *      http://www.apache.org/licenses/LICENSE-2.0
97ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski *
107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * Unless required by applicable law or agreed to in writing, software
117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * distributed under the License is distributed on an "AS IS" BASIS,
127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * See the License for the specific language governing permissions and
147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski * limitations under the License.
157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski */
167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#define ATRACE_TAG ATRACE_TAG_RESOURCES
187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "androidfw/AssetManager2.h"
207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
210c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski#include <set>
220c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "android-base/logging.h"
247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "android-base/stringprintf.h"
257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "utils/ByteOrder.h"
267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#include "utils/Trace.h"
277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#ifdef _WIN32
297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#ifdef ERROR
307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#undef ERROR
317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#endif
327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski#endif
337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
34929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski#include "androidfw/ResourceUtils.h"
35929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskinamespace android {
377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam LesinskiAssetManager2::AssetManager2() { memset(&configuration_, 0, sizeof(configuration_)); }
397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskibool AssetManager2::SetApkAssets(const std::vector<const ApkAssets*>& apk_assets,
417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                 bool invalidate_caches) {
427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  apk_assets_ = apk_assets;
43da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  BuildDynamicRefTable();
447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (invalidate_caches) {
457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    InvalidateCaches(static_cast<uint32_t>(-1));
467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return true;
487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
50da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskivoid AssetManager2::BuildDynamicRefTable() {
51da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  package_groups_.clear();
52da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  package_ids_.fill(0xff);
53da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
54da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // 0x01 is reserved for the android package.
55da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  int next_package_id = 0x02;
56da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const size_t apk_assets_count = apk_assets_.size();
57da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  for (size_t i = 0; i < apk_assets_count; i++) {
58da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    const ApkAssets* apk_asset = apk_assets_[i];
59da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    for (const std::unique_ptr<const LoadedPackage>& package :
60da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski         apk_asset->GetLoadedArsc()->GetPackages()) {
61da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      // Get the package ID or assign one if a shared library.
62da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      int package_id;
63da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      if (package->IsDynamic()) {
64da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        package_id = next_package_id++;
65da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      } else {
66da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        package_id = package->GetPackageId();
67da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
68da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
69da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      // Add the mapping for package ID to index if not present.
70da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      uint8_t idx = package_ids_[package_id];
71da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      if (idx == 0xff) {
72da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        package_ids_[package_id] = idx = static_cast<uint8_t>(package_groups_.size());
73da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        package_groups_.push_back({});
74da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        package_groups_.back().dynamic_ref_table.mAssignedPackageId = package_id;
75da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
76da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      PackageGroup* package_group = &package_groups_[idx];
77da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
78da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      // Add the package and to the set of packages with the same ID.
79da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      package_group->packages_.push_back(package.get());
80da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      package_group->cookies_.push_back(static_cast<ApkAssetsCookie>(i));
81da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
82da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      // Add the package name -> build time ID mappings.
83da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      for (const DynamicPackageEntry& entry : package->GetDynamicPackageMap()) {
84da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        String16 package_name(entry.package_name.c_str(), entry.package_name.size());
85da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        package_group->dynamic_ref_table.mEntries.replaceValueFor(
86da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski            package_name, static_cast<uint8_t>(entry.package_id));
87da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
88da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    }
89da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
90da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
91da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // Now assign the runtime IDs so that we have a build-time to runtime ID map.
92da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const auto package_groups_end = package_groups_.end();
93da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  for (auto iter = package_groups_.begin(); iter != package_groups_end; ++iter) {
94da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    const std::string& package_name = iter->packages_[0]->GetPackageName();
95da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    for (auto iter2 = package_groups_.begin(); iter2 != package_groups_end; ++iter2) {
96da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      iter2->dynamic_ref_table.addMapping(String16(package_name.c_str(), package_name.size()),
97da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski                                          iter->dynamic_ref_table.mAssignedPackageId);
98da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    }
99da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
100da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski}
101da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
102da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskivoid AssetManager2::DumpToLog() const {
103da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  base::ScopedLogSeverity _log(base::INFO);
104da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
105da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  std::string list;
106da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  for (size_t i = 0; i < package_ids_.size(); i++) {
107da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    if (package_ids_[i] != 0xff) {
108da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      base::StringAppendF(&list, "%02x -> %d, ", (int) i, package_ids_[i]);
109da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    }
110da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
111da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  LOG(INFO) << "Package ID map: " << list;
112da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
113da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  for (const auto& package_group: package_groups_) {
114da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      list = "";
115da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      for (const auto& package : package_group.packages_) {
116da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        base::StringAppendF(&list, "%s(%02x), ", package->GetPackageName().c_str(), package->GetPackageId());
117da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
118da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      LOG(INFO) << base::StringPrintf("PG (%02x): ", package_group.dynamic_ref_table.mAssignedPackageId) << list;
119da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
120da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski}
1217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiconst ResStringPool* AssetManager2::GetStringPoolForCookie(ApkAssetsCookie cookie) const {
1237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
1247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return nullptr;
1257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
1267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return apk_assets_[cookie]->GetLoadedArsc()->GetStringPool();
1277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
1287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
129da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinskiconst DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t package_id) const {
130da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  if (package_id >= package_ids_.size()) {
131da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    return nullptr;
132da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
133da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
134da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const size_t idx = package_ids_[package_id];
135da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  if (idx == 0xff) {
136da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    return nullptr;
137da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
138da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  return &package_groups_[idx].dynamic_ref_table;
139da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski}
140da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
141d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinskiconst DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const {
142d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  for (const PackageGroup& package_group : package_groups_) {
143d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    for (const ApkAssetsCookie& package_cookie : package_group.cookies_) {
144d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      if (package_cookie == cookie) {
145d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski        return &package_group.dynamic_ref_table;
146d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      }
147d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    }
148d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  }
149d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  return nullptr;
150d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski}
151d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
1527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskivoid AssetManager2::SetConfiguration(const ResTable_config& configuration) {
1537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const int diff = configuration_.diff(configuration);
1547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  configuration_ = configuration;
1557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (diff) {
1577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    InvalidateCaches(static_cast<uint32_t>(diff));
1587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
1597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
1607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1610c40524953f3d36a880f91183302a2ea5c722930Adam Lesinskistd::set<ResTable_config> AssetManager2::GetResourceConfigurations(bool exclude_system,
1620c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                                                                   bool exclude_mipmap) {
1630c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  ATRACE_CALL();
1640c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  std::set<ResTable_config> configurations;
1650c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  for (const PackageGroup& package_group : package_groups_) {
1660c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    for (const LoadedPackage* package : package_group.packages_) {
1670c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      if (exclude_system && package->IsSystem()) {
1680c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski        continue;
1690c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      }
1700c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      package->CollectConfigurations(exclude_mipmap, &configurations);
1710c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    }
1720c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  }
1730c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  return configurations;
1740c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski}
1750c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
1760c40524953f3d36a880f91183302a2ea5c722930Adam Lesinskistd::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system,
1770c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                                                        bool merge_equivalent_languages) {
1780c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  ATRACE_CALL();
1790c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  std::set<std::string> locales;
1800c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  for (const PackageGroup& package_group : package_groups_) {
1810c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    for (const LoadedPackage* package : package_group.packages_) {
1820c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      if (exclude_system && package->IsSystem()) {
1830c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski        continue;
1840c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      }
1850c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      package->CollectLocales(merge_equivalent_languages, &locales);
1860c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    }
1870c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  }
1880c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  return locales;
1890c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski}
1900c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
1917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistd::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, Asset::AccessMode mode) {
1927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const std::string new_path = "assets/" + filename;
1937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return OpenNonAsset(new_path, mode);
1947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
1957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
1967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistd::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAssetsCookie cookie,
1977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                           Asset::AccessMode mode) {
1987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const std::string new_path = "assets/" + filename;
1997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return OpenNonAsset(new_path, cookie, mode);
2007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
2017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
202d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinskistd::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) {
203d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  ATRACE_CALL();
204d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
205d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  std::string full_path = "assets/" + dirname;
206d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  std::unique_ptr<SortedVector<AssetDir::FileInfo>> files =
207d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      util::make_unique<SortedVector<AssetDir::FileInfo>>();
208d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
209d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  // Start from the back.
210d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) {
211d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    const ApkAssets* apk_assets = *iter;
212d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
213d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    auto func = [&](const StringPiece& name, FileType type) {
214d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      AssetDir::FileInfo info;
215d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      info.setFileName(String8(name.data(), name.size()));
216d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      info.setFileType(type);
217d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      info.setSourceName(String8(apk_assets->GetPath().c_str()));
218d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      files->add(info);
219d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    };
220d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
221d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    if (!apk_assets->ForEachFile(full_path, func)) {
222d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      return {};
223d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    }
224d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  }
225d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
226d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  std::unique_ptr<AssetDir> asset_dir = util::make_unique<AssetDir>();
227d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  asset_dir->setFileList(files.release());
228d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  return asset_dir;
229d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski}
230d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
2317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// Search in reverse because that's how we used to do it and we need to preserve behaviour.
2327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// This is unfortunate, because ClassLoaders delegate to the parent first, so the order
2337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski// is inconsistent for split APKs.
2347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistd::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
2357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                                   Asset::AccessMode mode,
2367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                                   ApkAssetsCookie* out_cookie) {
2377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ATRACE_CALL();
2387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) {
2397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    std::unique_ptr<Asset> asset = apk_assets_[i]->Open(filename, mode);
2407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (asset) {
2417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      if (out_cookie != nullptr) {
2427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        *out_cookie = i;
2437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      }
2447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return asset;
2457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
2467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
2477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
2487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (out_cookie != nullptr) {
2497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    *out_cookie = kInvalidCookie;
2507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
2517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return {};
2527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
2537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
2547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistd::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename,
2557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                                   ApkAssetsCookie cookie, Asset::AccessMode mode) {
2567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ATRACE_CALL();
2577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) {
2587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return {};
2597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
2607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return apk_assets_[cookie]->Open(filename, mode);
2617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
2627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
2637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam LesinskiApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_override,
264da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski                                         bool stop_at_first_match, LoadedArscEntry* out_entry,
2657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                         ResTable_config* out_selected_config,
2667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                         uint32_t* out_flags) {
2677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ATRACE_CALL();
2687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
2697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Might use this if density_override != 0.
2707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResTable_config density_override_config;
2717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
2727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Select our configuration or generate a density override configuration.
2737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResTable_config* desired_config = &configuration_;
2747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (density_override != 0 && density_override != configuration_.density) {
2757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    density_override_config = configuration_;
2767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    density_override_config.density = density_override;
2777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    desired_config = &density_override_config;
2787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
2797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
280d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  if (!is_valid_resid(resid)) {
281da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid);
282da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    return kInvalidCookie;
283da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
2847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
285d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  const uint32_t package_id = get_package_id(resid);
286d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  const uint8_t type_idx = get_type_id(resid) - 1;
287d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  const uint16_t entry_id = get_entry_id(resid);
288d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
289da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const uint8_t idx = package_ids_[package_id];
290da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  if (idx == 0xff) {
291da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid);
292da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    return kInvalidCookie;
293da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  }
294da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
295da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  LoadedArscEntry best_entry;
296da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  ResTable_config best_config;
297da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  ApkAssetsCookie best_cookie = kInvalidCookie;
298da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  uint32_t cumulated_flags = 0u;
299da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
300da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const PackageGroup& package_group = package_groups_[idx];
301da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const size_t package_count = package_group.packages_.size();
302da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  for (size_t i = 0; i < package_count; i++) {
303da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    LoadedArscEntry current_entry;
3047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    ResTable_config current_config;
305da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    uint32_t current_flags = 0;
306da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
307da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    const LoadedPackage* loaded_package = package_group.packages_[i];
308d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    if (!loaded_package->FindEntry(type_idx, entry_id, *desired_config, &current_entry,
309da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski                                   &current_config, &current_flags)) {
3107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      continue;
3117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
3127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
313da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    cumulated_flags |= current_flags;
3147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
315da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    if (best_cookie == kInvalidCookie || current_config.isBetterThan(best_config, desired_config)) {
3167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      best_entry = current_entry;
3177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      best_config = current_config;
318da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      best_cookie = package_group.cookies_[i];
3197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      if (stop_at_first_match) {
3207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        break;
3217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      }
3227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
3237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
3247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
325da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  if (best_cookie == kInvalidCookie) {
3267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return kInvalidCookie;
3277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
3287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
3297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  *out_entry = best_entry;
330da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  out_entry->dynamic_ref_table = &package_group.dynamic_ref_table;
3317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  *out_selected_config = best_config;
3327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  *out_flags = cumulated_flags;
333da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  return best_cookie;
3347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
3357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
3367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskibool AssetManager2::GetResourceName(uint32_t resid, ResourceName* out_name) {
3377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ATRACE_CALL();
3387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
339da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  LoadedArscEntry entry;
3407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResTable_config config;
3417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  uint32_t flags = 0u;
3427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
3437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                     true /* stop_at_first_match */, &entry, &config, &flags);
3447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (cookie == kInvalidCookie) {
3457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return false;
3467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
3477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
348da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const LoadedPackage* package = apk_assets_[cookie]->GetLoadedArsc()->GetPackageForId(resid);
349da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  if (package == nullptr) {
3507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return false;
3517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
3527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
353da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  out_name->package = package->GetPackageName().data();
354da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  out_name->package_len = package->GetPackageName().size();
3557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
3567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  out_name->type = entry.type_string_ref.string8(&out_name->type_len);
3577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  out_name->type16 = nullptr;
3587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (out_name->type == nullptr) {
3597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    out_name->type16 = entry.type_string_ref.string16(&out_name->type_len);
3607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (out_name->type16 == nullptr) {
3617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return false;
3627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
3637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
3647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
3657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  out_name->entry = entry.entry_string_ref.string8(&out_name->entry_len);
3667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  out_name->entry16 = nullptr;
3677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (out_name->entry == nullptr) {
3687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    out_name->entry16 = entry.entry_string_ref.string16(&out_name->entry_len);
3697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (out_name->entry16 == nullptr) {
3707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return false;
3717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
3727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
3737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return true;
3747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
3757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
3767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskibool AssetManager2::GetResourceFlags(uint32_t resid, uint32_t* out_flags) {
377da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  LoadedArscEntry entry;
3787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResTable_config config;
3797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
3807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                     false /* stop_at_first_match */, &entry, &config, out_flags);
3817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return cookie != kInvalidCookie;
3827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
3837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
3847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam LesinskiApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag,
3857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                           uint16_t density_override, Res_value* out_value,
3867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                           ResTable_config* out_selected_config,
3877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                           uint32_t* out_flags) {
3887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ATRACE_CALL();
3897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
390da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  LoadedArscEntry entry;
3917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResTable_config config;
3927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  uint32_t flags = 0u;
3937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ApkAssetsCookie cookie =
3947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      FindEntry(resid, density_override, false /* stop_at_first_match */, &entry, &config, &flags);
3957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (cookie == kInvalidCookie) {
3967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return kInvalidCookie;
3977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
3987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
3997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (dtohl(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) {
4007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (!may_be_bag) {
4017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      LOG(ERROR) << base::StringPrintf("Resource %08x is a complex map type.", resid);
4020c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      return kInvalidCookie;
4037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
4040c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
4050c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    // Create a reference since we can't represent this complex type as a Res_value.
4060c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    out_value->dataType = Res_value::TYPE_REFERENCE;
4070c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    out_value->data = resid;
4080c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    *out_selected_config = config;
4090c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    *out_flags = flags;
4100c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    return cookie;
4117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
4127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
4137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const Res_value* device_value = reinterpret_cast<const Res_value*>(
4147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      reinterpret_cast<const uint8_t*>(entry.entry) + dtohs(entry.entry->size));
4157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  out_value->copyFrom_dtoh(*device_value);
416da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
417da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // Convert the package ID to the runtime assigned package ID.
418da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  entry.dynamic_ref_table->lookupResourceValue(out_value);
419da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
4207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  *out_selected_config = config;
4217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  *out_flags = flags;
4227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return cookie;
4237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
4247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
4250c40524953f3d36a880f91183302a2ea5c722930Adam LesinskiApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value,
4260c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                                                ResTable_config* in_out_selected_config,
4270c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                                                uint32_t* in_out_flags,
428d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski                                                uint32_t* out_last_reference) {
4290c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  ATRACE_CALL();
4300c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  constexpr const int kMaxIterations = 20;
4310c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
432d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  *out_last_reference = 0u;
4330c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE &&
4340c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                              in_out_value->data != 0u && iteration < kMaxIterations;
4350c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski       iteration++) {
4360c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    if (out_last_reference != nullptr) {
437d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      *out_last_reference = in_out_value->data;
4380c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    }
4390c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    uint32_t new_flags = 0u;
4400c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/,
4410c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                         in_out_value, in_out_selected_config, &new_flags);
4420c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    if (cookie == kInvalidCookie) {
4430c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      return kInvalidCookie;
4440c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    }
4450c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    if (in_out_flags != nullptr) {
4460c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      *in_out_flags |= new_flags;
4470c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    }
448d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    if (*out_last_reference == in_out_value->data) {
4490c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      // This reference can't be resolved, so exit now and let the caller deal with it.
4500c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski      return cookie;
4510c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski    }
4520c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  }
4530c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  return cookie;
4540c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski}
4550c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
4567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskiconst ResolvedBag* AssetManager2::GetBag(uint32_t resid) {
4577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ATRACE_CALL();
4587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
4597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  auto cached_iter = cached_bags_.find(resid);
4607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (cached_iter != cached_bags_.end()) {
4617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return cached_iter->second.get();
4627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
4637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
464da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  LoadedArscEntry entry;
4657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResTable_config config;
4667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  uint32_t flags = 0u;
4677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ApkAssetsCookie cookie = FindEntry(resid, 0u /* density_override */,
4687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                     false /* stop_at_first_match */, &entry, &config, &flags);
4697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (cookie == kInvalidCookie) {
4707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return nullptr;
4717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
4727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
4737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Check that the size of the entry header is at least as big as
4747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // the desired ResTable_map_entry. Also verify that the entry
4757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // was intended to be a map.
4767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (dtohs(entry.entry->size) < sizeof(ResTable_map_entry) ||
4777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      (dtohs(entry.entry->flags) & ResTable_entry::FLAG_COMPLEX) == 0) {
4787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // Not a bag, nothing to do.
4797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return nullptr;
4807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
4817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
4827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const ResTable_map_entry* map = reinterpret_cast<const ResTable_map_entry*>(entry.entry);
4837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const ResTable_map* map_entry =
4847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      reinterpret_cast<const ResTable_map*>(reinterpret_cast<const uint8_t*>(map) + map->size);
4857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const ResTable_map* const map_entry_end = map_entry + dtohl(map->count);
4867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
487da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  uint32_t parent_resid = dtohl(map->parent.ident);
488da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  if (parent_resid == 0) {
4897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // There is no parent, meaning there is nothing to inherit and we can do a simple
4907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // copy of the entries in the map.
4917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const size_t entry_count = map_entry_end - map_entry;
4927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    util::unique_cptr<ResolvedBag> new_bag{reinterpret_cast<ResolvedBag*>(
4937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        malloc(sizeof(ResolvedBag) + (entry_count * sizeof(ResolvedBag::Entry))))};
4947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    ResolvedBag::Entry* new_entry = new_bag->entries;
4957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    for (; map_entry != map_entry_end; ++map_entry) {
496da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      uint32_t new_key = dtohl(map_entry->name.ident);
497929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      if (!is_internal_resid(new_key)) {
498da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        // Attributes, arrays, etc don't have a resource id as the name. They specify
499da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        // other data, which would be wrong to change via a lookup.
500da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
501da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski          LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
502da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski          return nullptr;
503da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        }
504da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
5057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->cookie = cookie;
5067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->value.copyFrom_dtoh(map_entry->value);
507da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      new_entry->key = new_key;
5087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->key_pool = nullptr;
5097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->type_pool = nullptr;
5107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      ++new_entry;
5117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
5127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_bag->type_spec_flags = flags;
5137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_bag->entry_count = static_cast<uint32_t>(entry_count);
5147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    ResolvedBag* result = new_bag.get();
5157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    cached_bags_[resid] = std::move(new_bag);
5167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return result;
5177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
5187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
519da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  // In case the parent is a dynamic reference, resolve it.
520da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  entry.dynamic_ref_table->lookupResourceId(&parent_resid);
521da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
5227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Get the parent and do a merge of the keys.
523da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  const ResolvedBag* parent_bag = GetBag(parent_resid);
5247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (parent_bag == nullptr) {
5257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // Failed to get the parent that should exist.
526da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    LOG(ERROR) << base::StringPrintf("Failed to find parent 0x%08x of bag 0x%08x.", parent_resid, resid);
5277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return nullptr;
5287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
5297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
5307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Combine flags from the parent and our own bag.
5317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  flags |= parent_bag->type_spec_flags;
5327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
5337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Create the max possible entries we can make. Once we construct the bag,
5347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // we will realloc to fit to size.
5357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const size_t max_count = parent_bag->entry_count + dtohl(map->count);
5367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResolvedBag* new_bag = reinterpret_cast<ResolvedBag*>(
5377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      malloc(sizeof(ResolvedBag) + (max_count * sizeof(ResolvedBag::Entry))));
5387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResolvedBag::Entry* new_entry = new_bag->entries;
5397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
5407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const ResolvedBag::Entry* parent_entry = parent_bag->entries;
5417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const ResolvedBag::Entry* const parent_entry_end = parent_entry + parent_bag->entry_count;
5427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
5437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // The keys are expected to be in sorted order. Merge the two bags.
5447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  while (map_entry != map_entry_end && parent_entry != parent_entry_end) {
545da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    uint32_t child_key = dtohl(map_entry->name.ident);
546929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    if (!is_internal_resid(child_key)) {
547da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      if (entry.dynamic_ref_table->lookupResourceId(&child_key) != NO_ERROR) {
548da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", child_key, resid);
549da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        return nullptr;
550da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
551da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    }
552da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
5537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (child_key <= parent_entry->key) {
5547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      // Use the child key if it comes before the parent
5557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      // or is equal to the parent (overrides).
5567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->cookie = cookie;
5577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->value.copyFrom_dtoh(map_entry->value);
5587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->key = child_key;
5597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->key_pool = nullptr;
5607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      new_entry->type_pool = nullptr;
5617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      ++map_entry;
5627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    } else {
5637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      // Take the parent entry as-is.
5647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      memcpy(new_entry, parent_entry, sizeof(*new_entry));
5657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
5667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
5677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (child_key >= parent_entry->key) {
5687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      // Move to the next parent entry if we used it or it was overridden.
5697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      ++parent_entry;
5707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
5717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // Increment to the next entry to fill.
5727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    ++new_entry;
5737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
5747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
5757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Finish the child entries if they exist.
5767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  while (map_entry != map_entry_end) {
577da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    uint32_t new_key = dtohl(map_entry->name.ident);
578929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    if (!is_internal_resid(new_key)) {
579da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      if (entry.dynamic_ref_table->lookupResourceId(&new_key) != NO_ERROR) {
580da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        LOG(ERROR) << base::StringPrintf("Failed to resolve key 0x%08x in bag 0x%08x.", new_key, resid);
581da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        return nullptr;
582da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
583da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    }
5847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_entry->cookie = cookie;
5857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_entry->value.copyFrom_dtoh(map_entry->value);
586da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    new_entry->key = new_key;
5877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_entry->key_pool = nullptr;
5887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_entry->type_pool = nullptr;
5897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    ++map_entry;
5907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    ++new_entry;
5917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
5927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
5937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Finish the parent entries if they exist.
5947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (parent_entry != parent_entry_end) {
5957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // Take the rest of the parent entries as-is.
5967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const size_t num_entries_to_copy = parent_entry_end - parent_entry;
5977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    memcpy(new_entry, parent_entry, num_entries_to_copy * sizeof(*new_entry));
5987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_entry += num_entries_to_copy;
5997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
6007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
6017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Resize the resulting array to fit.
6027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const size_t actual_count = new_entry - new_bag->entries;
6037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (actual_count != max_count) {
6047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    new_bag = reinterpret_cast<ResolvedBag*>(
6057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        realloc(new_bag, sizeof(ResolvedBag) + (actual_count * sizeof(ResolvedBag::Entry))));
6067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
6077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
6087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  util::unique_cptr<ResolvedBag> final_bag{new_bag};
6097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  final_bag->type_spec_flags = flags;
6107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  final_bag->entry_count = static_cast<uint32_t>(actual_count);
6117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ResolvedBag* result = final_bag.get();
6127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  cached_bags_[resid] = std::move(final_bag);
6137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return result;
6147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
6157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
616929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinskistatic bool Utf8ToUtf16(const StringPiece& str, std::u16string* out) {
617929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  ssize_t len =
618929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(str.data()), str.size(), false);
619929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  if (len < 0) {
620929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    return false;
621929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
622929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  out->resize(static_cast<size_t>(len));
623929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  utf8_to_utf16(reinterpret_cast<const uint8_t*>(str.data()), str.size(), &*out->begin(),
624929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski                static_cast<size_t>(len + 1));
625929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  return true;
626929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski}
627929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
6280c40524953f3d36a880f91183302a2ea5c722930Adam Lesinskiuint32_t AssetManager2::GetResourceId(const std::string& resource_name,
6290c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                                      const std::string& fallback_type,
6300c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski                                      const std::string& fallback_package) {
631929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  StringPiece package_name, type, entry;
632929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  if (!ExtractResourceName(resource_name, &package_name, &type, &entry)) {
633929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    return 0u;
634929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
635929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
636929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  if (entry.empty()) {
637929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    return 0u;
638929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
639929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
640929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  if (package_name.empty()) {
641929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    package_name = fallback_package;
642929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
643929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
644929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  if (type.empty()) {
645929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    type = fallback_type;
646929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
647929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
648929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  std::u16string type16;
649929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  if (!Utf8ToUtf16(type, &type16)) {
650929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    return 0u;
651929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
652929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
653929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  std::u16string entry16;
654929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  if (!Utf8ToUtf16(entry, &entry16)) {
655929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    return 0u;
656929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
657929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
658929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  const StringPiece16 kAttr16 = u"attr";
659929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  const static std::u16string kAttrPrivate16 = u"^attr-private";
660929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
661929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  for (const PackageGroup& package_group : package_groups_) {
662929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    for (const LoadedPackage* package : package_group.packages_) {
663929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      if (package_name != package->GetPackageName()) {
664929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski        // All packages in the same group are expected to have the same package name.
665929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski        break;
666929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      }
667929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
668929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      uint32_t resid = package->FindEntryByName(type16, entry16);
669929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      if (resid == 0u && kAttr16 == type16) {
670929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski        // Private attributes in libraries (such as the framework) are sometimes encoded
671929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski        // under the type '^attr-private' in order to leave the ID space of public 'attr'
672929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski        // free for future additions. Check '^attr-private' for the same name.
673929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski        resid = package->FindEntryByName(kAttrPrivate16, entry16);
674929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      }
675929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski
676929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      if (resid != 0u) {
677929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski        return fix_package_id(resid, package_group.dynamic_ref_table.mAssignedPackageId);
678929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski      }
679929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    }
680929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski  }
6810c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski  return 0u;
6820c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski}
6830c40524953f3d36a880f91183302a2ea5c722930Adam Lesinski
6847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskivoid AssetManager2::InvalidateCaches(uint32_t diff) {
6857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (diff == 0xffffffffu) {
6867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // Everything must go.
6877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    cached_bags_.clear();
6887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return;
6897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
6907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
6917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Be more conservative with what gets purged. Only if the bag has other possible
6927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // variations with respect to what changed (diff) should we remove it.
6937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  for (auto iter = cached_bags_.cbegin(); iter != cached_bags_.cend();) {
6947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (diff & iter->second->type_spec_flags) {
6957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      iter = cached_bags_.erase(iter);
6967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    } else {
6977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      ++iter;
6987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
6997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
7007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
7017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskistd::unique_ptr<Theme> AssetManager2::NewTheme() { return std::unique_ptr<Theme>(new Theme(this)); }
7037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskibool Theme::ApplyStyle(uint32_t resid, bool force) {
7057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  ATRACE_CALL();
7067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const ResolvedBag* bag = asset_manager_->GetBag(resid);
7087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (bag == nullptr) {
7097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return false;
7107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
7117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // Merge the flags from this style.
7137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  type_spec_flags_ |= bag->type_spec_flags;
7147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // On the first iteration, verify the attribute IDs and
7167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // update the entry count in each type.
7177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  const auto bag_iter_end = end(bag);
7187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  for (auto bag_iter = begin(bag); bag_iter != bag_iter_end; ++bag_iter) {
7197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const uint32_t attr_resid = bag_iter->key;
7207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // If the resource ID passed in is not a style, the key can be
7227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // some other identifier that is not a resource ID.
723929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    if (!is_valid_resid(attr_resid)) {
7247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return false;
7257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
7267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
727929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t package_idx = get_package_id(attr_resid);
7287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // The type ID is 1-based, so subtract 1 to get an index.
730929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t type_idx = get_type_id(attr_resid) - 1;
731929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t entry_idx = get_entry_id(attr_resid);
7327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    std::unique_ptr<Package>& package = packages_[package_idx];
7347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (package == nullptr) {
7357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      package.reset(new Package());
7367ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
7377ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7387ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    util::unique_cptr<Type>& type = package->types[type_idx];
7397ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (type == nullptr) {
7407ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      // Set the initial capacity to take up a total amount of 1024 bytes.
7417ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      constexpr uint32_t kInitialCapacity = (1024u - sizeof(Type)) / sizeof(Entry);
7427ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      const uint32_t initial_capacity = std::max(entry_idx, kInitialCapacity);
7437ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      type.reset(
7447ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski          reinterpret_cast<Type*>(calloc(sizeof(Type) + (initial_capacity * sizeof(Entry)), 1)));
7457ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      type->entry_capacity = initial_capacity;
7467ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
7477ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7487ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // Set the entry_count to include this entry. We will populate
7497ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // and resize the array as necessary in the next pass.
7507ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (entry_idx + 1 > type->entry_count) {
7517ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      // Increase the entry count to include this.
7527ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      type->entry_count = entry_idx + 1;
7537ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
7547ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
7557ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7567ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // On the second pass, we will realloc to fit the entry counts
7577ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  // and populate the structures.
7587ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  for (auto bag_iter = begin(bag); bag_iter != bag_iter_end; ++bag_iter) {
7597ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const uint32_t attr_resid = bag_iter->key;
760929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t package_idx = get_package_id(attr_resid);
761929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t type_idx = get_type_id(attr_resid) - 1;
762929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t entry_idx = get_entry_id(attr_resid);
7637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    Package* package = packages_[package_idx].get();
7647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    util::unique_cptr<Type>& type = package->types[type_idx];
7657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (type->entry_count != type->entry_capacity) {
7667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      // Resize to fit the actual entries that will be included.
7677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      Type* type_ptr = type.release();
7687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      type.reset(reinterpret_cast<Type*>(
7697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski          realloc(type_ptr, sizeof(Type) + (type_ptr->entry_count * sizeof(Entry)))));
7707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      if (type->entry_capacity < type->entry_count) {
7717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        // Clear the newly allocated memory (which does not get zero initialized).
7727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        // We need to do this because we |= type_spec_flags.
7737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        memset(type->entries + type->entry_capacity, 0,
7747ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski               sizeof(Entry) * (type->entry_count - type->entry_capacity));
7757ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      }
7767ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      type->entry_capacity = type->entry_count;
7777ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
7787ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    Entry& entry = type->entries[entry_idx];
7797ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (force || entry.value.dataType == Res_value::TYPE_NULL) {
7807ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      entry.cookie = bag_iter->cookie;
7817ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      entry.type_spec_flags |= bag->type_spec_flags;
7827ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      entry.value = bag_iter->value;
7837ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
7847ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
7857ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return true;
7867ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
7877ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7887ad1110ecd6a840fcd2895c62668828a1ca029c6Adam LesinskiApkAssetsCookie Theme::GetAttribute(uint32_t resid, Res_value* out_value,
7897ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                    uint32_t* out_flags) const {
7907ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  constexpr const int kMaxIterations = 20;
7917ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7927ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  uint32_t type_spec_flags = 0u;
7937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
7947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  for (int iterations_left = kMaxIterations; iterations_left > 0; iterations_left--) {
795929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    if (!is_valid_resid(resid)) {
7967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return kInvalidCookie;
7977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
7987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
799929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t package_idx = get_package_id(resid);
8007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    // Type ID is 1-based, subtract 1 to get the index.
802929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t type_idx = get_type_id(resid) - 1;
803929d6517dfd338f0d481dbe6587643d5aef27ec6Adam Lesinski    const uint32_t entry_idx = get_entry_id(resid);
8047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const Package* package = packages_[package_idx].get();
8067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (package == nullptr) {
8077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return kInvalidCookie;
8087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
8097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const Type* type = package->types[type_idx].get();
8117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (type == nullptr) {
8127ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return kInvalidCookie;
8137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
8147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (entry_idx >= type->entry_count) {
8167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      return kInvalidCookie;
8177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
8187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8197ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const Entry& entry = type->entries[entry_idx];
8207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    type_spec_flags |= entry.type_spec_flags;
8217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    switch (entry.value.dataType) {
823da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      case Res_value::TYPE_NULL:
824da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        return kInvalidCookie;
825da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
8267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      case Res_value::TYPE_ATTRIBUTE:
8277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        resid = entry.value.data;
8287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        break;
8297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
830da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      case Res_value::TYPE_DYNAMIC_ATTRIBUTE: {
831da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        // Resolve the dynamic attribute to a normal attribute
832da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        // (with the right package ID).
833da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        resid = entry.value.data;
834da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        const DynamicRefTable* ref_table =
835da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski            asset_manager_->GetDynamicRefTableForPackage(package_idx);
836da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        if (ref_table == nullptr || ref_table->lookupResourceId(&resid) != NO_ERROR) {
837da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski          LOG(ERROR) << base::StringPrintf("Failed to resolve dynamic attribute 0x%08x", resid);
838da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski          return kInvalidCookie;
839da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        }
840da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      } break;
841da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
842da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      case Res_value::TYPE_DYNAMIC_REFERENCE: {
843da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        // Resolve the dynamic reference to a normal reference
844da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        // (with the right package ID).
845da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        out_value->dataType = Res_value::TYPE_REFERENCE;
846da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        out_value->data = entry.value.data;
847da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        const DynamicRefTable* ref_table =
848da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski            asset_manager_->GetDynamicRefTableForPackage(package_idx);
849da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        if (ref_table == nullptr || ref_table->lookupResourceId(&out_value->data) != NO_ERROR) {
850da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski          LOG(ERROR) << base::StringPrintf("Failed to resolve dynamic reference 0x%08x",
851da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski                                           out_value->data);
852da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski          return kInvalidCookie;
853da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        }
854da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski
855da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        if (out_flags != nullptr) {
856da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski          *out_flags = type_spec_flags;
857da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        }
858da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski        return entry.cookie;
859da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski      }
8607ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8617ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      default:
8627ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        *out_value = entry.value;
8637ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        if (out_flags != nullptr) {
8647ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski          *out_flags = type_spec_flags;
8657ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        }
8667ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        return entry.cookie;
8677ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
8687ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
8697ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8707ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  LOG(WARNING) << base::StringPrintf("Too many (%d) attribute references, stopped at: 0x%08x",
8717ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski                                     kMaxIterations, resid);
8727ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return kInvalidCookie;
8737ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
874d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
875d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam LesinskiApkAssetsCookie Theme::ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value,
876d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski                                                 ResTable_config* in_out_selected_config,
877d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski                                                 uint32_t* in_out_type_spec_flags,
878d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski                                                 uint32_t* out_last_ref) {
879d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  if (in_out_value->dataType == Res_value::TYPE_ATTRIBUTE) {
880d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    uint32_t new_flags;
881d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    cookie = GetAttribute(in_out_value->data, in_out_value, &new_flags);
882d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    if (cookie == kInvalidCookie) {
883d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      return kInvalidCookie;
884d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    }
885d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski
886d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    if (in_out_type_spec_flags != nullptr) {
887d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski      *in_out_type_spec_flags |= new_flags;
888d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski    }
889d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  }
890d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski  return asset_manager_->ResolveReference(cookie, in_out_value, in_out_selected_config,
891d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski                                          in_out_type_spec_flags, out_last_ref);
892d1ecd7af687bcad0f87c37fe33515ff6c5ea0f1dAdam Lesinski}
8937ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
8947ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskivoid Theme::Clear() {
8957ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  type_spec_flags_ = 0u;
8967ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  for (std::unique_ptr<Package>& package : packages_) {
8977ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    package.reset();
8987ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
8997ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
9007ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
9017ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinskibool Theme::SetTo(const Theme& o) {
9027ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (this == &o) {
9037ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return true;
9047ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
9057ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
9067ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  if (asset_manager_ != o.asset_manager_) {
9077ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    return false;
9087ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
9097ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
9107ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  type_spec_flags_ = o.type_spec_flags_;
9117ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
912da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski  for (size_t p = 0; p < packages_.size(); p++) {
9137ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    const Package* package = o.packages_[p].get();
9147ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    if (package == nullptr) {
9157ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      packages_[p].reset();
9167ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      continue;
9177ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
9187ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
919da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski    for (size_t t = 0; t < package->types.size(); t++) {
9207ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      const Type* type = package->types[t].get();
9217ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      if (type == nullptr) {
9227ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        packages_[p]->types[t].reset();
9237ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski        continue;
9247ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      }
9257ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
9267ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      const size_t type_alloc_size = sizeof(Type) + (type->entry_capacity * sizeof(Entry));
9277ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      void* copied_data = malloc(type_alloc_size);
9287ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      memcpy(copied_data, type, type_alloc_size);
9297ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski      packages_[p]->types[t].reset(reinterpret_cast<Type*>(copied_data));
9307ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski    }
9317ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  }
9327ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski  return true;
9337ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}
9347ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski
9357ad1110ecd6a840fcd2895c62668828a1ca029c6Adam Lesinski}  // namespace android
936