Loading libs/androidfw/ApkAssets.cpp +74 −15 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ #include "androidfw/ApkAssets.h" #include <algorithm> #include "android-base/logging.h" #include "utils/FileMap.h" #include "utils/Trace.h" #include "ziparchive/zip_archive.h" Loading Loading @@ -62,13 +65,13 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(const std::string& path, bo LOG(WARNING) << "resources.arsc is compressed."; } loaded_apk->path_ = path; loaded_apk->resources_asset_ = loaded_apk->Open("resources.arsc", Asset::AccessMode::ACCESS_BUFFER); if (loaded_apk->resources_asset_ == nullptr) { return {}; } loaded_apk->path_ = path; loaded_apk->loaded_arsc_ = LoadedArsc::Load(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/), loaded_apk->resources_asset_->getLength(), system, load_as_shared_library); Loading @@ -80,37 +83,93 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(const std::string& path, bo return std::move(loaded_apk); } std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode /*mode*/) const { ATRACE_NAME("ApkAssets::Open"); std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode mode) const { ATRACE_CALL(); CHECK(zip_handle_ != nullptr); ::ZipString name(path.c_str()); ::ZipEntry entry; int32_t result = ::FindEntry(zip_handle_.get(), name, &entry); if (result != 0) { LOG(ERROR) << "No entry '" << path << "' found in APK."; LOG(ERROR) << "No entry '" << path << "' found in APK '" << path_ << "'"; return {}; } if (entry.method == kCompressDeflated) { auto compressed_asset = util::make_unique<_CompressedAsset>(); if (compressed_asset->openChunk(::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.method, entry.uncompressed_length, entry.compressed_length) != NO_ERROR) { std::unique_ptr<FileMap> map = util::make_unique<FileMap>(); if (!map->create(path_.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.compressed_length, true /*readOnly*/)) { LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'"; return {}; } std::unique_ptr<Asset> asset = Asset::createFromCompressedMap(std::move(map), entry.uncompressed_length, mode); if (asset == nullptr) { LOG(ERROR) << "Failed to decompress '" << path << "'."; return {}; } return std::move(compressed_asset); return asset; } else { auto uncompressed_asset = util::make_unique<_FileAsset>(); if (uncompressed_asset->openChunk(path.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.uncompressed_length) != NO_ERROR) { LOG(ERROR) << "Failed to mmap '" << path << "'."; std::unique_ptr<FileMap> map = util::make_unique<FileMap>(); if (!map->create(path_.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.uncompressed_length, true /*readOnly*/)) { LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'"; return {}; } return std::move(uncompressed_asset); } std::unique_ptr<Asset> asset = Asset::createFromUncompressedMap(std::move(map), mode); if (asset == nullptr) { LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'"; return {}; } return asset; } } bool ApkAssets::ForEachFile(const std::string& root_path, const std::function<void(const StringPiece&, FileType)>& f) const { CHECK(zip_handle_ != nullptr); std::string root_path_full = root_path; if (root_path_full.back() != '/') { root_path_full += '/'; } ::ZipString prefix(root_path_full.c_str()); void* cookie; if (::StartIteration(zip_handle_.get(), &cookie, &prefix, nullptr) != 0) { return false; } ::ZipString name; ::ZipEntry entry; // We need to hold back directories because many paths will contain them and we want to only // surface one. std::set<std::string> dirs; int32_t result; while ((result = ::Next(cookie, &entry, &name)) == 0) { StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length); StringPiece leaf_file_path = full_file_path.substr(root_path_full.size()); auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/'); if (iter != leaf_file_path.end()) { dirs.insert( leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string()); } else if (!leaf_file_path.empty()) { f(leaf_file_path, kFileTypeRegular); } } ::EndIteration(cookie); // Now present the unique directories. for (const std::string& dir : dirs) { f(dir, kFileTypeDirectory); } // -1 is end of iteration, anything else is an error. return result == -1; } } // namespace android libs/androidfw/Asset.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <androidfw/Asset.h> #include <androidfw/StreamingZipInflater.h> #include <androidfw/Util.h> #include <androidfw/ZipFileRO.h> #include <androidfw/ZipUtils.h> #include <utils/Atomic.h> Loading Loading @@ -298,6 +299,22 @@ Asset::Asset(void) return pAsset; } /*static*/ std::unique_ptr<Asset> Asset::createFromUncompressedMap(std::unique_ptr<FileMap> dataMap, AccessMode mode) { std::unique_ptr<_FileAsset> pAsset = util::make_unique<_FileAsset>(); status_t result = pAsset->openChunk(dataMap.get()); if (result != NO_ERROR) { return NULL; } // We succeeded, so relinquish control of dataMap (void) dataMap.release(); pAsset->mAccessMode = mode; return std::move(pAsset); } /* * Create a new Asset from compressed data in a memory mapping. */ Loading @@ -316,6 +333,21 @@ Asset::Asset(void) return pAsset; } /*static*/ std::unique_ptr<Asset> Asset::createFromCompressedMap(std::unique_ptr<FileMap> dataMap, size_t uncompressedLen, AccessMode mode) { std::unique_ptr<_CompressedAsset> pAsset = util::make_unique<_CompressedAsset>(); status_t result = pAsset->openChunk(dataMap.get(), uncompressedLen); if (result != NO_ERROR) { return NULL; } // We succeeded, so relinquish control of dataMap (void) dataMap.release(); pAsset->mAccessMode = mode; return std::move(pAsset); } /* * Do generic seek() housekeeping. Pass in the offset/whence values from Loading libs/androidfw/AssetManager2.cpp +69 −10 Original line number Diff line number Diff line Loading @@ -138,6 +138,17 @@ const DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t pack return &package_groups_[idx].dynamic_ref_table; } const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const { for (const PackageGroup& package_group : package_groups_) { for (const ApkAssetsCookie& package_cookie : package_group.cookies_) { if (package_cookie == cookie) { return &package_group.dynamic_ref_table; } } } return nullptr; } void AssetManager2::SetConfiguration(const ResTable_config& configuration) { const int diff = configuration_.diff(configuration); configuration_ = configuration; Loading Loading @@ -188,6 +199,35 @@ std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAsset return OpenNonAsset(new_path, cookie, mode); } std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) { ATRACE_CALL(); std::string full_path = "assets/" + dirname; std::unique_ptr<SortedVector<AssetDir::FileInfo>> files = util::make_unique<SortedVector<AssetDir::FileInfo>>(); // Start from the back. for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) { const ApkAssets* apk_assets = *iter; auto func = [&](const StringPiece& name, FileType type) { AssetDir::FileInfo info; info.setFileName(String8(name.data(), name.size())); info.setFileType(type); info.setSourceName(String8(apk_assets->GetPath().c_str())); files->add(info); }; if (!apk_assets->ForEachFile(full_path, func)) { return {}; } } std::unique_ptr<AssetDir> asset_dir = util::make_unique<AssetDir>(); asset_dir->setFileList(files.release()); return asset_dir; } // Search in reverse because that's how we used to do it and we need to preserve behaviour. // This is unfortunate, because ClassLoaders delegate to the parent first, so the order // is inconsistent for split APKs. Loading Loading @@ -237,15 +277,15 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri desired_config = &density_override_config; } const uint32_t package_id = get_package_id(resid); const uint8_t type_id = get_type_id(resid); const uint16_t entry_id = get_entry_id(resid); if (type_id == 0) { if (!is_valid_resid(resid)) { LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid); return kInvalidCookie; } const uint32_t package_id = get_package_id(resid); const uint8_t type_idx = get_type_id(resid) - 1; const uint16_t entry_id = get_entry_id(resid); const uint8_t idx = package_ids_[package_id]; if (idx == 0xff) { LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid); Loading @@ -265,7 +305,7 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri uint32_t current_flags = 0; const LoadedPackage* loaded_package = package_group.packages_[i]; if (!loaded_package->FindEntry(type_id - 1, entry_id, *desired_config, ¤t_entry, if (!loaded_package->FindEntry(type_idx, entry_id, *desired_config, ¤t_entry, ¤t_config, ¤t_flags)) { continue; } Loading Loading @@ -385,16 +425,16 @@ ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag, ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value, ResTable_config* in_out_selected_config, uint32_t* in_out_flags, ResTable_ref* out_last_reference) { uint32_t* out_last_reference) { ATRACE_CALL(); constexpr const int kMaxIterations = 20; out_last_reference->ident = 0u; *out_last_reference = 0u; for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE && in_out_value->data != 0u && iteration < kMaxIterations; iteration++) { if (out_last_reference != nullptr) { out_last_reference->ident = in_out_value->data; *out_last_reference = in_out_value->data; } uint32_t new_flags = 0u; cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/, Loading @@ -405,7 +445,7 @@ ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_valu if (in_out_flags != nullptr) { *in_out_flags |= new_flags; } if (out_last_reference->ident == in_out_value->data) { if (*out_last_reference == in_out_value->data) { // This reference can't be resolved, so exit now and let the caller deal with it. return cookie; } Loading Loading @@ -832,6 +872,25 @@ ApkAssetsCookie Theme::GetAttribute(uint32_t resid, Res_value* out_value, return kInvalidCookie; } ApkAssetsCookie Theme::ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value, ResTable_config* in_out_selected_config, uint32_t* in_out_type_spec_flags, uint32_t* out_last_ref) { if (in_out_value->dataType == Res_value::TYPE_ATTRIBUTE) { uint32_t new_flags; cookie = GetAttribute(in_out_value->data, in_out_value, &new_flags); if (cookie == kInvalidCookie) { return kInvalidCookie; } if (in_out_type_spec_flags != nullptr) { *in_out_type_spec_flags |= new_flags; } } return asset_manager_->ResolveReference(cookie, in_out_value, in_out_selected_config, in_out_type_spec_flags, out_last_ref); } void Theme::Clear() { type_spec_flags_ = 0u; for (std::unique_ptr<Package>& package : packages_) { Loading libs/androidfw/ResourceTypes.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -6532,6 +6532,8 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, return NO_ERROR; } DynamicRefTable::DynamicRefTable() : DynamicRefTable(0, false) {} DynamicRefTable::DynamicRefTable(uint8_t packageId, bool appAsLib) : mAssignedPackageId(packageId) , mAppAsLib(appAsLib) Loading Loading @@ -6637,11 +6639,11 @@ status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { // Do a proper lookup. uint8_t translatedId = mLookupTable[packageId]; if (translatedId == 0) { ALOGV("DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x.", ALOGW("DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x.", (uint8_t)mAssignedPackageId, (uint8_t)packageId); for (size_t i = 0; i < 256; i++) { if (mLookupTable[i] != 0) { ALOGV("e[0x%02x] -> 0x%02x", (uint8_t)i, mLookupTable[i]); ALOGW("e[0x%02x] -> 0x%02x", (uint8_t)i, mLookupTable[i]); } } return UNKNOWN_ERROR; Loading libs/androidfw/Util.cpp +26 −0 Original line number Diff line number Diff line Loading @@ -41,5 +41,31 @@ void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out } } std::u16string Utf8ToUtf16(const StringPiece& utf8) { ssize_t utf16_length = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length()); if (utf16_length <= 0) { return {}; } std::u16string utf16; utf16.resize(utf16_length); utf8_to_utf16(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length(), &*utf16.begin(), utf16_length + 1); return utf16; } std::string Utf16ToUtf8(const StringPiece16& utf16) { ssize_t utf8_length = utf16_to_utf8_length(utf16.data(), utf16.length()); if (utf8_length <= 0) { return {}; } std::string utf8; utf8.resize(utf8_length); utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8_length + 1); return utf8; } } // namespace util } // namespace android Loading
libs/androidfw/ApkAssets.cpp +74 −15 Original line number Diff line number Diff line Loading @@ -18,7 +18,10 @@ #include "androidfw/ApkAssets.h" #include <algorithm> #include "android-base/logging.h" #include "utils/FileMap.h" #include "utils/Trace.h" #include "ziparchive/zip_archive.h" Loading Loading @@ -62,13 +65,13 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(const std::string& path, bo LOG(WARNING) << "resources.arsc is compressed."; } loaded_apk->path_ = path; loaded_apk->resources_asset_ = loaded_apk->Open("resources.arsc", Asset::AccessMode::ACCESS_BUFFER); if (loaded_apk->resources_asset_ == nullptr) { return {}; } loaded_apk->path_ = path; loaded_apk->loaded_arsc_ = LoadedArsc::Load(loaded_apk->resources_asset_->getBuffer(true /*wordAligned*/), loaded_apk->resources_asset_->getLength(), system, load_as_shared_library); Loading @@ -80,37 +83,93 @@ std::unique_ptr<const ApkAssets> ApkAssets::LoadImpl(const std::string& path, bo return std::move(loaded_apk); } std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode /*mode*/) const { ATRACE_NAME("ApkAssets::Open"); std::unique_ptr<Asset> ApkAssets::Open(const std::string& path, Asset::AccessMode mode) const { ATRACE_CALL(); CHECK(zip_handle_ != nullptr); ::ZipString name(path.c_str()); ::ZipEntry entry; int32_t result = ::FindEntry(zip_handle_.get(), name, &entry); if (result != 0) { LOG(ERROR) << "No entry '" << path << "' found in APK."; LOG(ERROR) << "No entry '" << path << "' found in APK '" << path_ << "'"; return {}; } if (entry.method == kCompressDeflated) { auto compressed_asset = util::make_unique<_CompressedAsset>(); if (compressed_asset->openChunk(::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.method, entry.uncompressed_length, entry.compressed_length) != NO_ERROR) { std::unique_ptr<FileMap> map = util::make_unique<FileMap>(); if (!map->create(path_.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.compressed_length, true /*readOnly*/)) { LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'"; return {}; } std::unique_ptr<Asset> asset = Asset::createFromCompressedMap(std::move(map), entry.uncompressed_length, mode); if (asset == nullptr) { LOG(ERROR) << "Failed to decompress '" << path << "'."; return {}; } return std::move(compressed_asset); return asset; } else { auto uncompressed_asset = util::make_unique<_FileAsset>(); if (uncompressed_asset->openChunk(path.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.uncompressed_length) != NO_ERROR) { LOG(ERROR) << "Failed to mmap '" << path << "'."; std::unique_ptr<FileMap> map = util::make_unique<FileMap>(); if (!map->create(path_.c_str(), ::GetFileDescriptor(zip_handle_.get()), entry.offset, entry.uncompressed_length, true /*readOnly*/)) { LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'"; return {}; } return std::move(uncompressed_asset); } std::unique_ptr<Asset> asset = Asset::createFromUncompressedMap(std::move(map), mode); if (asset == nullptr) { LOG(ERROR) << "Failed to mmap file '" << path << "' in APK '" << path_ << "'"; return {}; } return asset; } } bool ApkAssets::ForEachFile(const std::string& root_path, const std::function<void(const StringPiece&, FileType)>& f) const { CHECK(zip_handle_ != nullptr); std::string root_path_full = root_path; if (root_path_full.back() != '/') { root_path_full += '/'; } ::ZipString prefix(root_path_full.c_str()); void* cookie; if (::StartIteration(zip_handle_.get(), &cookie, &prefix, nullptr) != 0) { return false; } ::ZipString name; ::ZipEntry entry; // We need to hold back directories because many paths will contain them and we want to only // surface one. std::set<std::string> dirs; int32_t result; while ((result = ::Next(cookie, &entry, &name)) == 0) { StringPiece full_file_path(reinterpret_cast<const char*>(name.name), name.name_length); StringPiece leaf_file_path = full_file_path.substr(root_path_full.size()); auto iter = std::find(leaf_file_path.begin(), leaf_file_path.end(), '/'); if (iter != leaf_file_path.end()) { dirs.insert( leaf_file_path.substr(0, std::distance(leaf_file_path.begin(), iter)).to_string()); } else if (!leaf_file_path.empty()) { f(leaf_file_path, kFileTypeRegular); } } ::EndIteration(cookie); // Now present the unique directories. for (const std::string& dir : dirs) { f(dir, kFileTypeDirectory); } // -1 is end of iteration, anything else is an error. return result == -1; } } // namespace android
libs/androidfw/Asset.cpp +32 −0 Original line number Diff line number Diff line Loading @@ -23,6 +23,7 @@ #include <androidfw/Asset.h> #include <androidfw/StreamingZipInflater.h> #include <androidfw/Util.h> #include <androidfw/ZipFileRO.h> #include <androidfw/ZipUtils.h> #include <utils/Atomic.h> Loading Loading @@ -298,6 +299,22 @@ Asset::Asset(void) return pAsset; } /*static*/ std::unique_ptr<Asset> Asset::createFromUncompressedMap(std::unique_ptr<FileMap> dataMap, AccessMode mode) { std::unique_ptr<_FileAsset> pAsset = util::make_unique<_FileAsset>(); status_t result = pAsset->openChunk(dataMap.get()); if (result != NO_ERROR) { return NULL; } // We succeeded, so relinquish control of dataMap (void) dataMap.release(); pAsset->mAccessMode = mode; return std::move(pAsset); } /* * Create a new Asset from compressed data in a memory mapping. */ Loading @@ -316,6 +333,21 @@ Asset::Asset(void) return pAsset; } /*static*/ std::unique_ptr<Asset> Asset::createFromCompressedMap(std::unique_ptr<FileMap> dataMap, size_t uncompressedLen, AccessMode mode) { std::unique_ptr<_CompressedAsset> pAsset = util::make_unique<_CompressedAsset>(); status_t result = pAsset->openChunk(dataMap.get(), uncompressedLen); if (result != NO_ERROR) { return NULL; } // We succeeded, so relinquish control of dataMap (void) dataMap.release(); pAsset->mAccessMode = mode; return std::move(pAsset); } /* * Do generic seek() housekeeping. Pass in the offset/whence values from Loading
libs/androidfw/AssetManager2.cpp +69 −10 Original line number Diff line number Diff line Loading @@ -138,6 +138,17 @@ const DynamicRefTable* AssetManager2::GetDynamicRefTableForPackage(uint32_t pack return &package_groups_[idx].dynamic_ref_table; } const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const { for (const PackageGroup& package_group : package_groups_) { for (const ApkAssetsCookie& package_cookie : package_group.cookies_) { if (package_cookie == cookie) { return &package_group.dynamic_ref_table; } } } return nullptr; } void AssetManager2::SetConfiguration(const ResTable_config& configuration) { const int diff = configuration_.diff(configuration); configuration_ = configuration; Loading Loading @@ -188,6 +199,35 @@ std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAsset return OpenNonAsset(new_path, cookie, mode); } std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) { ATRACE_CALL(); std::string full_path = "assets/" + dirname; std::unique_ptr<SortedVector<AssetDir::FileInfo>> files = util::make_unique<SortedVector<AssetDir::FileInfo>>(); // Start from the back. for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) { const ApkAssets* apk_assets = *iter; auto func = [&](const StringPiece& name, FileType type) { AssetDir::FileInfo info; info.setFileName(String8(name.data(), name.size())); info.setFileType(type); info.setSourceName(String8(apk_assets->GetPath().c_str())); files->add(info); }; if (!apk_assets->ForEachFile(full_path, func)) { return {}; } } std::unique_ptr<AssetDir> asset_dir = util::make_unique<AssetDir>(); asset_dir->setFileList(files.release()); return asset_dir; } // Search in reverse because that's how we used to do it and we need to preserve behaviour. // This is unfortunate, because ClassLoaders delegate to the parent first, so the order // is inconsistent for split APKs. Loading Loading @@ -237,15 +277,15 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri desired_config = &density_override_config; } const uint32_t package_id = get_package_id(resid); const uint8_t type_id = get_type_id(resid); const uint16_t entry_id = get_entry_id(resid); if (type_id == 0) { if (!is_valid_resid(resid)) { LOG(ERROR) << base::StringPrintf("Invalid ID 0x%08x.", resid); return kInvalidCookie; } const uint32_t package_id = get_package_id(resid); const uint8_t type_idx = get_type_id(resid) - 1; const uint16_t entry_id = get_entry_id(resid); const uint8_t idx = package_ids_[package_id]; if (idx == 0xff) { LOG(ERROR) << base::StringPrintf("No package ID %02x found for ID 0x%08x.", package_id, resid); Loading @@ -265,7 +305,7 @@ ApkAssetsCookie AssetManager2::FindEntry(uint32_t resid, uint16_t density_overri uint32_t current_flags = 0; const LoadedPackage* loaded_package = package_group.packages_[i]; if (!loaded_package->FindEntry(type_id - 1, entry_id, *desired_config, ¤t_entry, if (!loaded_package->FindEntry(type_idx, entry_id, *desired_config, ¤t_entry, ¤t_config, ¤t_flags)) { continue; } Loading Loading @@ -385,16 +425,16 @@ ApkAssetsCookie AssetManager2::GetResource(uint32_t resid, bool may_be_bag, ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_value* in_out_value, ResTable_config* in_out_selected_config, uint32_t* in_out_flags, ResTable_ref* out_last_reference) { uint32_t* out_last_reference) { ATRACE_CALL(); constexpr const int kMaxIterations = 20; out_last_reference->ident = 0u; *out_last_reference = 0u; for (size_t iteration = 0u; in_out_value->dataType == Res_value::TYPE_REFERENCE && in_out_value->data != 0u && iteration < kMaxIterations; iteration++) { if (out_last_reference != nullptr) { out_last_reference->ident = in_out_value->data; *out_last_reference = in_out_value->data; } uint32_t new_flags = 0u; cookie = GetResource(in_out_value->data, true /*may_be_bag*/, 0u /*density_override*/, Loading @@ -405,7 +445,7 @@ ApkAssetsCookie AssetManager2::ResolveReference(ApkAssetsCookie cookie, Res_valu if (in_out_flags != nullptr) { *in_out_flags |= new_flags; } if (out_last_reference->ident == in_out_value->data) { if (*out_last_reference == in_out_value->data) { // This reference can't be resolved, so exit now and let the caller deal with it. return cookie; } Loading Loading @@ -832,6 +872,25 @@ ApkAssetsCookie Theme::GetAttribute(uint32_t resid, Res_value* out_value, return kInvalidCookie; } ApkAssetsCookie Theme::ResolveAttributeReference(ApkAssetsCookie cookie, Res_value* in_out_value, ResTable_config* in_out_selected_config, uint32_t* in_out_type_spec_flags, uint32_t* out_last_ref) { if (in_out_value->dataType == Res_value::TYPE_ATTRIBUTE) { uint32_t new_flags; cookie = GetAttribute(in_out_value->data, in_out_value, &new_flags); if (cookie == kInvalidCookie) { return kInvalidCookie; } if (in_out_type_spec_flags != nullptr) { *in_out_type_spec_flags |= new_flags; } } return asset_manager_->ResolveReference(cookie, in_out_value, in_out_selected_config, in_out_type_spec_flags, out_last_ref); } void Theme::Clear() { type_spec_flags_ = 0u; for (std::unique_ptr<Package>& package : packages_) { Loading
libs/androidfw/ResourceTypes.cpp +4 −2 Original line number Diff line number Diff line Loading @@ -6532,6 +6532,8 @@ status_t ResTable::parsePackage(const ResTable_package* const pkg, return NO_ERROR; } DynamicRefTable::DynamicRefTable() : DynamicRefTable(0, false) {} DynamicRefTable::DynamicRefTable(uint8_t packageId, bool appAsLib) : mAssignedPackageId(packageId) , mAppAsLib(appAsLib) Loading Loading @@ -6637,11 +6639,11 @@ status_t DynamicRefTable::lookupResourceId(uint32_t* resId) const { // Do a proper lookup. uint8_t translatedId = mLookupTable[packageId]; if (translatedId == 0) { ALOGV("DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x.", ALOGW("DynamicRefTable(0x%02x): No mapping for build-time package ID 0x%02x.", (uint8_t)mAssignedPackageId, (uint8_t)packageId); for (size_t i = 0; i < 256; i++) { if (mLookupTable[i] != 0) { ALOGV("e[0x%02x] -> 0x%02x", (uint8_t)i, mLookupTable[i]); ALOGW("e[0x%02x] -> 0x%02x", (uint8_t)i, mLookupTable[i]); } } return UNKNOWN_ERROR; Loading
libs/androidfw/Util.cpp +26 −0 Original line number Diff line number Diff line Loading @@ -41,5 +41,31 @@ void ReadUtf16StringFromDevice(const uint16_t* src, size_t len, std::string* out } } std::u16string Utf8ToUtf16(const StringPiece& utf8) { ssize_t utf16_length = utf8_to_utf16_length(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length()); if (utf16_length <= 0) { return {}; } std::u16string utf16; utf16.resize(utf16_length); utf8_to_utf16(reinterpret_cast<const uint8_t*>(utf8.data()), utf8.length(), &*utf16.begin(), utf16_length + 1); return utf16; } std::string Utf16ToUtf8(const StringPiece16& utf16) { ssize_t utf8_length = utf16_to_utf8_length(utf16.data(), utf16.length()); if (utf8_length <= 0) { return {}; } std::string utf8; utf8.resize(utf8_length); utf16_to_utf8(utf16.data(), utf16.length(), &*utf8.begin(), utf8_length + 1); return utf8; } } // namespace util } // namespace android