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, ¤t_entry, 309da431a22da38f9c4085b5d71ed9a9c6122c6a5a6Adam Lesinski ¤t_config, ¤t_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