diff options
-rw-r--r-- | core/jni/android_util_AssetManager.cpp | 154 | ||||
-rw-r--r-- | libs/androidfw/AssetManager2.cpp | 137 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/AssetManager2.h | 31 | ||||
-rw-r--r-- | libs/androidfw/tests/AssetManager2_test.cpp | 32 | ||||
-rw-r--r-- | libs/androidfw/tests/Idmap_test.cpp | 4 | ||||
-rw-r--r-- | tools/aapt2/process/SymbolTable.cpp | 3 |
6 files changed, 243 insertions, 118 deletions
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp index 3d1d1433ba1c..fc53a766b772 100644 --- a/core/jni/android_util_AssetManager.cpp +++ b/core/jni/android_util_AssetManager.cpp @@ -17,6 +17,9 @@ #define ATRACE_TAG ATRACE_TAG_RESOURCES #define LOG_TAG "asset" +#include "android_runtime/android_util_AssetManager.h" + +#include <errno.h> #include <inttypes.h> #include <linux/capability.h> #include <stdio.h> @@ -31,7 +34,7 @@ #include "android-base/logging.h" #include "android-base/properties.h" #include "android-base/stringprintf.h" -#include "android_runtime/android_util_AssetManager.h" +#include "android_content_res_ApkAssets.h" #include "android_runtime/AndroidRuntime.h" #include "android_util_Binder.h" #include "androidfw/Asset.h" @@ -39,11 +42,9 @@ #include "androidfw/AssetManager2.h" #include "androidfw/AttributeResolution.h" #include "androidfw/MutexGuard.h" -#include <androidfw/ResourceTimer.h> +#include "androidfw/ResourceTimer.h" #include "androidfw/ResourceTypes.h" #include "androidfw/ResourceUtils.h" - -#include "android_content_res_ApkAssets.h" #include "core_jni_helpers.h" #include "jni.h" #include "nativehelper/JNIPlatformHelp.h" @@ -161,9 +162,30 @@ static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) { return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr)); } +struct ScopedLockedAssetsOperation { + ScopedLockedAssetsOperation(Guarded<AssetManager2>& guarded_am) + : am_(guarded_am), op_(am_->StartOperation()) {} + + AssetManager2& operator*() { return *am_; } + + AssetManager2* operator->() { return am_.get(); } + + AssetManager2* get() { return am_.get(); } + + private: + DISALLOW_COPY_AND_ASSIGN(ScopedLockedAssetsOperation); + + ScopedLock<AssetManager2> am_; + AssetManager2::ScopedOperation op_; +}; + +ScopedLockedAssetsOperation LockAndStartAssetManager(jlong ptr) { + return ScopedLockedAssetsOperation(AssetManagerFromLong(ptr)); +} + static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring package_name) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); const ScopedUtfChars package_name_utf8(env, package_name); CHECK(package_name_utf8.c_str() != nullptr); const std::string std_package_name(package_name_utf8.c_str()); @@ -209,7 +231,7 @@ static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr, static jstring NativeGetOverlayablesToString(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring package_name) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); const ScopedUtfChars package_name_utf8(env, package_name); CHECK(package_name_utf8.c_str() != nullptr); const std::string std_package_name(package_name_utf8.c_str()); @@ -320,7 +342,7 @@ static void NativeSetApkAssets(JNIEnv* env, jclass /*clazz*/, jlong ptr, apk_assets.emplace_back(*scoped_assets); } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); assetmanager->SetApkAssets(apk_assets, invalidate_caches); } @@ -370,14 +392,14 @@ static void NativeSetConfiguration(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin configuration.screenLayout2 = static_cast<uint8_t>((screen_layout & kScreenLayoutRoundMask) >> kScreenLayoutRoundShift); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); assetmanager->SetConfiguration(configuration); } static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/, jlong ptr, jboolean includeOverlays, jboolean includeLoaders) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); jobject sparse_array = env->NewObject(gSparseArrayOffsets.classObject, gSparseArrayOffsets.constructor); @@ -407,7 +429,7 @@ static jobject NativeGetAssignedPackageIdentifiers(JNIEnv* env, jclass /*clazz*/ } static jboolean ContainsAllocatedTable(JNIEnv* env, jclass /*clazz*/, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); return assetmanager->ContainsAllocatedTable(); } @@ -418,7 +440,7 @@ static jobjectArray NativeList(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring return nullptr; } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<AssetDir> asset_dir = assetmanager->OpenDir(path_utf8.c_str()); if (asset_dir == nullptr) { @@ -466,7 +488,7 @@ static jlong NativeOpenAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring a return 0; } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), static_cast<Asset::AccessMode>(access_mode)); if (!asset) { @@ -486,7 +508,7 @@ static jobject NativeOpenAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstri ATRACE_NAME(base::StringPrintf("AssetManager::OpenAssetFd(%s)", asset_path_utf8.c_str()).c_str()); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset = assetmanager->Open(asset_path_utf8.c_str(), Asset::ACCESS_RANDOM); if (!asset) { jniThrowException(env, "java/io/FileNotFoundException", asset_path_utf8.c_str()); @@ -512,7 +534,7 @@ static jlong NativeOpenNonAsset(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint j return 0; } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset; if (cookie != kInvalidCookie) { asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, @@ -540,7 +562,7 @@ static jobject NativeOpenNonAssetFd(JNIEnv* env, jclass /*clazz*/, jlong ptr, ji ATRACE_NAME(base::StringPrintf("AssetManager::OpenNonAssetFd(%s)", asset_path_utf8.c_str()).c_str()); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset; if (cookie != kInvalidCookie) { asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM); @@ -566,7 +588,7 @@ static jlong NativeOpenXmlAsset(JNIEnv* env, jobject /*clazz*/, jlong ptr, jint ATRACE_NAME(base::StringPrintf("AssetManager::OpenXmlAsset(%s)", asset_path_utf8.c_str()).c_str()); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::unique_ptr<Asset> asset; if (cookie != kInvalidCookie) { asset = assetmanager->OpenNonAsset(asset_path_utf8.c_str(), cookie, Asset::ACCESS_RANDOM); @@ -614,7 +636,8 @@ static jlong NativeOpenXmlAssetFd(JNIEnv* env, jobject /*clazz*/, jlong ptr, int std::unique_ptr<Asset> asset(Asset::createFromFd(dup_fd.release(), nullptr, Asset::AccessMode::ACCESS_BUFFER)); - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + ApkAssetsCookie cookie = JavaCookieToApkAssetsCookie(jcookie); const incfs::map_ptr<void> buffer = asset->getIncFsBuffer(true /* aligned */); @@ -637,8 +660,9 @@ static jlong NativeOpenXmlAssetFd(JNIEnv* env, jobject /*clazz*/, jlong ptr, int static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid, jshort density, jobject typed_value, jboolean resolve_references) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); ResourceTimer _timer(ResourceTimer::Counter::GetResourceValue); + auto value = assetmanager->GetResource(static_cast<uint32_t>(resid), false /*may_be_bag*/, static_cast<uint16_t>(density)); if (!value.has_value()) { @@ -656,7 +680,8 @@ static jint NativeGetResourceValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid, jint bag_entry_id, jobject typed_value) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag.has_value()) { return ApkAssetsCookieToJavaCookie(kInvalidCookie); @@ -683,7 +708,8 @@ static jint NativeGetResourceBagValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, } static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -704,7 +730,8 @@ static jintArray NativeGetStyleAttributes(JNIEnv* env, jclass /*clazz*/, jlong p static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -725,8 +752,8 @@ static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, } if (attr_value.type == Res_value::TYPE_STRING) { - auto apk_assets_weak = assetmanager->GetApkAssets()[attr_value.cookie]; - if (auto apk_assets = apk_assets_weak.promote()) { + const auto& apk_assets = assetmanager->GetApkAssets(attr_value.cookie); + if (apk_assets) { const ResStringPool* pool = apk_assets->GetLoadedArsc()->GetStringPool(); jstring java_string; @@ -762,7 +789,8 @@ static jobjectArray NativeGetResourceStringArray(JNIEnv* env, jclass /*clazz*/, static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -800,7 +828,8 @@ static jintArray NativeGetResourceStringArrayInfo(JNIEnv* env, jclass /*clazz*/, } static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); if (!bag_result.has_value()) { return nullptr; @@ -835,21 +864,22 @@ static jintArray NativeGetResourceIntArray(JNIEnv* env, jclass /*clazz*/, jlong } static jint NativeGetResourceArraySize(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); - auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid)); - if (!bag.has_value()) { - return -1; - } + auto assetmanager = LockAndStartAssetManager(ptr); + auto bag = assetmanager->GetBag(static_cast<uint32_t>(resid)); + if (!bag.has_value()) { + return -1; + } return static_cast<jint>((*bag)->entry_count); } static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid, jintArray out_data) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); - auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); - if (!bag_result.has_value()) { + auto assetmanager = LockAndStartAssetManager(ptr); + + auto bag_result = assetmanager->GetBag(static_cast<uint32_t>(resid)); + if (!bag_result.has_value()) { return -1; - } + } const jsize out_data_length = env->GetArrayLength(out_data); if (env->ExceptionCheck()) { @@ -896,7 +926,7 @@ static jint NativeGetResourceArray(JNIEnv* env, jclass /*clazz*/, jlong ptr, jin } static jint NativeGetParentThemeIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); const auto parentThemeResId = assetmanager->GetParentThemeResourceId(resid); return parentThemeResId.value_or(0); } @@ -923,7 +953,7 @@ static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr package = package_utf8.c_str(); } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto resid = assetmanager->GetResourceId(name_utf8.c_str(), type, package); if (!resid.has_value()) { return 0; @@ -933,7 +963,7 @@ static jint NativeGetResourceIdentifier(JNIEnv* env, jclass /*clazz*/, jlong ptr } static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -944,7 +974,7 @@ static jstring NativeGetResourceName(JNIEnv* env, jclass /*clazz*/, jlong ptr, j } static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -957,7 +987,7 @@ static jstring NativeGetResourcePackageName(JNIEnv* env, jclass /*clazz*/, jlong } static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -972,7 +1002,7 @@ static jstring NativeGetResourceTypeName(JNIEnv* env, jclass /*clazz*/, jlong pt } static jstring NativeGetResourceEntryName(JNIEnv* env, jclass /*clazz*/, jlong ptr, jint resid) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto name = assetmanager->GetResourceName(static_cast<uint32_t>(resid)); if (!name.has_value()) { return nullptr; @@ -990,14 +1020,14 @@ static void NativeSetResourceResolutionLoggingEnabled(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jboolean enabled) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); assetmanager->SetResourceResolutionLoggingEnabled(enabled); } static jstring NativeGetLastResourceResolution(JNIEnv* env, jclass /*clazz*/, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::string resolution = assetmanager->GetLastResourceResolution(); if (resolution.empty()) { return nullptr; @@ -1008,7 +1038,7 @@ static jstring NativeGetLastResourceResolution(JNIEnv* env, static jobjectArray NativeGetLocales(JNIEnv* env, jclass /*class*/, jlong ptr, jboolean exclude_system) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); std::set<std::string> locales = assetmanager->GetResourceLocales(exclude_system, true /*merge_equivalent_languages*/); @@ -1046,7 +1076,7 @@ static jobject ConstructConfigurationObject(JNIEnv* env, const ResTable_config& } static jobjectArray GetSizeAndUiModeConfigurations(JNIEnv* env, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); auto configurations = assetmanager->GetResourceConfigurations(true /*exclude_system*/, false /*exclude_mipmap*/); if (!configurations.has_value()) { @@ -1080,12 +1110,10 @@ static jobjectArray NativeGetSizeAndUiModeConfigurations(JNIEnv* env, jclass /*c return GetSizeAndUiModeConfigurations(env, ptr); } -static jintArray NativeAttributeResolutionStack( - JNIEnv* env, jclass /*clazz*/, jlong ptr, - jlong theme_ptr, jint xml_style_res, - jint def_style_attr, jint def_style_resid) { - - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); +static jintArray NativeAttributeResolutionStack(JNIEnv* env, jclass /*clazz*/, jlong ptr, + jlong theme_ptr, jint xml_style_res, + jint def_style_attr, jint def_style_resid) { + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1120,7 +1148,7 @@ static jintArray NativeAttributeResolutionStack( static void NativeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint def_style_attr, jint def_style_resid, jlong xml_parser_ptr, jintArray java_attrs, jlong out_values_ptr, jlong out_indices_ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1195,7 +1223,7 @@ static jboolean NativeResolveAttrs(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlo } } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1254,7 +1282,7 @@ static jboolean NativeRetrieveAttributes(JNIEnv* env, jclass /*clazz*/, jlong pt } } - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); ResourceTimer _timer(ResourceTimer::Counter::RetrieveAttributes); ResXMLParser* xml_parser = reinterpret_cast<ResXMLParser*>(xml_parser_ptr); auto result = @@ -1272,7 +1300,7 @@ static jboolean NativeRetrieveAttributes(JNIEnv* env, jclass /*clazz*/, jlong pt } static jlong NativeThemeCreate(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); return reinterpret_cast<jlong>(assetmanager->NewTheme().release()); } @@ -1287,7 +1315,7 @@ static jlong NativeGetThemeFreeFunction(JNIEnv* /*env*/, jclass /*clazz*/) { static void NativeThemeApplyStyle(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint resid, jboolean force) { // AssetManager is accessed via the theme, so grab an explicit lock here. - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1305,7 +1333,7 @@ static void NativeThemeRebase(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong th jint style_count) { // Lock both the original asset manager of the theme and the new asset manager to be used for the // theme. - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); uint32_t* style_id_args = nullptr; if (style_ids != nullptr) { @@ -1348,25 +1376,23 @@ static void NativeThemeCopy(JNIEnv* env, jclass /*clazz*/, jlong dst_asset_manag Theme* dst_theme = reinterpret_cast<Theme*>(dst_theme_ptr); Theme* src_theme = reinterpret_cast<Theme*>(src_theme_ptr); - ScopedLock<AssetManager2> src_assetmanager(AssetManagerFromLong(src_asset_manager_ptr)); + auto src_assetmanager = LockAndStartAssetManager(src_asset_manager_ptr); CHECK(src_theme->GetAssetManager() == &(*src_assetmanager)); - (void) src_assetmanager; if (dst_asset_manager_ptr != src_asset_manager_ptr) { - ScopedLock<AssetManager2> dst_assetmanager(AssetManagerFromLong(dst_asset_manager_ptr)); + auto dst_assetmanager = LockAndStartAssetManager(dst_asset_manager_ptr); CHECK(dst_theme->GetAssetManager() == &(*dst_assetmanager)); - (void) dst_assetmanager; - dst_theme->SetTo(*src_theme); } else { - dst_theme->SetTo(*src_theme); + dst_theme->SetTo(*src_theme); } } static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint resid, jobject typed_value, jboolean resolve_references) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); + Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; @@ -1389,7 +1415,7 @@ static jint NativeThemeGetAttributeValue(JNIEnv* env, jclass /*clazz*/, jlong pt static void NativeThemeDump(JNIEnv* /*env*/, jclass /*clazz*/, jlong ptr, jlong theme_ptr, jint priority, jstring tag, jstring prefix) { - ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(ptr)); + auto assetmanager = LockAndStartAssetManager(ptr); Theme* theme = reinterpret_cast<Theme*>(theme_ptr); CHECK(theme->GetAssetManager() == &(*assetmanager)); (void) assetmanager; diff --git a/libs/androidfw/AssetManager2.cpp b/libs/androidfw/AssetManager2.cpp index 3a7c91ef5b08..d33b592bddc6 100644 --- a/libs/androidfw/AssetManager2.cpp +++ b/libs/androidfw/AssetManager2.cpp @@ -112,7 +112,15 @@ bool AssetManager2::SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, } void AssetManager2::BuildDynamicRefTable(ApkAssetsList apk_assets) { - apk_assets_.assign(apk_assets.begin(), apk_assets.end()); + auto op = StartOperation(); + + apk_assets_.resize(apk_assets.size()); + for (size_t i = 0; i != apk_assets.size(); ++i) { + apk_assets_[i].first = apk_assets[i]; + // Let's populate the locked assets right away as we're going to need them here later. + apk_assets_[i].second = apk_assets[i]; + } + package_groups_.clear(); package_ids_.fill(0xff); @@ -124,7 +132,7 @@ void AssetManager2::BuildDynamicRefTable(ApkAssetsList apk_assets) { // Overlay resources are not directly referenced by an application so their resource ids // can change throughout the application's lifetime. Assign overlay package ids last. std::vector<const ApkAssets*> sorted_apk_assets; - sorted_apk_assets.reserve(apk_assets_.size()); + sorted_apk_assets.reserve(apk_assets.size()); for (auto& asset : apk_assets) { sorted_apk_assets.push_back(asset.get()); } @@ -250,9 +258,10 @@ void AssetManager2::BuildDynamicRefTable(ApkAssetsList apk_assets) { void AssetManager2::DumpToLog() const { LOG(INFO) << base::StringPrintf("AssetManager2(this=%p)", this); + auto op = StartOperation(); std::string list; - for (const auto& apk_assets : apk_assets_) { - auto assets = apk_assets.promote(); + for (size_t i = 0; i < apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); base::StringAppendF(&list, "%s,", assets ? assets->GetDebugName().c_str() : "nullptr"); } LOG(INFO) << "ApkAssets: " << list; @@ -290,7 +299,8 @@ const ResStringPool* AssetManager2::GetStringPoolForCookie(ApkAssetsCookie cooki if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) { return nullptr; } - auto assets = apk_assets_[cookie].promote(); + auto op = StartOperation(); + const auto& assets = GetApkAssets(cookie); return assets ? assets->GetLoadedArsc()->GetStringPool() : nullptr; } @@ -341,9 +351,10 @@ const std::unordered_map<std::string, std::string>* bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name, std::string* out) const { + auto op = StartOperation(); uint8_t package_id = 0U; - for (const auto& apk_assets : apk_assets_) { - auto assets = apk_assets.promote(); + for (size_t i = 0; i != apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); if (!assets) { continue; } @@ -400,10 +411,14 @@ bool AssetManager2::GetOverlayablesToString(android::StringPiece package_name, } bool AssetManager2::ContainsAllocatedTable() const { - return std::find_if(apk_assets_.begin(), apk_assets_.end(), [](auto&& assets_weak) { - auto assets = assets_weak.promote(); - return assets && assets->IsTableAllocated(); - }) != apk_assets_.end(); + auto op = StartOperation(); + for (size_t i = 0; i != apk_assets_.size(); ++i) { + const auto& assets = GetApkAssets(i); + if (assets && assets->IsTableAllocated()) { + return true; + } + } + return false; } void AssetManager2::SetConfiguration(const ResTable_config& configuration) { @@ -428,8 +443,9 @@ std::set<AssetManager2::ApkAssetsPtr> AssetManager2::GetNonSystemOverlays() cons } if (!found_system_package) { + auto op = StartOperation(); for (const ConfiguredOverlay& overlay : package_group.overlays_) { - if (auto asset = apk_assets_[overlay.cookie].promote()) { + if (const auto& asset = GetApkAssets(overlay.cookie)) { non_system_overlays.insert(std::move(asset)); } } @@ -442,6 +458,8 @@ std::set<AssetManager2::ApkAssetsPtr> AssetManager2::GetNonSystemOverlays() cons base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceConfigurations( bool exclude_system, bool exclude_mipmap) const { ATRACE_NAME("AssetManager::GetResourceConfigurations"); + auto op = StartOperation(); + const auto non_system_overlays = exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>(); @@ -455,7 +473,7 @@ base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceCon } if (!non_system_overlays.empty()) { // Exclude overlays that target only system resources. - auto apk_assets = apk_assets_[package_group.cookies_[i]].promote(); + const auto& apk_assets = GetApkAssets(package_group.cookies_[i]); if (apk_assets && apk_assets->IsOverlay() && non_system_overlays.find(apk_assets) == non_system_overlays.end()) { continue; @@ -475,6 +493,8 @@ base::expected<std::set<ResTable_config>, IOError> AssetManager2::GetResourceCon std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system, bool merge_equivalent_languages) const { ATRACE_NAME("AssetManager::GetResourceLocales"); + auto op = StartOperation(); + std::set<std::string> locales; const auto non_system_overlays = exclude_system ? GetNonSystemOverlays() : std::set<ApkAssetsPtr>(); @@ -488,7 +508,7 @@ std::set<std::string> AssetManager2::GetResourceLocales(bool exclude_system, } if (!non_system_overlays.empty()) { // Exclude overlays that target only system resources. - auto apk_assets = apk_assets_[package_group.cookies_[i]].promote(); + const auto& apk_assets = GetApkAssets(package_group.cookies_[i]); if (apk_assets && apk_assets->IsOverlay() && non_system_overlays.find(apk_assets) == non_system_overlays.end()) { continue; @@ -516,13 +536,14 @@ std::unique_ptr<Asset> AssetManager2::Open(const std::string& filename, ApkAsset std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) const { ATRACE_NAME("AssetManager::OpenDir"); + auto op = StartOperation(); std::string full_path = "assets/" + dirname; auto files = util::make_unique<SortedVector<AssetDir::FileInfo>>(); // Start from the back. - for (auto iter = apk_assets_.rbegin(); iter != apk_assets_.rend(); ++iter) { - auto apk_assets = iter->promote(); + for (size_t i = apk_assets_.size(); i > 0; --i) { + const auto& apk_assets = GetApkAssets(i - 1); if (!apk_assets || apk_assets->IsOverlay()) { continue; } @@ -551,8 +572,9 @@ std::unique_ptr<AssetDir> AssetManager2::OpenDir(const std::string& dirname) con std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename, Asset::AccessMode mode, ApkAssetsCookie* out_cookie) const { - for (int32_t i = apk_assets_.size() - 1; i >= 0; i--) { - const auto assets = apk_assets_[i].promote(); + auto op = StartOperation(); + for (size_t i = apk_assets_.size(); i > 0; i--) { + const auto& assets = GetApkAssets(i - 1); // Prevent RRO from modifying assets and other entries accessed by file // path. Explicitly asking for a path in a given package (denoted by a // cookie) is still OK. @@ -581,7 +603,8 @@ std::unique_ptr<Asset> AssetManager2::OpenNonAsset(const std::string& filename, if (cookie < 0 || static_cast<size_t>(cookie) >= apk_assets_.size()) { return {}; } - auto assets = apk_assets_[cookie].promote(); + auto op = StartOperation(); + const auto& assets = GetApkAssets(cookie); return assets ? assets->GetAssetsProvider()->Open(filename, mode) : nullptr; } @@ -595,6 +618,8 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( last_resolution_.resid = resid; } + auto op = StartOperation(); + // Might use this if density_override != 0. ResTable_config density_override_config; @@ -631,7 +656,7 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntry( bool overlaid = false; if (!stop_at_first_match && !ignore_configuration) { - auto assets = apk_assets_[result->cookie].promote(); + const auto& assets = GetApkAssets(result->cookie); if (!assets) { ALOGE("Found expired ApkAssets #%d for resource ID 0x%08x.", result->cookie, resid); return base::unexpected(std::nullopt); @@ -873,13 +898,7 @@ base::expected<FindEntryResult, NullOrIOError> AssetManager2::FindEntryInternal( } void AssetManager2::ResetResourceResolution() const { - last_resolution_.cookie = kInvalidCookie; - last_resolution_.resid = 0; - last_resolution_.steps.clear(); - last_resolution_.type_string_ref = StringPoolRef(); - last_resolution_.entry_string_ref = StringPoolRef(); - last_resolution_.best_config_name.clear(); - last_resolution_.best_package_name.clear(); + last_resolution_ = Resolution{}; } void AssetManager2::SetResourceResolutionLoggingEnabled(bool enabled) { @@ -901,8 +920,10 @@ std::string AssetManager2::GetLastResourceResolution() const { return {}; } + auto op = StartOperation(); + const uint32_t resid = last_resolution_.resid; - auto assets = apk_assets_[cookie].promote(); + const auto& assets = GetApkAssets(cookie); const auto package = assets ? assets->GetLoadedArsc()->GetPackageById(get_package_id(resid)) : nullptr; @@ -934,7 +955,7 @@ std::string AssetManager2::GetLastResourceResolution() const { if (prefix == kStepStrings.end()) { continue; } - auto assets = apk_assets_[step.cookie].promote(); + const auto& assets = GetApkAssets(step.cookie); log_stream << "\n\t" << prefix->second << ": " << (assets ? assets->GetDebugName() : "<null>") << " #" << step.cookie; if (!step.config_name.isEmpty()) { @@ -1466,6 +1487,37 @@ void AssetManager2::ForEachPackage(base::function_ref<bool(const std::string&, u } } +AssetManager2::ScopedOperation AssetManager2::StartOperation() const { + ++number_of_running_scoped_operations_; + return ScopedOperation(*this); +} + +void AssetManager2::FinishOperation() const { + if (number_of_running_scoped_operations_ < 1) { + ALOGW("Invalid FinishOperation() call when there's none happening"); + return; + } + if (--number_of_running_scoped_operations_ == 0) { + for (auto&& [_, assets] : apk_assets_) { + assets.clear(); + } + } +} + +const AssetManager2::ApkAssetsPtr& AssetManager2::GetApkAssets(ApkAssetsCookie cookie) const { + DCHECK(number_of_running_scoped_operations_ > 0) << "Must have an operation running"; + + if (cookie < 0 || cookie >= apk_assets_.size()) { + static const ApkAssetsPtr empty{}; + return empty; + } + auto& [wptr, res] = apk_assets_[cookie]; + if (!res) { + res = wptr.promote(); + } + return res; +} + Theme::Theme(AssetManager2* asset_manager) : asset_manager_(asset_manager) { } @@ -1598,22 +1650,16 @@ base::expected<std::monostate, IOError> Theme::SetTo(const Theme& source) { using SourceToDestinationRuntimePackageMap = std::unordered_map<int, int>; std::unordered_map<ApkAssetsCookie, SourceToDestinationRuntimePackageMap> src_asset_cookie_id_map; - // Determine which ApkAssets are loaded in both theme AssetManagers. - const auto& src_assets = source.asset_manager_->GetApkAssets(); - const auto& dest_assets = asset_manager_->GetApkAssets(); - std::vector<AssetManager2::ApkAssetsPtr> promoted_src_assets; - promoted_src_assets.reserve(src_assets.size()); - for (const auto& src_asset : src_assets) { - promoted_src_assets.emplace_back(src_asset.promote()); - } + auto op_src = source.asset_manager_->StartOperation(); + auto op_dst = asset_manager_->StartOperation(); - for (size_t j = 0; j < dest_assets.size(); j++) { - auto dest_asset = dest_assets[j].promote(); - if (!dest_asset) { + for (size_t i = 0; i < source.asset_manager_->GetApkAssetsCount(); i++) { + const auto& src_asset = source.asset_manager_->GetApkAssets(i); + if (!src_asset) { continue; } - for (size_t i = 0; i < promoted_src_assets.size(); i++) { - const auto& src_asset = promoted_src_assets[i]; + for (int j = 0; j < asset_manager_->GetApkAssetsCount(); j++) { + const auto& dest_asset = asset_manager_->GetApkAssets(j); if (src_asset != dest_asset) { // ResourcesManager caches and reuses ApkAssets when the same apk must be present in // multiple AssetManagers. Two ApkAssets point to the same version of the same resources @@ -1739,4 +1785,11 @@ void Theme::Dump() const { } } +AssetManager2::ScopedOperation::ScopedOperation(const AssetManager2& am) : am_(am) { +} + +AssetManager2::ScopedOperation::~ScopedOperation() { + am_.FinishOperation(); +} + } // namespace android diff --git a/libs/androidfw/include/androidfw/AssetManager2.h b/libs/androidfw/include/androidfw/AssetManager2.h index e276cd211ee7..fc391bc2ce67 100644 --- a/libs/androidfw/include/androidfw/AssetManager2.h +++ b/libs/androidfw/include/androidfw/AssetManager2.h @@ -102,9 +102,20 @@ class AssetManager2 { AssetManager2() = default; explicit AssetManager2(AssetManager2&& other) = default; - AssetManager2(ApkAssetsList apk_assets, const ResTable_config& configuration); + struct ScopedOperation { + DISALLOW_COPY_AND_ASSIGN(ScopedOperation); + friend AssetManager2; + const AssetManager2& am_; + ScopedOperation(const AssetManager2& am); + + public: + ~ScopedOperation(); + }; + + [[nodiscard]] ScopedOperation StartOperation() const; + // Sets/resets the underlying ApkAssets for this AssetManager. The ApkAssets // are not owned by the AssetManager, and must have a longer lifetime. // @@ -114,8 +125,9 @@ class AssetManager2 { bool SetApkAssets(ApkAssetsList apk_assets, bool invalidate_caches = true); bool SetApkAssets(std::initializer_list<ApkAssetsPtr> apk_assets, bool invalidate_caches = true); - inline const std::vector<ApkAssetsWPtr>& GetApkAssets() const { - return apk_assets_; + const ApkAssetsPtr& GetApkAssets(ApkAssetsCookie cookie) const; + int GetApkAssetsCount() const { + return int(apk_assets_.size()); } // Returns the string pool for the given asset cookie. @@ -426,9 +438,16 @@ class AssetManager2 { base::expected<const ResolvedBag*, NullOrIOError> GetBag( uint32_t resid, std::vector<uint32_t>& child_resids) const; + // Finish an operation that was running with the current asset manager, and clean up the + // promoted apk assets when the last operation ends. + void FinishOperation() const; + // The ordered list of ApkAssets to search. These are not owned by the AssetManager, and must // have a longer lifetime. - std::vector<ApkAssetsWPtr> apk_assets_; + // The second pair element is the promoted version of the assets, that is held for the duration + // of the currently running operation. FinishOperation() clears all promoted assets to make sure + // they can be released when the system needs that. + mutable std::vector<std::pair<ApkAssetsWPtr, ApkAssetsPtr>> apk_assets_; // DynamicRefTables for shared library package resolution. // These are ordered according to apk_assets_. The mappings may change depending on what is @@ -455,6 +474,10 @@ class AssetManager2 { // Cached set of resolved resource values. mutable std::unordered_map<uint32_t, SelectedValue> cached_resolved_values_; + // Tracking the number of the started operations running with the current AssetManager. + // Finishing the last one clears all promoted apk assets. + mutable int number_of_running_scoped_operations_ = 0; + // Whether or not to save resource resolution steps bool resource_resolution_logging_enabled_ = false; diff --git a/libs/androidfw/tests/AssetManager2_test.cpp b/libs/androidfw/tests/AssetManager2_test.cpp index 5a5bafdf829a..df3fa02ce44c 100644 --- a/libs/androidfw/tests/AssetManager2_test.cpp +++ b/libs/androidfw/tests/AssetManager2_test.cpp @@ -207,11 +207,11 @@ TEST_F(AssetManager2Test, AssignsOverlayPackageIdLast) { AssetManager2 assetmanager; assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_}); - auto apk_assets = assetmanager.GetApkAssets(); - ASSERT_EQ(3, apk_assets.size()); - ASSERT_EQ(overlayable_assets_, apk_assets[0].promote()); - ASSERT_EQ(overlay_assets_, apk_assets[1].promote()); - ASSERT_EQ(lib_one_assets_, apk_assets[2].promote()); + ASSERT_EQ(3, assetmanager.GetApkAssetsCount()); + auto op = assetmanager.StartOperation(); + ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0)); + ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1)); + ASSERT_EQ(lib_one_assets_, assetmanager.GetApkAssets(2)); auto get_first_package_id = [&assetmanager](auto apkAssets) -> uint8_t { return assetmanager.GetAssignedPackageId(apkAssets->GetLoadedArsc()->GetPackages()[0].get()); @@ -834,4 +834,26 @@ TEST_F(AssetManager2Test, GetOverlayablesToString) { std::string::npos); } +TEST_F(AssetManager2Test, GetApkAssets) { + AssetManager2 assetmanager; + assetmanager.SetApkAssets({overlayable_assets_, overlay_assets_, lib_one_assets_}); + + ASSERT_EQ(3, assetmanager.GetApkAssetsCount()); + EXPECT_EQ(1, overlayable_assets_->getStrongCount()); + EXPECT_EQ(1, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); + + { + auto op = assetmanager.StartOperation(); + ASSERT_EQ(overlayable_assets_, assetmanager.GetApkAssets(0)); + ASSERT_EQ(overlay_assets_, assetmanager.GetApkAssets(1)); + EXPECT_EQ(2, overlayable_assets_->getStrongCount()); + EXPECT_EQ(2, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); + } + EXPECT_EQ(1, overlayable_assets_->getStrongCount()); + EXPECT_EQ(1, overlay_assets_->getStrongCount()); + EXPECT_EQ(1, lib_one_assets_->getStrongCount()); +} + } // namespace android diff --git a/libs/androidfw/tests/Idmap_test.cpp b/libs/androidfw/tests/Idmap_test.cpp index 568e041ebe5b..60aa7d88925d 100644 --- a/libs/androidfw/tests/Idmap_test.cpp +++ b/libs/androidfw/tests/Idmap_test.cpp @@ -66,9 +66,9 @@ class IdmapTest : public ::testing::Test { std::string GetStringFromApkAssets(const AssetManager2& asset_manager, const AssetManager2::SelectedValue& value) { - auto assets = asset_manager.GetApkAssets(); + auto op = asset_manager.StartOperation(); const ResStringPool* string_pool = - assets[value.cookie].promote()->GetLoadedArsc()->GetStringPool(); + asset_manager.GetApkAssets(value.cookie)->GetLoadedArsc()->GetStringPool(); return GetStringFromPool(string_pool, value.data); } diff --git a/tools/aapt2/process/SymbolTable.cpp b/tools/aapt2/process/SymbolTable.cpp index b75458a7b8b6..d78baf9ffeb4 100644 --- a/tools/aapt2/process/SymbolTable.cpp +++ b/tools/aapt2/process/SymbolTable.cpp @@ -260,10 +260,11 @@ bool AssetManagerSymbolSource::IsPackageDynamic(uint32_t packageId, static std::unique_ptr<SymbolTable::Symbol> LookupAttributeInTable( android::AssetManager2& am, ResourceId id) { using namespace android; - if (am.GetApkAssets().empty()) { + if (am.GetApkAssetsCount() == 0) { return {}; } + auto op = am.StartOperation(); auto bag_result = am.GetBag(id.id); if (!bag_result.has_value()) { return nullptr; |