Loading core/java/android/content/res/AssetManager.java +13 −1 Original line number Diff line number Diff line Loading @@ -1064,6 +1064,17 @@ public final class AssetManager implements AutoCloseable { } } @UnsupportedAppUsage void setThemeTo(long dstThemePtr, @NonNull AssetManager srcAssetManager, long srcThemePtr) { synchronized (this) { ensureValidLocked(); synchronized (srcAssetManager) { srcAssetManager.ensureValidLocked(); nativeThemeCopy(mObject, dstThemePtr, srcAssetManager.mObject, srcThemePtr); } } } @Override protected void finalize() throws Throwable { if (DEBUG_REFS && mNumRefs != 0) { Loading Loading @@ -1375,7 +1386,8 @@ public final class AssetManager implements AutoCloseable { private static native void nativeThemeDestroy(long themePtr); private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId, boolean force); static native void nativeThemeCopy(long destThemePtr, long sourceThemePtr); private static native void nativeThemeCopy(long dstAssetManagerPtr, long dstThemePtr, long srcAssetManagerPtr, long srcThemePtr); static native void nativeThemeClear(long themePtr); private static native int nativeThemeGetAttributeValue(long ptr, long themePtr, @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve); Loading core/java/android/content/res/ResourcesImpl.java +1 −1 Original line number Diff line number Diff line Loading @@ -1336,7 +1336,7 @@ public class ResourcesImpl { void setTo(ThemeImpl other) { synchronized (mKey) { synchronized (other.mKey) { AssetManager.nativeThemeCopy(mTheme, other.mTheme); mAssets.setThemeTo(mTheme, other.mAssets, other.mTheme); mThemeResId = other.mThemeResId; mKey.setTo(other.getKey()); Loading core/jni/android_util_AssetManager.cpp +18 −7 Original line number Diff line number Diff line Loading @@ -1208,13 +1208,23 @@ static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlon // jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str()); } static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_theme_ptr, jlong src_theme_ptr) { static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_asset_manager_ptr, jlong dst_theme_ptr, jlong src_asset_manager_ptr, jlong src_theme_ptr) { Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr); Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr); if (!dst_theme->SetTo(*src_theme)) { jniThrowException(env, "java/lang/IllegalArgumentException", "Themes are from different AssetManagers"); if (dst_asset_manager_ptr != src_asset_manager_ptr) { ScopedLock<AssetManager2> dst_assetmanager(AssetManagerFromLong(dst_asset_manager_ptr)); CHECK(dst_theme->GetAssetManager() == &(*dst_assetmanager)); (void) dst_assetmanager; ScopedLock <AssetManager2> src_assetmanager(AssetManagerFromLong(src_asset_manager_ptr)); CHECK(src_theme->GetAssetManager() == &(*src_assetmanager)); (void) src_assetmanager; dst_theme->SetTo(*src_theme); } else { dst_theme->SetTo(*src_theme); } } Loading Loading @@ -1255,10 +1265,11 @@ static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; (void) theme; (void) priority; (void) tag; (void) prefix; theme->Dump(); } static jint NativeThemeGetChangingConfigurations(JNIEnv* /*env*/, jclass /*clazz*/, Loading Loading @@ -1377,7 +1388,7 @@ static const JNINativeMethod gAssetManagerMethods[] = { {"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate}, {"nativeThemeDestroy", "(J)V", (void*)NativeThemeDestroy}, {"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle}, {"nativeThemeCopy", "(JJ)V", (void*)NativeThemeCopy}, {"nativeThemeCopy", "(JJJJ)V", (void*)NativeThemeCopy}, {"nativeThemeClear", "(J)V", (void*)NativeThemeClear}, {"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I", (void*)NativeThemeGetAttributeValue}, Loading libs/androidfw/AssetManager2.cpp +221 −22 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <algorithm> #include <iterator> #include <set> #include <map> #include "android-base/logging.h" #include "android-base/stringprintf.h" Loading Loading @@ -869,6 +870,17 @@ void AssetManager2::InvalidateCaches(uint32_t diff) { } } uint8_t AssetManager2::GetAssignedPackageId(const LoadedPackage* package) { for (auto& package_group : package_groups_) { for (auto& package2 : package_group.packages_) { if (package2.loaded_package_ == package) { return package_group.dynamic_ref_table.mAssignedPackageId; } } } return 0; } std::unique_ptr<Theme> AssetManager2::NewTheme() { return std::unique_ptr<Theme>(new Theme(this)); } Loading Loading @@ -1054,18 +1066,18 @@ void Theme::Clear() { } } bool Theme::SetTo(const Theme& o) { void Theme::SetTo(const Theme& o) { if (this == &o) { return true; return; } type_spec_flags_ = o.type_spec_flags_; const bool copy_only_system = asset_manager_ != o.asset_manager_; if (asset_manager_ == o.asset_manager_) { // The theme comes from the same asset manager so all theme data can be copied exactly for (size_t p = 0; p < packages_.size(); p++) { const Package *package = o.packages_[p].get(); if (package == nullptr || (copy_only_system && p != 0x01)) { if (package == nullptr) { // The other theme doesn't have this package, clear ours. packages_[p].reset(); continue; Loading @@ -1091,7 +1103,194 @@ bool Theme::SetTo(const Theme& o) { packages_[p]->types[t].reset(reinterpret_cast<ThemeType *>(copied_data)); } } return true; } else { std::map<ApkAssetsCookie, ApkAssetsCookie> src_to_dest_asset_cookies; typedef std::map<int, int> SourceToDestinationRuntimePackageMap; std::map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map; // Determine which ApkAssets are loaded in both theme AssetManagers std::vector<const ApkAssets*> src_assets = o.asset_manager_->GetApkAssets(); for (size_t i = 0; i < src_assets.size(); i++) { const ApkAssets* src_asset = src_assets[i]; std::vector<const ApkAssets*> dest_assets = asset_manager_->GetApkAssets(); for (size_t j = 0; j < dest_assets.size(); j++) { const ApkAssets* dest_asset = dest_assets[j]; // Map the runtime package of the source apk asset to the destination apk asset if (src_asset->GetPath() == dest_asset->GetPath()) { const std::vector<std::unique_ptr<const LoadedPackage>>& src_packages = src_asset->GetLoadedArsc()->GetPackages(); const std::vector<std::unique_ptr<const LoadedPackage>>& dest_packages = dest_asset->GetLoadedArsc()->GetPackages(); SourceToDestinationRuntimePackageMap package_map; // The source and destination package should have the same number of packages loaded in // the same order. const size_t N = src_packages.size(); CHECK(N == dest_packages.size()) << " LoadedArsc " << src_asset->GetPath() << " differs number of packages."; for (size_t p = 0; p < N; p++) { auto& src_package = src_packages[p]; auto& dest_package = dest_packages[p]; CHECK(src_package->GetPackageName() == dest_package->GetPackageName()) << " Package " << src_package->GetPackageName() << " differs in load order."; int src_package_id = o.asset_manager_->GetAssignedPackageId(src_package.get()); int dest_package_id = asset_manager_->GetAssignedPackageId(dest_package.get()); package_map[src_package_id] = dest_package_id; } src_to_dest_asset_cookies.insert(std::pair<ApkAssetsCookie, ApkAssetsCookie>(i, j)); src_asset_cookie_id_map.insert( std::pair<ApkAssetsCookie, SourceToDestinationRuntimePackageMap>(i, package_map)); break; } } } // Reset the data in the destination theme for (size_t p = 0; p < packages_.size(); p++) { if (packages_[p] != nullptr) { packages_[p].reset(); } } for (size_t p = 0; p < packages_.size(); p++) { const Package *package = o.packages_[p].get(); if (package == nullptr) { continue; } for (size_t t = 0; t < package->types.size(); t++) { const ThemeType *type = package->types[t].get(); if (type == nullptr) { continue; } for (size_t e = 0; e < type->entry_count; e++) { const ThemeEntry &entry = type->entries[e]; if (entry.value.dataType == Res_value::TYPE_NULL && entry.value.data != Res_value::DATA_NULL_EMPTY) { continue; } // The package id of the attribute needs to be rewritten to the package id of the value in // the destination int attribute_dest_package_id = p; if (attribute_dest_package_id != 0x01) { // Find the cookie of the attribute resource id FindEntryResult attribute_entry_result; ApkAssetsCookie attribute_cookie = o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ , false, &attribute_entry_result); // Determine the package id of the attribute in the destination AssetManager auto attribute_package_map = src_asset_cookie_id_map.find(attribute_cookie); if (attribute_package_map == src_asset_cookie_id_map.end()) { continue; } auto attribute_dest_package = attribute_package_map->second.find( attribute_dest_package_id); if (attribute_dest_package == attribute_package_map->second.end()) { continue; } attribute_dest_package_id = attribute_dest_package->second; } // If the attribute value represents an attribute or reference, the package id of the // value needs to be rewritten to the package id of the value in the destination uint32_t attribue_data = entry.value.data; if (entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE || entry.value.dataType == Res_value::TYPE_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_REFERENCE) { // Determine the package id of the reference in the destination AssetManager auto value_package_map = src_asset_cookie_id_map.find(entry.cookie); if (value_package_map == src_asset_cookie_id_map.end()) { continue; } auto value_dest_package = value_package_map->second.find( get_package_id(entry.value.data)); if (value_dest_package == value_package_map->second.end()) { continue; } attribue_data = fix_package_id(entry.value.data, value_dest_package->second); } // Lazily instantiate the destination package std::unique_ptr<Package>& dest_package = packages_[attribute_dest_package_id]; if (dest_package == nullptr) { dest_package.reset(new Package()); } // Lazily instantiate and resize the destination type util::unique_cptr<ThemeType>& dest_type = dest_package->types[t]; if (dest_type == nullptr || dest_type->entry_count < type->entry_count) { const size_t type_alloc_size = sizeof(ThemeType) + (type->entry_count * sizeof(ThemeEntry)); void* dest_data = malloc(type_alloc_size); memset(dest_data, 0, type->entry_count * sizeof(ThemeEntry)); // Copy the existing destination type values if the type is resized if (dest_type != nullptr) { memcpy(dest_data, type, sizeof(ThemeType) + (dest_type->entry_count * sizeof(ThemeEntry))); } dest_type.reset(reinterpret_cast<ThemeType *>(dest_data)); dest_type->entry_count = type->entry_count; } // Find the cookie of the value in the destination auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie); if (value_dest_cookie == src_to_dest_asset_cookies.end()) { continue; } dest_type->entries[e].cookie = value_dest_cookie->second; dest_type->entries[e].value.dataType = entry.value.dataType; dest_type->entries[e].value.data = attribue_data; dest_type->entries[e].type_spec_flags = entry.type_spec_flags; } } } } } void Theme::Dump() const { base::ScopedLogSeverity _log(base::INFO); LOG(INFO) << base::StringPrintf("Theme(this=%p, AssetManager2=%p)", this, asset_manager_); for (int p = 0; p < packages_.size(); p++) { auto& package = packages_[p]; if (package == nullptr) { continue; } for (int t = 0; t < package->types.size(); t++) { auto& type = package->types[t]; if (type == nullptr) { continue; } for (int e = 0; e < type->entry_count; e++) { auto& entry = type->entries[e]; if (entry.value.dataType == Res_value::TYPE_NULL && entry.value.data != Res_value::DATA_NULL_EMPTY) { continue; } LOG(INFO) << base::StringPrintf(" entry(0x%08x)=(0x%08x) type=(0x%02x), cookie(%d)", make_resid(p, t, e), entry.value.data, entry.value.dataType, entry.cookie); } } } } } // namespace android libs/androidfw/include/androidfw/AssetManager2.h +10 −2 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ struct FindEntryResult; // AssetManager2 is the main entry point for accessing assets and resources. // AssetManager2 provides caching of resources retrieved via the underlying ApkAssets. class AssetManager2 { friend Theme; public: struct ResourceName { const char* package = nullptr; Loading Loading @@ -285,6 +287,9 @@ class AssetManager2 { // been seen while traversing bag parents. const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids); // Retrieve the assigned package id of the package if loaded into this AssetManager uint8_t GetAssignedPackageId(const LoadedPackage* package); // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must // have a longer lifetime. std::vector<const ApkAssets*> apk_assets_; Loading Loading @@ -355,11 +360,14 @@ class Theme { bool ApplyStyle(uint32_t resid, bool force = false); // Sets this Theme to be a copy of `o` if `o` has the same AssetManager as this Theme. // Returns false if the AssetManagers of the Themes were not compatible. bool SetTo(const Theme& o); // If `o` does not have the same AssetManager as this theme, only attributes from ApkAssets loaded // into both AssetManagers will be copied to this theme. void SetTo(const Theme& o); void Clear(); void Dump() const; inline const AssetManager2* GetAssetManager() const { return asset_manager_; } Loading Loading
core/java/android/content/res/AssetManager.java +13 −1 Original line number Diff line number Diff line Loading @@ -1064,6 +1064,17 @@ public final class AssetManager implements AutoCloseable { } } @UnsupportedAppUsage void setThemeTo(long dstThemePtr, @NonNull AssetManager srcAssetManager, long srcThemePtr) { synchronized (this) { ensureValidLocked(); synchronized (srcAssetManager) { srcAssetManager.ensureValidLocked(); nativeThemeCopy(mObject, dstThemePtr, srcAssetManager.mObject, srcThemePtr); } } } @Override protected void finalize() throws Throwable { if (DEBUG_REFS && mNumRefs != 0) { Loading Loading @@ -1375,7 +1386,8 @@ public final class AssetManager implements AutoCloseable { private static native void nativeThemeDestroy(long themePtr); private static native void nativeThemeApplyStyle(long ptr, long themePtr, @StyleRes int resId, boolean force); static native void nativeThemeCopy(long destThemePtr, long sourceThemePtr); private static native void nativeThemeCopy(long dstAssetManagerPtr, long dstThemePtr, long srcAssetManagerPtr, long srcThemePtr); static native void nativeThemeClear(long themePtr); private static native int nativeThemeGetAttributeValue(long ptr, long themePtr, @AttrRes int resId, @NonNull TypedValue outValue, boolean resolve); Loading
core/java/android/content/res/ResourcesImpl.java +1 −1 Original line number Diff line number Diff line Loading @@ -1336,7 +1336,7 @@ public class ResourcesImpl { void setTo(ThemeImpl other) { synchronized (mKey) { synchronized (other.mKey) { AssetManager.nativeThemeCopy(mTheme, other.mTheme); mAssets.setThemeTo(mTheme, other.mAssets, other.mTheme); mThemeResId = other.mThemeResId; mKey.setTo(other.getKey()); Loading
core/jni/android_util_AssetManager.cpp +18 −7 Original line number Diff line number Diff line Loading @@ -1208,13 +1208,23 @@ static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlon // jniThrowException(env, "java/lang/IllegalArgumentException", error_msg.c_str()); } static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_theme_ptr, jlong src_theme_ptr) { static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_asset_manager_ptr, jlong dst_theme_ptr, jlong src_asset_manager_ptr, jlong src_theme_ptr) { Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr); Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr); if (!dst_theme->SetTo(*src_theme)) { jniThrowException(env, "java/lang/IllegalArgumentException", "Themes are from different AssetManagers"); if (dst_asset_manager_ptr != src_asset_manager_ptr) { ScopedLock<AssetManager2> dst_assetmanager(AssetManagerFromLong(dst_asset_manager_ptr)); CHECK(dst_theme->GetAssetManager() == &(*dst_assetmanager)); (void) dst_assetmanager; ScopedLock <AssetManager2> src_assetmanager(AssetManagerFromLong(src_asset_manager_ptr)); CHECK(src_theme->GetAssetManager() == &(*src_assetmanager)); (void) src_assetmanager; dst_theme->SetTo(*src_theme); } else { dst_theme->SetTo(*src_theme); } } Loading Loading @@ -1255,10 +1265,11 @@ static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; (void) theme; (void) priority; (void) tag; (void) prefix; theme->Dump(); } static jint NativeThemeGetChangingConfigurations(JNIEnv* /*env*/, jclass /*clazz*/, Loading Loading @@ -1377,7 +1388,7 @@ static const JNINativeMethod gAssetManagerMethods[] = { {"nativeThemeCreate", "(J)J", (void*)NativeThemeCreate}, {"nativeThemeDestroy", "(J)V", (void*)NativeThemeDestroy}, {"nativeThemeApplyStyle", "(JJIZ)V", (void*)NativeThemeApplyStyle}, {"nativeThemeCopy", "(JJ)V", (void*)NativeThemeCopy}, {"nativeThemeCopy", "(JJJJ)V", (void*)NativeThemeCopy}, {"nativeThemeClear", "(J)V", (void*)NativeThemeClear}, {"nativeThemeGetAttributeValue", "(JJILandroid/util/TypedValue;Z)I", (void*)NativeThemeGetAttributeValue}, Loading
libs/androidfw/AssetManager2.cpp +221 −22 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ #include <algorithm> #include <iterator> #include <set> #include <map> #include "android-base/logging.h" #include "android-base/stringprintf.h" Loading Loading @@ -869,6 +870,17 @@ void AssetManager2::InvalidateCaches(uint32_t diff) { } } uint8_t AssetManager2::GetAssignedPackageId(const LoadedPackage* package) { for (auto& package_group : package_groups_) { for (auto& package2 : package_group.packages_) { if (package2.loaded_package_ == package) { return package_group.dynamic_ref_table.mAssignedPackageId; } } } return 0; } std::unique_ptr<Theme> AssetManager2::NewTheme() { return std::unique_ptr<Theme>(new Theme(this)); } Loading Loading @@ -1054,18 +1066,18 @@ void Theme::Clear() { } } bool Theme::SetTo(const Theme& o) { void Theme::SetTo(const Theme& o) { if (this == &o) { return true; return; } type_spec_flags_ = o.type_spec_flags_; const bool copy_only_system = asset_manager_ != o.asset_manager_; if (asset_manager_ == o.asset_manager_) { // The theme comes from the same asset manager so all theme data can be copied exactly for (size_t p = 0; p < packages_.size(); p++) { const Package *package = o.packages_[p].get(); if (package == nullptr || (copy_only_system && p != 0x01)) { if (package == nullptr) { // The other theme doesn't have this package, clear ours. packages_[p].reset(); continue; Loading @@ -1091,7 +1103,194 @@ bool Theme::SetTo(const Theme& o) { packages_[p]->types[t].reset(reinterpret_cast<ThemeType *>(copied_data)); } } return true; } else { std::map<ApkAssetsCookie, ApkAssetsCookie> src_to_dest_asset_cookies; typedef std::map<int, int> SourceToDestinationRuntimePackageMap; std::map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map; // Determine which ApkAssets are loaded in both theme AssetManagers std::vector<const ApkAssets*> src_assets = o.asset_manager_->GetApkAssets(); for (size_t i = 0; i < src_assets.size(); i++) { const ApkAssets* src_asset = src_assets[i]; std::vector<const ApkAssets*> dest_assets = asset_manager_->GetApkAssets(); for (size_t j = 0; j < dest_assets.size(); j++) { const ApkAssets* dest_asset = dest_assets[j]; // Map the runtime package of the source apk asset to the destination apk asset if (src_asset->GetPath() == dest_asset->GetPath()) { const std::vector<std::unique_ptr<const LoadedPackage>>& src_packages = src_asset->GetLoadedArsc()->GetPackages(); const std::vector<std::unique_ptr<const LoadedPackage>>& dest_packages = dest_asset->GetLoadedArsc()->GetPackages(); SourceToDestinationRuntimePackageMap package_map; // The source and destination package should have the same number of packages loaded in // the same order. const size_t N = src_packages.size(); CHECK(N == dest_packages.size()) << " LoadedArsc " << src_asset->GetPath() << " differs number of packages."; for (size_t p = 0; p < N; p++) { auto& src_package = src_packages[p]; auto& dest_package = dest_packages[p]; CHECK(src_package->GetPackageName() == dest_package->GetPackageName()) << " Package " << src_package->GetPackageName() << " differs in load order."; int src_package_id = o.asset_manager_->GetAssignedPackageId(src_package.get()); int dest_package_id = asset_manager_->GetAssignedPackageId(dest_package.get()); package_map[src_package_id] = dest_package_id; } src_to_dest_asset_cookies.insert(std::pair<ApkAssetsCookie, ApkAssetsCookie>(i, j)); src_asset_cookie_id_map.insert( std::pair<ApkAssetsCookie, SourceToDestinationRuntimePackageMap>(i, package_map)); break; } } } // Reset the data in the destination theme for (size_t p = 0; p < packages_.size(); p++) { if (packages_[p] != nullptr) { packages_[p].reset(); } } for (size_t p = 0; p < packages_.size(); p++) { const Package *package = o.packages_[p].get(); if (package == nullptr) { continue; } for (size_t t = 0; t < package->types.size(); t++) { const ThemeType *type = package->types[t].get(); if (type == nullptr) { continue; } for (size_t e = 0; e < type->entry_count; e++) { const ThemeEntry &entry = type->entries[e]; if (entry.value.dataType == Res_value::TYPE_NULL && entry.value.data != Res_value::DATA_NULL_EMPTY) { continue; } // The package id of the attribute needs to be rewritten to the package id of the value in // the destination int attribute_dest_package_id = p; if (attribute_dest_package_id != 0x01) { // Find the cookie of the attribute resource id FindEntryResult attribute_entry_result; ApkAssetsCookie attribute_cookie = o.asset_manager_->FindEntry(make_resid(p, t, e), 0 /* density_override */ , false, &attribute_entry_result); // Determine the package id of the attribute in the destination AssetManager auto attribute_package_map = src_asset_cookie_id_map.find(attribute_cookie); if (attribute_package_map == src_asset_cookie_id_map.end()) { continue; } auto attribute_dest_package = attribute_package_map->second.find( attribute_dest_package_id); if (attribute_dest_package == attribute_package_map->second.end()) { continue; } attribute_dest_package_id = attribute_dest_package->second; } // If the attribute value represents an attribute or reference, the package id of the // value needs to be rewritten to the package id of the value in the destination uint32_t attribue_data = entry.value.data; if (entry.value.dataType == Res_value::TYPE_DYNAMIC_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE || entry.value.dataType == Res_value::TYPE_ATTRIBUTE || entry.value.dataType == Res_value::TYPE_REFERENCE) { // Determine the package id of the reference in the destination AssetManager auto value_package_map = src_asset_cookie_id_map.find(entry.cookie); if (value_package_map == src_asset_cookie_id_map.end()) { continue; } auto value_dest_package = value_package_map->second.find( get_package_id(entry.value.data)); if (value_dest_package == value_package_map->second.end()) { continue; } attribue_data = fix_package_id(entry.value.data, value_dest_package->second); } // Lazily instantiate the destination package std::unique_ptr<Package>& dest_package = packages_[attribute_dest_package_id]; if (dest_package == nullptr) { dest_package.reset(new Package()); } // Lazily instantiate and resize the destination type util::unique_cptr<ThemeType>& dest_type = dest_package->types[t]; if (dest_type == nullptr || dest_type->entry_count < type->entry_count) { const size_t type_alloc_size = sizeof(ThemeType) + (type->entry_count * sizeof(ThemeEntry)); void* dest_data = malloc(type_alloc_size); memset(dest_data, 0, type->entry_count * sizeof(ThemeEntry)); // Copy the existing destination type values if the type is resized if (dest_type != nullptr) { memcpy(dest_data, type, sizeof(ThemeType) + (dest_type->entry_count * sizeof(ThemeEntry))); } dest_type.reset(reinterpret_cast<ThemeType *>(dest_data)); dest_type->entry_count = type->entry_count; } // Find the cookie of the value in the destination auto value_dest_cookie = src_to_dest_asset_cookies.find(entry.cookie); if (value_dest_cookie == src_to_dest_asset_cookies.end()) { continue; } dest_type->entries[e].cookie = value_dest_cookie->second; dest_type->entries[e].value.dataType = entry.value.dataType; dest_type->entries[e].value.data = attribue_data; dest_type->entries[e].type_spec_flags = entry.type_spec_flags; } } } } } void Theme::Dump() const { base::ScopedLogSeverity _log(base::INFO); LOG(INFO) << base::StringPrintf("Theme(this=%p, AssetManager2=%p)", this, asset_manager_); for (int p = 0; p < packages_.size(); p++) { auto& package = packages_[p]; if (package == nullptr) { continue; } for (int t = 0; t < package->types.size(); t++) { auto& type = package->types[t]; if (type == nullptr) { continue; } for (int e = 0; e < type->entry_count; e++) { auto& entry = type->entries[e]; if (entry.value.dataType == Res_value::TYPE_NULL && entry.value.data != Res_value::DATA_NULL_EMPTY) { continue; } LOG(INFO) << base::StringPrintf(" entry(0x%08x)=(0x%08x) type=(0x%02x), cookie(%d)", make_resid(p, t, e), entry.value.data, entry.value.dataType, entry.cookie); } } } } } // namespace android
libs/androidfw/include/androidfw/AssetManager2.h +10 −2 Original line number Diff line number Diff line Loading @@ -74,6 +74,8 @@ struct FindEntryResult; // AssetManager2 is the main entry point for accessing assets and resources. // AssetManager2 provides caching of resources retrieved via the underlying ApkAssets. class AssetManager2 { friend Theme; public: struct ResourceName { const char* package = nullptr; Loading Loading @@ -285,6 +287,9 @@ class AssetManager2 { // been seen while traversing bag parents. const ResolvedBag* GetBag(uint32_t resid, std::vector<uint32_t>& child_resids); // Retrieve the assigned package id of the package if loaded into this AssetManager uint8_t GetAssignedPackageId(const LoadedPackage* package); // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must // have a longer lifetime. std::vector<const ApkAssets*> apk_assets_; Loading Loading @@ -355,11 +360,14 @@ class Theme { bool ApplyStyle(uint32_t resid, bool force = false); // Sets this Theme to be a copy of `o` if `o` has the same AssetManager as this Theme. // Returns false if the AssetManagers of the Themes were not compatible. bool SetTo(const Theme& o); // If `o` does not have the same AssetManager as this theme, only attributes from ApkAssets loaded // into both AssetManagers will be copied to this theme. void SetTo(const Theme& o); void Clear(); void Dump() const; inline const AssetManager2* GetAssetManager() const { return asset_manager_; } Loading