From 8d4d0021b392c877e4fe96bad8a487d85c6855e4 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Fri, 2 Feb 2024 10:00:07 +0100 Subject: [PATCH] use libandroidfw also for themes --- .../android_content_res_AssetManager.c | 46 ++++++++++ .../android_content_res_AssetManager.h | 24 ++--- .../android/content/res/AssetManager.java | 91 ++++++------------- .../android/content/res/Resources.java | 24 ++--- 4 files changed, 100 insertions(+), 85 deletions(-) diff --git a/src/api-impl-jni/android_content_res_AssetManager.c b/src/api-impl-jni/android_content_res_AssetManager.c index abc191f4..84fe2d35 100644 --- a/src/api-impl-jni/android_content_res_AssetManager.c +++ b/src/api-impl-jni/android_content_res_AssetManager.c @@ -224,3 +224,49 @@ JNIEXPORT jobject JNICALL Java_android_content_res_AssetManager_getPooledString( const char16_t *string = ResStringPool_stringAt(string_pool, index, &len); return (*env)->NewString(env, string, len); } + +JNIEXPORT jlong JNICALL Java_android_content_res_AssetManager_newTheme(JNIEnv *env, jobject this) +{ + struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(this, "mObject")); + struct Theme *theme = Theme_new(AssetManager_getResources(asset_manager, true)); + return _INTPTR(theme); +} + +JNIEXPORT void JNICALL Java_android_content_res_AssetManager_deleteTheme(JNIEnv *env, jobject this, jlong theme_ptr) +{ + Theme_delete(_PTR(theme_ptr)); +} + +JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyThemeStyle(JNIEnv *env, jobject this, jlong theme_ptr, jint styleRes, jboolean force) +{ + Theme_applyStyle(_PTR(theme_ptr), styleRes, force); +} + +JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadThemeAttributeValue(JNIEnv *env, jobject this, jlong theme_ptr, jint ident, jobject outValue, jboolean resolve) +{ + struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(this, "mObject")); + const struct ResTable *res_table = AssetManager_getResources(asset_manager, true); + struct Theme *theme = _PTR(theme_ptr); + uint32_t resId = ident; + struct Res_value value; + uint32_t outSpecFlags; + struct ResTable_config outConfig; + int block = Theme_getAttribute(theme, resId, &value, &outSpecFlags); + if (resolve) { + block = Theme_resolveAttributeReference(theme, &value, block, &resId, &outSpecFlags, &outConfig); + } + if (block >= 0) { + _SET_INT_FIELD(outValue, "type", value.dataType); + _SET_INT_FIELD(outValue, "data", value.data); + _SET_INT_FIELD(outValue, "resourceId", resId); + if (value.dataType == TYPE_STRING) { + const struct ResStringPool *string_pool = ResTable_getTableStringBlock(res_table, block); + size_t len; + const char16_t *string = ResStringPool_stringAt(string_pool, value.data, &len); + _SET_OBJ_FIELD(outValue, "string", "Ljava/lang/CharSequence;", (*env)->NewString(env, string, len)); + } else { + _SET_OBJ_FIELD(outValue, "string", "Ljava/lang/CharSequence;", NULL); + } + } + return block; +} 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 64058216..bea145f2 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 @@ -252,50 +252,50 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_getGlobalAssetManag /* * Class: android_content_res_AssetManager * Method: newTheme - * Signature: ()I + * Signature: ()J */ -JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_newTheme +JNIEXPORT jlong JNICALL Java_android_content_res_AssetManager_newTheme (JNIEnv *, jobject); /* * Class: android_content_res_AssetManager * Method: deleteTheme - * Signature: (I)V + * Signature: (J)V */ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_deleteTheme - (JNIEnv *, jobject, jint); + (JNIEnv *, jobject, jlong); /* * Class: android_content_res_AssetManager * Method: applyThemeStyle - * Signature: (IIZ)V + * Signature: (JIZ)V */ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyThemeStyle - (JNIEnv *, jclass, jint, jint, jboolean); + (JNIEnv *, jclass, jlong, jint, jboolean); /* * Class: android_content_res_AssetManager * Method: copyTheme - * Signature: (II)V + * Signature: (JJ)V */ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_copyTheme - (JNIEnv *, jclass, jint, jint); + (JNIEnv *, jclass, jlong, jlong); /* * Class: android_content_res_AssetManager * Method: loadThemeAttributeValue - * Signature: (IILandroid/util/TypedValue;Z)I + * Signature: (JILandroid/util/TypedValue;Z)I */ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadThemeAttributeValue - (JNIEnv *, jclass, jint, jint, jobject, jboolean); + (JNIEnv *, jobject, jlong, jint, jobject, jboolean); /* * Class: android_content_res_AssetManager * Method: dumpTheme - * Signature: (IILjava/lang/String;Ljava/lang/String;)V + * Signature: (JILjava/lang/String;Ljava/lang/String;)V */ JNIEXPORT void JNICALL Java_android_content_res_AssetManager_dumpTheme - (JNIEnv *, jclass, jint, jint, jstring, jstring); + (JNIEnv *, jclass, jlong, jint, jstring, jstring); /* * Class: android_content_res_AssetManager diff --git a/src/api-impl/android/content/res/AssetManager.java b/src/api-impl/android/content/res/AssetManager.java index be43fb8d..e1ff61a3 100644 --- a/src/api-impl/android/content/res/AssetManager.java +++ b/src/api-impl/android/content/res/AssetManager.java @@ -301,51 +301,10 @@ public final class AssetManager { return map; } - /*package*/ final boolean getThemeValue(Map style, int ident, + /*package*/ final boolean getThemeValue(long style, int ident, TypedValue outValue, boolean resolveRefs) { - EntryGroup entryGroup = tableBlockSearch(ident); - if (entryGroup == null) - return false; - Entry entry = entryGroup.pickOne(); - ValueItem valueItem = null; - while ("attr".equals(entry.getTypeName())) { - valueItem = null; - if (style.containsKey(ident)) - valueItem = style.get(ident); - if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE) { - ident = valueItem.getData(); - entryGroup = tableBlockSearch(ident); - if (entryGroup == null) { - break; - } - entry = entryGroup.pickOne(); - } else { - break; - } - } - - ident = 0; - if (valueItem != null && valueItem.getValueType() == ValueType.REFERENCE) { - while (valueItem.getValueType() == ValueType.REFERENCE) { - ident = valueItem.getData(); - valueItem = null; - if (ident == 0) - break; - valueItem = tableBlockSearch(ident).pickOne().getResValue(); - if (valueItem == null) - break; - } - } - if (valueItem == null) - return false; - outValue.resourceId = ident; - outValue.type = valueItem.getType(); - outValue.data = valueItem.getData(); - outValue.assetCookie = -1; - if (outValue.type == TypedValue.TYPE_STRING) { - outValue.string = valueItem.getDataAsPoolString().get(); - } - return true; + int block = loadThemeAttributeValue(style, ident, outValue, resolveRefs); + return block >= 0; } /*package*/ final void ensureStringBlocks() { @@ -628,21 +587,21 @@ public final class AssetManager { } } - /*package*/ final int createTheme() { + /*package*/ final long createTheme() { synchronized (this) { if (!mOpen) { throw new RuntimeException("Assetmanager has been closed"); } - int res = newTheme(); - incRefsLocked(res); + long res = newTheme(); + incRefsLocked(new Long(res).hashCode()); return res; } } - /*package*/ final void releaseTheme(int theme) { + /*package*/ final void releaseTheme(long theme) { synchronized (this) { // deleteTheme(theme); - decRefsLocked(theme); + decRefsLocked(new Long(theme).hashCode()); } } @@ -871,11 +830,11 @@ public final class AssetManager { /*package*/ static final int STYLE_RESOURCE_ID = 3; /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4; /*package*/ static final int STYLE_DENSITY = 5; - /*package*/ /*native*/ final boolean applyStyle(Map theme, + /*package*/ /*native*/ final boolean applyStyle(long theme, int defStyleAttr, int defStyleRes, AttributeSet set, int[] inAttrs, int[] outValues, int[] outIndices) { - if (defStyleRes == 0 && theme.containsKey(defStyleAttr)) - defStyleRes = theme.get(defStyleAttr).getData(); + // if (defStyleRes == 0 && theme.containsKey(defStyleAttr)) + // defStyleRes = theme.get(defStyleAttr).getData(); if (defStyleRes == 0 && set != null) defStyleRes = set.getAttributeResourceValue(null, "style", 0); Map defStyle = loadStyle(defStyleRes); @@ -910,8 +869,6 @@ public final class AssetManager { if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE && valueItem.getData() == resId) valueItem = null; } - if (valueItem == null) - valueItem = theme.get(resId); if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE) { resId = valueItem.getData(); entryGroup = tableBlockSearch(resId); @@ -923,8 +880,20 @@ public final class AssetManager { break; } } - if (valueItem == null) + if (valueItem == null) { + if (theme != 0) { + TypedValue value = new TypedValue(); + int block = loadThemeAttributeValue(theme, resId, value, true); + if (block >= 0) { + outValues[d + AssetManager.STYLE_RESOURCE_ID] = value.resourceId; + outValues[d + AssetManager.STYLE_TYPE] = value.type; + outValues[d + AssetManager.STYLE_DATA] = value.data; + outValues[d + AssetManager.STYLE_ASSET_COOKIE] = block; + outIndices[++outIndices[0]] = i; + } + } continue; + } if (valueItem.getValueType() == ValueType.REFERENCE) { resId = valueItem.getData(); TypedValue value = new TypedValue(); @@ -983,14 +952,14 @@ public final class AssetManager { */ public native static final int getGlobalAssetManagerCount(); - private native final int newTheme(); - private native final void deleteTheme(int theme); - /*package*/ native static final void applyThemeStyle(int theme, int styleRes, boolean force); - /*package*/ native static final void copyTheme(int dest, int source); - /*package*/ native static final int loadThemeAttributeValue(int theme, int ident, + private native final long newTheme(); + private native final void deleteTheme(long theme); + /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force); + /*package*/ native static final void copyTheme(long dest, long source); + /*package*/ native final int loadThemeAttributeValue(long theme, int ident, TypedValue outValue, boolean resolve); - /*package*/ native static final void dumpTheme(int theme, int priority, String tag, String prefix); + /*package*/ native static final void dumpTheme(long theme, int priority, String tag, String prefix); private /*native*/ final int openXmlAssetNative(int cookie, String fileName) { return openAsset("../" + fileName, 0); diff --git a/src/api-impl/android/content/res/Resources.java b/src/api-impl/android/content/res/Resources.java index 3ee322db..7e7a56e7 100644 --- a/src/api-impl/android/content/res/Resources.java +++ b/src/api-impl/android/content/res/Resources.java @@ -1198,7 +1198,8 @@ public class Resources { * retrieve XML attributes with style and theme information applied. */ public final class Theme { - private Map themeMap = new HashMap<>(); + private long theme; + /** * Place new attribute values into the theme. The style resource * specified by resid will be retrieved from this Theme's @@ -1217,7 +1218,7 @@ public class Resources { * if not already defined in the theme. */ public void applyStyle(int resid, boolean force) { - themeMap.putAll(mAssets.loadStyle(resid)); + mAssets.applyThemeStyle(theme, resid, force); } /** @@ -1230,7 +1231,7 @@ public class Resources { * @param other The existing Theme to copy from. */ public void setTo(Theme other) { - themeMap = new HashMap<>(other.themeMap); + this.theme = other.theme; } /** @@ -1256,7 +1257,7 @@ public class Resources { int len = attrs.length; TypedArray array = getCachedStyledAttributes(len); array.mRsrcs = attrs; - mAssets.applyStyle(themeMap, 0, 0, null, attrs, array.mData, array.mIndices); + mAssets.applyStyle(theme, 0, 0, null, attrs, array.mData, array.mIndices); return array; } @@ -1285,7 +1286,7 @@ public class Resources { int len = attrs.length; TypedArray array = getCachedStyledAttributes(len); array.mRsrcs = attrs; - mAssets.applyStyle(themeMap, 0, resid, null, attrs, + mAssets.applyStyle(theme, 0, resid, null, attrs, array.mData, array.mIndices); if (false) { int[] data = array.mData; @@ -1374,7 +1375,7 @@ public class Resources { // out the attributes from the XML file (applying type information // contained in the resources and such). ResXmlPullParser parser = (ResXmlPullParser)set; - mAssets.applyStyle(themeMap, defStyleAttr, defStyleRes, + mAssets.applyStyle(theme, defStyleAttr, defStyleRes, set, attrs, array.mData, array.mIndices); array.mRsrcs = attrs; array.mXml = parser; @@ -1428,7 +1429,7 @@ public class Resources { */ public boolean resolveAttribute(int resid, TypedValue outValue, boolean resolveRefs) { - boolean got = mAssets.getThemeValue(themeMap, resid, outValue, resolveRefs); + boolean got = mAssets.getThemeValue(theme, resid, outValue, resolveRefs); if (false) { System.out.println( "resolveAttribute #" + Integer.toHexString(resid) + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type) + ", data=0x" + Integer.toHexString(outValue.data)); @@ -1444,21 +1445,20 @@ public class Resources { * @param prefix Text to prefix each line printed. */ public void dump(int priority, String tag, String prefix) { - AssetManager.dumpTheme(mTheme, priority, tag, prefix); + AssetManager.dumpTheme(theme, priority, tag, prefix); } protected void finalize() throws Throwable { super.finalize(); - mAssets.releaseTheme(mTheme); + mAssets.releaseTheme(theme); } /*package*/ Theme() { mAssets = Resources.this.mAssets; - mTheme = 0 /*mAssets.createTheme()*/; + theme = mAssets.createTheme(); } private final AssetManager mAssets; - private final int mTheme; } /** @@ -1492,7 +1492,7 @@ public class Resources { // out the attributes from the XML file (applying type information // contained in the resources and such). ResXmlPullParser parser = (ResXmlPullParser)set; - mAssets.applyStyle(Collections.EMPTY_MAP, 0, 0, + mAssets.applyStyle(0, 0, 0, set, attrs, array.mData, array.mIndices); array.mRsrcs = attrs;