From 7d59407138facda5c0587da7ae7c03aa29cd2f8a Mon Sep 17 00:00:00 2001 From: Mis012 Date: Thu, 2 Jan 2025 22:18:45 +0100 Subject: [PATCH] AssetManager: implement resolveAttrs --- .../android_content_res_AssetManager.c | 91 ++++++++++++++++++- src/api-impl-jni/defines.h | 11 +++ .../android_content_res_AssetManager.h | 8 ++ src/api-impl/android/app/ActivityManager.java | 7 +- .../android/content/res/AssetManager.java | 9 +- 5 files changed, 116 insertions(+), 10 deletions(-) diff --git a/src/api-impl-jni/android_content_res_AssetManager.c b/src/api-impl-jni/android_content_res_AssetManager.c index ab1a342b..dd223091 100644 --- a/src/api-impl-jni/android_content_res_AssetManager.c +++ b/src/api-impl-jni/android_content_res_AssetManager.c @@ -15,6 +15,18 @@ #include #include +#define JAVA_ENUM_CLASS android_content_res_AssetManager +enum { + JAVA_ENUM(STYLE_TYPE), + JAVA_ENUM(STYLE_DATA), + JAVA_ENUM(STYLE_ASSET_COOKIE), + JAVA_ENUM(STYLE_RESOURCE_ID), + JAVA_ENUM(STYLE_CHANGING_CONFIGURATIONS), + JAVA_ENUM(STYLE_DENSITY), + JAVA_ENUM(STYLE_NUM_ENTRIES), +}; +#undef JAVA_ENUM_CLASS + #define ASSET_DIR "assets/" char *get_app_data_dir(); @@ -259,6 +271,77 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadThemeAttributeV return block; } +/* function ported from AOSP - Copyright 2006, The Android Open Source Project */ +JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs(JNIEnv *env, jclass this, + jlong theme_ptr, jint def_style_attr, + jint def_style_res, jintArray java_values, + jintArray java_attrs, jintArray out_java_values, + jintArray out_java_indices) +{ + struct Theme *theme = _PTR(theme_ptr); + const jsize attrs_len = (*env)->GetArrayLength(env, java_attrs); + const jsize out_values_len = (*env)->GetArrayLength(env, out_java_values); + if (out_values_len < (attrs_len * STYLE_NUM_ENTRIES)) { + (*env)->ThrowNew(env, (*env)->FindClass(env, "java/lang/IndexOutOfBoundsException"), "outValues too small"); + return false; + } + + jint *attrs = (jint *)(*env)->GetPrimitiveArrayCritical(env, java_attrs, NULL); + if (attrs == NULL) { + return true; + } + + jint *values = NULL; + jsize values_len = 0; + if (java_values != NULL) { + values_len = (*env)->GetArrayLength(env, java_values); + values = (jint *)(*env)->GetPrimitiveArrayCritical(env, java_values, NULL); + if (values == NULL) { + (*env)->ReleasePrimitiveArrayCritical(env, java_attrs, attrs, JNI_ABORT); + return false; + } + } + + jint *out_values = (jint *)(*env)->GetPrimitiveArrayCritical(env, out_java_values, NULL); + if (!out_values) { + (*env)->ReleasePrimitiveArrayCritical(env, java_attrs, attrs, JNI_ABORT); + if (values) { + (*env)->ReleasePrimitiveArrayCritical(env, java_values, values, JNI_ABORT); + } + return false; + } + + jint *out_indices = NULL; + if (out_java_indices) { + jsize out_indices_len = (*env)->GetArrayLength(env, out_java_indices); + if (out_indices_len > attrs_len) { + out_indices = (jint *)(*env)->GetPrimitiveArrayCritical(env, out_java_indices, NULL); + if (!out_indices) { + (*env)->ReleasePrimitiveArrayCritical(env, java_attrs, attrs, JNI_ABORT); + if (values) + (*env)->ReleasePrimitiveArrayCritical(env, java_values, values, JNI_ABORT); + (*env)->ReleasePrimitiveArrayCritical(env, out_java_values, out_values, JNI_ABORT); + return false; + } + } + } + + bool ret = ResolveAttrs(theme, def_style_attr, def_style_res, + (uint32_t *)values, values_len, + (uint32_t *)attrs, attrs_len, + (uint32_t *)out_values, (uint32_t *)out_indices); + if (out_indices) + (*env)->ReleasePrimitiveArrayCritical(env, out_java_indices, out_indices, 0); + + (*env)->ReleasePrimitiveArrayCritical(env, out_java_values, out_values, 0); + + if (values) + (*env)->ReleasePrimitiveArrayCritical(env, java_values, values, JNI_ABORT); + + (*env)->ReleasePrimitiveArrayCritical(env, java_attrs, attrs, JNI_ABORT); + return ret; +} + JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_getArraySize(JNIEnv *env, jobject this, jint ident) { struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(this, "mObject")); @@ -283,10 +366,10 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_retrieveArray(JNIEn uint32_t resId = 0; ssize_t block = ResTable_resolveReference(res_table, &value, bag[i].stringBlock, &resId, NULL, NULL); - array[i*android_content_res_AssetManager_STYLE_NUM_ENTRIES + android_content_res_AssetManager_STYLE_TYPE] = value.dataType; - array[i*android_content_res_AssetManager_STYLE_NUM_ENTRIES + android_content_res_AssetManager_STYLE_DATA] = value.data; - array[i*android_content_res_AssetManager_STYLE_NUM_ENTRIES + android_content_res_AssetManager_STYLE_ASSET_COOKIE] = block; - array[i*android_content_res_AssetManager_STYLE_NUM_ENTRIES + android_content_res_AssetManager_STYLE_RESOURCE_ID] = resId; + array[i*STYLE_NUM_ENTRIES + STYLE_TYPE] = value.dataType; + array[i*STYLE_NUM_ENTRIES + STYLE_DATA] = value.data; + array[i*STYLE_NUM_ENTRIES + STYLE_ASSET_COOKIE] = block; + array[i*STYLE_NUM_ENTRIES + STYLE_RESOURCE_ID] = resId; } ResTable_unlockBag(res_table, bag); diff --git a/src/api-impl-jni/defines.h b/src/api-impl-jni/defines.h index e81068f3..ef98b6de 100644 --- a/src/api-impl-jni/defines.h +++ b/src/api-impl-jni/defines.h @@ -40,6 +40,17 @@ #define _GET_BYTE_ARRAY_ELEMENTS(b_array) ((*env)->GetByteArrayElements(env, b_array, NULL)) #define _RELEASE_BYTE_ARRAY_ELEMENTS(b_array, buffer_ptr) ((*env)->ReleaseByteArrayElements(env, b_array, buffer_ptr, 0)) +// token pasting with macro expansion + +#define __JOIN(x, y) x ## y +#define JOIN(x, y) __JOIN(x, y) +#define JOIN3(x, y, z) JOIN(JOIN(x, y), z) + +// define enum member value to a value from autogenerated header + +#define JAVA_ENUM(name) \ + name = JOIN3(JAVA_ENUM_CLASS, _, name) + // this really doesn't belong here, should probably put this in Java and deal with ugly name convention of autogenerated headers #define MOTION_EVENT_ACTION_DOWN 0 diff --git a/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h b/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h index cf1c6608..5ba5ce1e 100644 --- a/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h +++ b/src/api-impl-jni/generated_headers/android_content_res_AssetManager.h @@ -201,6 +201,14 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceValue JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValue (JNIEnv *, jobject, jint, jint, jobject, jboolean); +/* + * Class: android_content_res_AssetManager + * Method: resolveAttrs + * Signature: (JII[I[I[I[I)Z + */ +JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs + (JNIEnv *, jclass, jlong, jint, jint, jintArray, jintArray, jintArray, jintArray); + /* * Class: android_content_res_AssetManager * Method: retrieveAttributes diff --git a/src/api-impl/android/app/ActivityManager.java b/src/api-impl/android/app/ActivityManager.java index e6a273ed..cb676c03 100644 --- a/src/api-impl/android/app/ActivityManager.java +++ b/src/api-impl/android/app/ActivityManager.java @@ -47,6 +47,7 @@ public class ActivityManager { } public int getMemoryClass() {return 20;} // suggested heap size in MB + public int getLargeMemoryClass() {return 60;} // value chosen arbitrarily public static void getMyMemoryState(RunningAppProcessInfo outInfo) {} @@ -56,7 +57,7 @@ public class ActivityManager { public List getAppTasks() { return new ArrayList<>(); } - + public static class RunningServiceInfo implements Parcelable { public RunningServiceInfo() { } @@ -72,7 +73,7 @@ public class ActivityManager { public void readFromParcel(Parcel source) { return; } - } + } public List getRunningServices(int maxNum) @@ -80,8 +81,6 @@ public class ActivityManager { return new ArrayList<>(); } - public int getLargeMemoryClass() {return getMemoryClass();} - public List getHistoricalProcessExitReasons(String pkgname, int pid, int maxNum) { return Collections.emptyList(); } diff --git a/src/api-impl/android/content/res/AssetManager.java b/src/api-impl/android/content/res/AssetManager.java index 602c8a5b..59e6f871 100644 --- a/src/api-impl/android/content/res/AssetManager.java +++ b/src/api-impl/android/content/res/AssetManager.java @@ -812,8 +812,13 @@ public final class AssetManager { } return true; } - /*package*/ native final boolean retrieveAttributes( - int xmlParser, int[] inAttrs, int[] outValues, int[] outIndices); + + /*package*/ native static final boolean resolveAttrs(long theme, int defStyleAttr, + int defStyleRes, int[] inValues, + int[] inAttrs, int[] outValues, + int[] outIndices); + /*package*/ native final boolean retrieveAttributes(int xmlParser, int[] inAttrs, + int[] outValues, int[] outIndices); /*package*/ native final int getArraySize(int resource); /*package*/ native final int retrieveArray(int resource, int[] outValues); private native final int getStringBlockCount();