Loading core/java/android/content/res/AssetManager.java +14 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import java.nio.channels.FileLock; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * Provides access to an application's raw asset files; see {@link Resources} Loading Loading @@ -1345,6 +1346,17 @@ public final class AssetManager implements AutoCloseable { } } /** * @hide */ @GuardedBy("this") public @Nullable Map<String, String> getOverlayableMap(String packageName) { synchronized (this) { ensureValidLocked(); return nativeGetOverlayableMap(mObject, packageName); } } @GuardedBy("this") private void incRefsLocked(long id) { if (DEBUG_REFS) { Loading Loading @@ -1462,6 +1474,8 @@ public final class AssetManager implements AutoCloseable { private static native void nativeVerifySystemIdmaps(); private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid(); private static native @Nullable Map nativeGetOverlayableMap(long ptr, @NonNull String packageName); // Global debug native methods. /** Loading core/jni/android_util_AssetManager.cpp +60 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,12 @@ static struct configuration_offsets_t { jfieldID mScreenHeightDpOffset; } gConfigurationOffsets; static struct arraymap_offsets_t { jclass classObject; jmethodID constructor; jmethodID put; } gArrayMapOffsets; jclass g_stringClass = nullptr; // ---------------------------------------------------------------------------- Loading Loading @@ -326,6 +332,50 @@ static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) { return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr)); } static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring package_name) { ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(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()); const std::unordered_map<std::string, std::string>* map = nullptr; assetmanager->ForEachPackage([&](const std::string& this_package_name, uint8_t package_id) { if (this_package_name == std_package_name) { map = assetmanager->GetOverlayableMapForPackage(package_id); } }); if (map == nullptr) { return nullptr; } jobject array_map = env->NewObject(gArrayMapOffsets.classObject, gArrayMapOffsets.constructor); if (array_map == nullptr) { return nullptr; } for (const auto& iter : *map) { jstring name = env->NewStringUTF(iter.first.c_str()); if (env->ExceptionCheck()) { return nullptr; } jstring actor = env->NewStringUTF(iter.second.c_str()); if (env->ExceptionCheck()) { env->DeleteLocalRef(name); return nullptr; } env->CallObjectMethod(array_map, gArrayMapOffsets.put, name, actor); env->DeleteLocalRef(name); env->DeleteLocalRef(actor); } return array_map; } static jobject ReturnParcelFileDescriptor(JNIEnv* env, std::unique_ptr<Asset> asset, jlongArray out_offsets) { off64_t start_offset, length; Loading Loading @@ -1524,6 +1574,8 @@ static const JNINativeMethod gAssetManagerMethods[] = { {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps}, {"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;", (void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid}, {"nativeGetOverlayableMap", "(JLjava/lang/String;)Ljava/util/Map;", (void*)NativeGetOverlayableMap}, // Global management/debug methods. {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount}, Loading Loading @@ -1575,6 +1627,14 @@ int register_android_content_AssetManager(JNIEnv* env) { gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass, "screenHeightDp", "I"); jclass arrayMapClass = FindClassOrDie(env, "android/util/ArrayMap"); gArrayMapOffsets.classObject = MakeGlobalRefOrDie(env, arrayMapClass); gArrayMapOffsets.constructor = GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "<init>", "()V"); gArrayMapOffsets.put = GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods)); } Loading libs/androidfw/AssetManager2.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,27 @@ const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCooki return nullptr; } const std::unordered_map<std::string, std::string>* AssetManager2::GetOverlayableMapForPackage(uint32_t package_id) const { if (package_id >= package_ids_.size()) { return nullptr; } const size_t idx = package_ids_[package_id]; if (idx == 0xff) { return nullptr; } const PackageGroup& package_group = package_groups_[idx]; if (package_group.packages_.size() == 0) { return nullptr; } const auto loaded_package = package_group.packages_[0].loaded_package_; return &loaded_package->GetOverlayableMap(); } void AssetManager2::SetConfiguration(const ResTable_config& configuration) { const int diff = configuration_.diff(configuration); configuration_ = configuration; Loading libs/androidfw/LoadedArsc.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -598,6 +598,13 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, std::string actor; util::ReadUtf16StringFromDevice(header->actor, arraysize(header->actor), &actor); if (loaded_package->overlayable_map_.find(name) != loaded_package->overlayable_map_.end()) { LOG(ERROR) << "Multiple <overlayable> blocks with the same name '" << name << "'."; return {}; } loaded_package->overlayable_map_.emplace(name, actor); // Iterate over the overlayable policy chunks contained within the overlayable chunk data ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size()); while (overlayable_iter.HasNext()) { Loading libs/androidfw/include/androidfw/AssetManager2.h +3 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,9 @@ class AssetManager2 { // This may be nullptr if the APK represented by `cookie` has no resource table. const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const; const std::unordered_map<std::string, std::string>* GetOverlayableMapForPackage(uint32_t package_id) const; // Sets/resets the configuration for this AssetManager. This will cause all // caches that are related to the configuration change to be invalidated. void SetConfiguration(const ResTable_config& configuration); Loading Loading
core/java/android/content/res/AssetManager.java +14 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import java.nio.channels.FileLock; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** * Provides access to an application's raw asset files; see {@link Resources} Loading Loading @@ -1345,6 +1346,17 @@ public final class AssetManager implements AutoCloseable { } } /** * @hide */ @GuardedBy("this") public @Nullable Map<String, String> getOverlayableMap(String packageName) { synchronized (this) { ensureValidLocked(); return nativeGetOverlayableMap(mObject, packageName); } } @GuardedBy("this") private void incRefsLocked(long id) { if (DEBUG_REFS) { Loading Loading @@ -1462,6 +1474,8 @@ public final class AssetManager implements AutoCloseable { private static native void nativeVerifySystemIdmaps(); private static native String[] nativeCreateIdmapsForStaticOverlaysTargetingAndroid(); private static native @Nullable Map nativeGetOverlayableMap(long ptr, @NonNull String packageName); // Global debug native methods. /** Loading
core/jni/android_util_AssetManager.cpp +60 −0 Original line number Diff line number Diff line Loading @@ -104,6 +104,12 @@ static struct configuration_offsets_t { jfieldID mScreenHeightDpOffset; } gConfigurationOffsets; static struct arraymap_offsets_t { jclass classObject; jmethodID constructor; jmethodID put; } gArrayMapOffsets; jclass g_stringClass = nullptr; // ---------------------------------------------------------------------------- Loading Loading @@ -326,6 +332,50 @@ static Guarded<AssetManager2>& AssetManagerFromLong(jlong ptr) { return *AssetManagerForNdkAssetManager(reinterpret_cast<AAssetManager*>(ptr)); } static jobject NativeGetOverlayableMap(JNIEnv* env, jclass /*clazz*/, jlong ptr, jstring package_name) { ScopedLock<AssetManager2> assetmanager(AssetManagerFromLong(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()); const std::unordered_map<std::string, std::string>* map = nullptr; assetmanager->ForEachPackage([&](const std::string& this_package_name, uint8_t package_id) { if (this_package_name == std_package_name) { map = assetmanager->GetOverlayableMapForPackage(package_id); } }); if (map == nullptr) { return nullptr; } jobject array_map = env->NewObject(gArrayMapOffsets.classObject, gArrayMapOffsets.constructor); if (array_map == nullptr) { return nullptr; } for (const auto& iter : *map) { jstring name = env->NewStringUTF(iter.first.c_str()); if (env->ExceptionCheck()) { return nullptr; } jstring actor = env->NewStringUTF(iter.second.c_str()); if (env->ExceptionCheck()) { env->DeleteLocalRef(name); return nullptr; } env->CallObjectMethod(array_map, gArrayMapOffsets.put, name, actor); env->DeleteLocalRef(name); env->DeleteLocalRef(actor); } return array_map; } static jobject ReturnParcelFileDescriptor(JNIEnv* env, std::unique_ptr<Asset> asset, jlongArray out_offsets) { off64_t start_offset, length; Loading Loading @@ -1524,6 +1574,8 @@ static const JNINativeMethod gAssetManagerMethods[] = { {"nativeVerifySystemIdmaps", "()V", (void*)NativeVerifySystemIdmaps}, {"nativeCreateIdmapsForStaticOverlaysTargetingAndroid", "()[Ljava/lang/String;", (void*)NativeCreateIdmapsForStaticOverlaysTargetingAndroid}, {"nativeGetOverlayableMap", "(JLjava/lang/String;)Ljava/util/Map;", (void*)NativeGetOverlayableMap}, // Global management/debug methods. {"getGlobalAssetCount", "()I", (void*)NativeGetGlobalAssetCount}, Loading Loading @@ -1575,6 +1627,14 @@ int register_android_content_AssetManager(JNIEnv* env) { gConfigurationOffsets.mScreenHeightDpOffset = GetFieldIDOrDie(env, configurationClass, "screenHeightDp", "I"); jclass arrayMapClass = FindClassOrDie(env, "android/util/ArrayMap"); gArrayMapOffsets.classObject = MakeGlobalRefOrDie(env, arrayMapClass); gArrayMapOffsets.constructor = GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "<init>", "()V"); gArrayMapOffsets.put = GetMethodIDOrDie(env, gArrayMapOffsets.classObject, "put", "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); return RegisterMethodsOrDie(env, "android/content/res/AssetManager", gAssetManagerMethods, NELEM(gAssetManagerMethods)); } Loading
libs/androidfw/AssetManager2.cpp +21 −0 Original line number Diff line number Diff line Loading @@ -203,6 +203,27 @@ const DynamicRefTable* AssetManager2::GetDynamicRefTableForCookie(ApkAssetsCooki return nullptr; } const std::unordered_map<std::string, std::string>* AssetManager2::GetOverlayableMapForPackage(uint32_t package_id) const { if (package_id >= package_ids_.size()) { return nullptr; } const size_t idx = package_ids_[package_id]; if (idx == 0xff) { return nullptr; } const PackageGroup& package_group = package_groups_[idx]; if (package_group.packages_.size() == 0) { return nullptr; } const auto loaded_package = package_group.packages_[0].loaded_package_; return &loaded_package->GetOverlayableMap(); } void AssetManager2::SetConfiguration(const ResTable_config& configuration) { const int diff = configuration_.diff(configuration); configuration_ = configuration; Loading
libs/androidfw/LoadedArsc.cpp +7 −0 Original line number Diff line number Diff line Loading @@ -598,6 +598,13 @@ std::unique_ptr<const LoadedPackage> LoadedPackage::Load(const Chunk& chunk, std::string actor; util::ReadUtf16StringFromDevice(header->actor, arraysize(header->actor), &actor); if (loaded_package->overlayable_map_.find(name) != loaded_package->overlayable_map_.end()) { LOG(ERROR) << "Multiple <overlayable> blocks with the same name '" << name << "'."; return {}; } loaded_package->overlayable_map_.emplace(name, actor); // Iterate over the overlayable policy chunks contained within the overlayable chunk data ChunkIterator overlayable_iter(child_chunk.data_ptr(), child_chunk.data_size()); while (overlayable_iter.HasNext()) { Loading
libs/androidfw/include/androidfw/AssetManager2.h +3 −0 Original line number Diff line number Diff line Loading @@ -124,6 +124,9 @@ class AssetManager2 { // This may be nullptr if the APK represented by `cookie` has no resource table. const DynamicRefTable* GetDynamicRefTableForCookie(ApkAssetsCookie cookie) const; const std::unordered_map<std::string, std::string>* GetOverlayableMapForPackage(uint32_t package_id) const; // Sets/resets the configuration for this AssetManager. This will cause all // caches that are related to the configuration change to be invalidated. void SetConfiguration(const ResTable_config& configuration); Loading