Loading cmds/idmap2/idmap2/Lookup.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ Result<Unit> Lookup(const std::vector<std::string>& args) { if (i == 0) { target_path = idmap_header->GetTargetPath(); // TODO: b/437989879 - Add support for r/w flags in idmap auto target_apk = ApkAssets::Load(target_path); if (!target_apk) { return Error("failed to read target apk from %s", target_path.c_str()); Loading cmds/idmap2/libidmap2/ResourceContainer.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -274,7 +274,9 @@ struct ResState { package_property_t flags) { ResState state; state.zip_assets = zip.get(); if ((state.apk_assets = ApkAssets::Load(std::move(zip), flags)) == nullptr) { // TODO: b/437989879 - Add support for r/w flags in idmap if ((state.apk_assets = ApkAssets::Load(std::move(zip), nullptr, flags)) == nullptr) { return Error("failed to load apk asset for '%s'", state.zip_assets->GetDebugName().c_str()); } Loading core/java/android/content/res/ApkAssets.java +21 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.pm.pkg.parsing.ParsingPackageUtils; import dalvik.annotation.optimization.CriticalNative; Loading Loading @@ -513,6 +514,26 @@ public final class ApkAssets { pw.println(prefix + "assetPath=" + getAssetPath()); } /** * This exists as a function the native layer can call through jni to determine which android * feature flags are enabled. * * @param flagNames An array of all the names the native layer needs to know the status of * @return An array that parallels the flagNames parameter and contains if each flag is enabled */ private static boolean[] getFlagValuesForNative(@NonNull String[] flagNames) { boolean[] values = new boolean[flagNames.length]; for (int i = 0; i < flagNames.length; i++) { Boolean value = ParsingPackageUtils.getAconfigFlags().getFlagValue(flagNames[i]); if (value == null) { Log.w("ApkAssets", "Couldn't find flag value for native: " + flagNames[i]); } else { values[i] = value; } } return values; } private static native long nativeLoad(@FormatType int format, @NonNull String path, @PropertyFlags int flags, @Nullable AssetsProvider asset) throws IOException; private static native long nativeLoadEmpty(@PropertyFlags int flags, Loading core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ cc_library_shared_for_libandroid_runtime { ], static_libs: [ "android.content.res.flags-aconfig-cc-host-ro", "libziparchive_for_incfs", "libguiflags", ], Loading core/jni/android_content_res_ApkAssets.cpp +65 −10 Original line number Diff line number Diff line Loading @@ -55,6 +55,12 @@ static struct assetsprovider_offsets_t { jmethodID toString; } gAssetsProviderOffsets; static struct apkassets_offsets_t { jclass classObject; jclass stringClassObject; jmethodID getFlagValues; } gApkAssetsOffsets; static struct { jmethodID detachFd; } gParcelFileDescriptorOffsets; Loading Loading @@ -219,6 +225,41 @@ class LoaderAssetsProvider : public AssetsProvider { std::string debug_name_; }; static void GetFlagValues(JNIEnv* env, FlagMap& flag_map) { if (flag_map.empty()) { return; } jobjectArray flag_names = env->NewObjectArray(flag_map.size(), gApkAssetsOffsets.stringClassObject, nullptr); if (flag_names == nullptr) { ALOGE("ApkAssets: Getting flag values failed due to jni error, unable to create name " "array"); } size_t i = 0; for (const auto& [flag_name, _] : flag_map) { jstring jstr = env->NewStringUTF(flag_name.c_str()); env->SetObjectArrayElement(flag_names, i++, jstr); env->DeleteLocalRef(jstr); } jbooleanArray jflag_values = static_cast<jbooleanArray>( env->CallStaticObjectMethod(gApkAssetsOffsets.classObject, gApkAssetsOffsets.getFlagValues, flag_names)); jboolean* flag_values = env->GetBooleanArrayElements(jflag_values, nullptr); if (flag_values == NULL) { ALOGE("ApkAssets: Getting flag values failed due to jni error"); } else { i = 0; for (auto& [_, flag_value] : flag_map) { flag_value = flag_values[i++] != JNI_FALSE ? LoadedArscFlagStatus::Enabled : LoadedArscFlagStatus::Disabled; } } if (jflag_values != nullptr) { env->ReleaseBooleanArrayElements(jflag_values, flag_values, 0); } } static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t format, jstring java_path, const jint property_flags, jobject assets_provider) { ScopedUtfChars path(env, java_path); Loading @@ -228,6 +269,8 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma ATRACE_NAME(base::StringPrintf("LoadApkAssets(%s)", path.c_str()).c_str()); auto flag_func = [=](FlagMap& map) { return GetFlagValues(env, map); }; auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider); AssetManager2::ApkAssetsPtr apk_assets; switch (format) { Loading @@ -235,7 +278,7 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma auto assets = AssetsProvider::CreateWithOverride(ZipAssetsProvider::Create(path.c_str(), property_flags), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load(std::move(assets), flag_func, property_flags); break; } case FORMAT_IDMAP: Loading @@ -245,13 +288,13 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma apk_assets = ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFile(path.c_str()), AssetsProvider::CreateFromNullable(std::move(loader_assets)), property_flags); flag_func, property_flags); break; case FORMAT_DIRECTORY: { auto assets = AssetsProvider::CreateWithOverride(DirectoryAssetsProvider::Create(path.c_str()), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load(std::move(assets), flag_func, property_flags); break; } default: Loading Loading @@ -314,7 +357,9 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t .c_str(), property_flags), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load( std::move(assets), [=](FlagMap& map) { return GetFlagValues(env, map); }, property_flags); break; } case FORMAT_ARSC: Loading @@ -322,7 +367,7 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFd(std::move(dup_fd), nullptr /* path */), AssetsProvider::CreateFromNullable(std::move(loader_assets)), property_flags); nullptr, property_flags); break; default: const std::string error_msg = base::StringPrintf("Unsupported format type %d", format); Loading Loading @@ -388,7 +433,9 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ static_cast<off64_t>( length)), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load( std::move(assets), [=](FlagMap& map) { return GetFlagValues(env, map); }, property_flags); break; } case FORMAT_ARSC: Loading @@ -399,7 +446,7 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ static_cast<off64_t>( length)), AssetsProvider::CreateFromNullable(std::move(loader_assets)), property_flags); nullptr, property_flags); break; default: const std::string error_msg = base::StringPrintf("Unsupported format type %d", format); Loading @@ -417,9 +464,9 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ } static jlong NativeLoadEmpty(JNIEnv* env, jclass /*clazz*/, jint flags, jobject assets_provider) { auto apk_assets = ApkAssets::Load(AssetsProvider::CreateFromNullable( LoaderAssetsProvider::Create(env, assets_provider)), flags); auto apk_assets = ApkAssets::Load( AssetsProvider::CreateFromNullable(LoaderAssetsProvider::Create(env, assets_provider)), [=](FlagMap& map) { return GetFlagValues(env, map); }, flags); if (apk_assets == nullptr) { const std::string error_msg = base::StringPrintf("Failed to load empty assets with provider %p", Loading Loading @@ -599,6 +646,14 @@ int register_android_content_res_ApkAssets(JNIEnv* env) { jclass parcelFd = FindClassOrDie(env, "android/os/ParcelFileDescriptor"); gParcelFileDescriptorOffsets.detachFd = GetMethodIDOrDie(env, parcelFd, "detachFd", "()I"); gApkAssetsOffsets.classObject = FindClassOrDie(env, "android/content/res/ApkAssets"); gApkAssetsOffsets.getFlagValues = GetStaticMethodIDOrDie(env, gApkAssetsOffsets.classObject, "getFlagValuesForNative", "([Ljava/lang/String;)[Z"); gApkAssetsOffsets.stringClassObject = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String")); return RegisterMethodsOrDie(env, "android/content/res/ApkAssets", gApkAssetsMethods, arraysize(gApkAssetsMethods)); } Loading Loading
cmds/idmap2/idmap2/Lookup.cpp +1 −0 Original line number Diff line number Diff line Loading @@ -188,6 +188,7 @@ Result<Unit> Lookup(const std::vector<std::string>& args) { if (i == 0) { target_path = idmap_header->GetTargetPath(); // TODO: b/437989879 - Add support for r/w flags in idmap auto target_apk = ApkAssets::Load(target_path); if (!target_apk) { return Error("failed to read target apk from %s", target_path.c_str()); Loading
cmds/idmap2/libidmap2/ResourceContainer.cpp +3 −1 Original line number Diff line number Diff line Loading @@ -274,7 +274,9 @@ struct ResState { package_property_t flags) { ResState state; state.zip_assets = zip.get(); if ((state.apk_assets = ApkAssets::Load(std::move(zip), flags)) == nullptr) { // TODO: b/437989879 - Add support for r/w flags in idmap if ((state.apk_assets = ApkAssets::Load(std::move(zip), nullptr, flags)) == nullptr) { return Error("failed to load apk asset for '%s'", state.zip_assets->GetDebugName().c_str()); } Loading
core/java/android/content/res/ApkAssets.java +21 −0 Original line number Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.internal.annotations.GuardedBy; import com.android.internal.pm.pkg.parsing.ParsingPackageUtils; import dalvik.annotation.optimization.CriticalNative; Loading Loading @@ -513,6 +514,26 @@ public final class ApkAssets { pw.println(prefix + "assetPath=" + getAssetPath()); } /** * This exists as a function the native layer can call through jni to determine which android * feature flags are enabled. * * @param flagNames An array of all the names the native layer needs to know the status of * @return An array that parallels the flagNames parameter and contains if each flag is enabled */ private static boolean[] getFlagValuesForNative(@NonNull String[] flagNames) { boolean[] values = new boolean[flagNames.length]; for (int i = 0; i < flagNames.length; i++) { Boolean value = ParsingPackageUtils.getAconfigFlags().getFlagValue(flagNames[i]); if (value == null) { Log.w("ApkAssets", "Couldn't find flag value for native: " + flagNames[i]); } else { values[i] = value; } } return values; } private static native long nativeLoad(@FormatType int format, @NonNull String path, @PropertyFlags int flags, @Nullable AssetsProvider asset) throws IOException; private static native long nativeLoadEmpty(@PropertyFlags int flags, Loading
core/jni/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -114,6 +114,7 @@ cc_library_shared_for_libandroid_runtime { ], static_libs: [ "android.content.res.flags-aconfig-cc-host-ro", "libziparchive_for_incfs", "libguiflags", ], Loading
core/jni/android_content_res_ApkAssets.cpp +65 −10 Original line number Diff line number Diff line Loading @@ -55,6 +55,12 @@ static struct assetsprovider_offsets_t { jmethodID toString; } gAssetsProviderOffsets; static struct apkassets_offsets_t { jclass classObject; jclass stringClassObject; jmethodID getFlagValues; } gApkAssetsOffsets; static struct { jmethodID detachFd; } gParcelFileDescriptorOffsets; Loading Loading @@ -219,6 +225,41 @@ class LoaderAssetsProvider : public AssetsProvider { std::string debug_name_; }; static void GetFlagValues(JNIEnv* env, FlagMap& flag_map) { if (flag_map.empty()) { return; } jobjectArray flag_names = env->NewObjectArray(flag_map.size(), gApkAssetsOffsets.stringClassObject, nullptr); if (flag_names == nullptr) { ALOGE("ApkAssets: Getting flag values failed due to jni error, unable to create name " "array"); } size_t i = 0; for (const auto& [flag_name, _] : flag_map) { jstring jstr = env->NewStringUTF(flag_name.c_str()); env->SetObjectArrayElement(flag_names, i++, jstr); env->DeleteLocalRef(jstr); } jbooleanArray jflag_values = static_cast<jbooleanArray>( env->CallStaticObjectMethod(gApkAssetsOffsets.classObject, gApkAssetsOffsets.getFlagValues, flag_names)); jboolean* flag_values = env->GetBooleanArrayElements(jflag_values, nullptr); if (flag_values == NULL) { ALOGE("ApkAssets: Getting flag values failed due to jni error"); } else { i = 0; for (auto& [_, flag_value] : flag_map) { flag_value = flag_values[i++] != JNI_FALSE ? LoadedArscFlagStatus::Enabled : LoadedArscFlagStatus::Disabled; } } if (jflag_values != nullptr) { env->ReleaseBooleanArrayElements(jflag_values, flag_values, 0); } } static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t format, jstring java_path, const jint property_flags, jobject assets_provider) { ScopedUtfChars path(env, java_path); Loading @@ -228,6 +269,8 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma ATRACE_NAME(base::StringPrintf("LoadApkAssets(%s)", path.c_str()).c_str()); auto flag_func = [=](FlagMap& map) { return GetFlagValues(env, map); }; auto loader_assets = LoaderAssetsProvider::Create(env, assets_provider); AssetManager2::ApkAssetsPtr apk_assets; switch (format) { Loading @@ -235,7 +278,7 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma auto assets = AssetsProvider::CreateWithOverride(ZipAssetsProvider::Create(path.c_str(), property_flags), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load(std::move(assets), flag_func, property_flags); break; } case FORMAT_IDMAP: Loading @@ -245,13 +288,13 @@ static jlong NativeLoad(JNIEnv* env, jclass /*clazz*/, const format_type_t forma apk_assets = ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFile(path.c_str()), AssetsProvider::CreateFromNullable(std::move(loader_assets)), property_flags); flag_func, property_flags); break; case FORMAT_DIRECTORY: { auto assets = AssetsProvider::CreateWithOverride(DirectoryAssetsProvider::Create(path.c_str()), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load(std::move(assets), flag_func, property_flags); break; } default: Loading Loading @@ -314,7 +357,9 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t .c_str(), property_flags), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load( std::move(assets), [=](FlagMap& map) { return GetFlagValues(env, map); }, property_flags); break; } case FORMAT_ARSC: Loading @@ -322,7 +367,7 @@ static jlong NativeLoadFromFd(JNIEnv* env, jclass /*clazz*/, const format_type_t ApkAssets::LoadTable(AssetsProvider::CreateAssetFromFd(std::move(dup_fd), nullptr /* path */), AssetsProvider::CreateFromNullable(std::move(loader_assets)), property_flags); nullptr, property_flags); break; default: const std::string error_msg = base::StringPrintf("Unsupported format type %d", format); Loading Loading @@ -388,7 +433,9 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ static_cast<off64_t>( length)), std::move(loader_assets)); apk_assets = ApkAssets::Load(std::move(assets), property_flags); apk_assets = ApkAssets::Load( std::move(assets), [=](FlagMap& map) { return GetFlagValues(env, map); }, property_flags); break; } case FORMAT_ARSC: Loading @@ -399,7 +446,7 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ static_cast<off64_t>( length)), AssetsProvider::CreateFromNullable(std::move(loader_assets)), property_flags); nullptr, property_flags); break; default: const std::string error_msg = base::StringPrintf("Unsupported format type %d", format); Loading @@ -417,9 +464,9 @@ static jlong NativeLoadFromFdOffset(JNIEnv* env, jclass /*clazz*/, const format_ } static jlong NativeLoadEmpty(JNIEnv* env, jclass /*clazz*/, jint flags, jobject assets_provider) { auto apk_assets = ApkAssets::Load(AssetsProvider::CreateFromNullable( LoaderAssetsProvider::Create(env, assets_provider)), flags); auto apk_assets = ApkAssets::Load( AssetsProvider::CreateFromNullable(LoaderAssetsProvider::Create(env, assets_provider)), [=](FlagMap& map) { return GetFlagValues(env, map); }, flags); if (apk_assets == nullptr) { const std::string error_msg = base::StringPrintf("Failed to load empty assets with provider %p", Loading Loading @@ -599,6 +646,14 @@ int register_android_content_res_ApkAssets(JNIEnv* env) { jclass parcelFd = FindClassOrDie(env, "android/os/ParcelFileDescriptor"); gParcelFileDescriptorOffsets.detachFd = GetMethodIDOrDie(env, parcelFd, "detachFd", "()I"); gApkAssetsOffsets.classObject = FindClassOrDie(env, "android/content/res/ApkAssets"); gApkAssetsOffsets.getFlagValues = GetStaticMethodIDOrDie(env, gApkAssetsOffsets.classObject, "getFlagValuesForNative", "([Ljava/lang/String;)[Z"); gApkAssetsOffsets.stringClassObject = MakeGlobalRefOrDie(env, FindClassOrDie(env, "java/lang/String")); return RegisterMethodsOrDie(env, "android/content/res/ApkAssets", gApkAssetsMethods, arraysize(gApkAssetsMethods)); } Loading