use libandroidfw also for themes

This commit is contained in:
Julian Winkler
2024-02-02 10:00:07 +01:00
parent 3284518418
commit 8d4d0021b3
4 changed files with 100 additions and 85 deletions

View File

@@ -224,3 +224,49 @@ JNIEXPORT jobject JNICALL Java_android_content_res_AssetManager_getPooledString(
const char16_t *string = ResStringPool_stringAt(string_pool, index, &len); const char16_t *string = ResStringPool_stringAt(string_pool, index, &len);
return (*env)->NewString(env, string, 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;
}

View File

@@ -252,50 +252,50 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_getGlobalAssetManag
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: newTheme * 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); (JNIEnv *, jobject);
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: deleteTheme * Method: deleteTheme
* Signature: (I)V * Signature: (J)V
*/ */
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_deleteTheme JNIEXPORT void JNICALL Java_android_content_res_AssetManager_deleteTheme
(JNIEnv *, jobject, jint); (JNIEnv *, jobject, jlong);
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: applyThemeStyle * Method: applyThemeStyle
* Signature: (IIZ)V * Signature: (JIZ)V
*/ */
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyThemeStyle JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyThemeStyle
(JNIEnv *, jclass, jint, jint, jboolean); (JNIEnv *, jclass, jlong, jint, jboolean);
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: copyTheme * Method: copyTheme
* Signature: (II)V * Signature: (JJ)V
*/ */
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_copyTheme JNIEXPORT void JNICALL Java_android_content_res_AssetManager_copyTheme
(JNIEnv *, jclass, jint, jint); (JNIEnv *, jclass, jlong, jlong);
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: loadThemeAttributeValue * Method: loadThemeAttributeValue
* Signature: (IILandroid/util/TypedValue;Z)I * Signature: (JILandroid/util/TypedValue;Z)I
*/ */
JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadThemeAttributeValue 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 * Class: android_content_res_AssetManager
* Method: dumpTheme * 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 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 * Class: android_content_res_AssetManager

View File

@@ -301,51 +301,10 @@ public final class AssetManager {
return map; return map;
} }
/*package*/ final boolean getThemeValue(Map<Integer,ValueItem> style, int ident, /*package*/ final boolean getThemeValue(long style, int ident,
TypedValue outValue, boolean resolveRefs) { TypedValue outValue, boolean resolveRefs) {
EntryGroup entryGroup = tableBlockSearch(ident); int block = loadThemeAttributeValue(style, ident, outValue, resolveRefs);
if (entryGroup == null) return block >= 0;
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;
} }
/*package*/ final void ensureStringBlocks() { /*package*/ final void ensureStringBlocks() {
@@ -628,21 +587,21 @@ public final class AssetManager {
} }
} }
/*package*/ final int createTheme() { /*package*/ final long createTheme() {
synchronized (this) { synchronized (this) {
if (!mOpen) { if (!mOpen) {
throw new RuntimeException("Assetmanager has been closed"); throw new RuntimeException("Assetmanager has been closed");
} }
int res = newTheme(); long res = newTheme();
incRefsLocked(res); incRefsLocked(new Long(res).hashCode());
return res; return res;
} }
} }
/*package*/ final void releaseTheme(int theme) { /*package*/ final void releaseTheme(long theme) {
synchronized (this) { synchronized (this) {
// deleteTheme(theme); // 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_RESOURCE_ID = 3;
/*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4; /*package*/ static final int STYLE_CHANGING_CONFIGURATIONS = 4;
/*package*/ static final int STYLE_DENSITY = 5; /*package*/ static final int STYLE_DENSITY = 5;
/*package*/ /*native*/ final boolean applyStyle(Map<Integer,ValueItem> theme, /*package*/ /*native*/ final boolean applyStyle(long theme,
int defStyleAttr, int defStyleRes, AttributeSet set, int defStyleAttr, int defStyleRes, AttributeSet set,
int[] inAttrs, int[] outValues, int[] outIndices) { int[] inAttrs, int[] outValues, int[] outIndices) {
if (defStyleRes == 0 && theme.containsKey(defStyleAttr)) // if (defStyleRes == 0 && theme.containsKey(defStyleAttr))
defStyleRes = theme.get(defStyleAttr).getData(); // defStyleRes = theme.get(defStyleAttr).getData();
if (defStyleRes == 0 && set != null) if (defStyleRes == 0 && set != null)
defStyleRes = set.getAttributeResourceValue(null, "style", 0); defStyleRes = set.getAttributeResourceValue(null, "style", 0);
Map<Integer,ValueItem> defStyle = loadStyle(defStyleRes); Map<Integer,ValueItem> defStyle = loadStyle(defStyleRes);
@@ -910,8 +869,6 @@ public final class AssetManager {
if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE && valueItem.getData() == resId) if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE && valueItem.getData() == resId)
valueItem = null; valueItem = null;
} }
if (valueItem == null)
valueItem = theme.get(resId);
if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE) { if (valueItem != null && valueItem.getValueType() == ValueType.ATTRIBUTE) {
resId = valueItem.getData(); resId = valueItem.getData();
entryGroup = tableBlockSearch(resId); entryGroup = tableBlockSearch(resId);
@@ -923,8 +880,20 @@ public final class AssetManager {
break; 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; continue;
}
if (valueItem.getValueType() == ValueType.REFERENCE) { if (valueItem.getValueType() == ValueType.REFERENCE) {
resId = valueItem.getData(); resId = valueItem.getData();
TypedValue value = new TypedValue(); TypedValue value = new TypedValue();
@@ -983,14 +952,14 @@ public final class AssetManager {
*/ */
public native static final int getGlobalAssetManagerCount(); public native static final int getGlobalAssetManagerCount();
private native final int newTheme(); private native final long newTheme();
private native final void deleteTheme(int theme); private native final void deleteTheme(long theme);
/*package*/ native static final void applyThemeStyle(int theme, int styleRes, boolean force); /*package*/ native static final void applyThemeStyle(long theme, int styleRes, boolean force);
/*package*/ native static final void copyTheme(int dest, int source); /*package*/ native static final void copyTheme(long dest, long source);
/*package*/ native static final int loadThemeAttributeValue(int theme, int ident, /*package*/ native final int loadThemeAttributeValue(long theme, int ident,
TypedValue outValue, TypedValue outValue,
boolean resolve); 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) { private /*native*/ final int openXmlAssetNative(int cookie, String fileName) {
return openAsset("../" + fileName, 0); return openAsset("../" + fileName, 0);

View File

@@ -1198,7 +1198,8 @@ public class Resources {
* retrieve XML attributes with style and theme information applied. * retrieve XML attributes with style and theme information applied.
*/ */
public final class Theme { public final class Theme {
private Map<Integer,ValueItem> themeMap = new HashMap<>(); private long theme;
/** /**
* Place new attribute values into the theme. The style resource * Place new attribute values into the theme. The style resource
* specified by <var>resid</var> will be retrieved from this Theme's * specified by <var>resid</var> will be retrieved from this Theme's
@@ -1217,7 +1218,7 @@ public class Resources {
* if not already defined in the theme. * if not already defined in the theme.
*/ */
public void applyStyle(int resid, boolean force) { 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. * @param other The existing Theme to copy from.
*/ */
public void setTo(Theme other) { 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; int len = attrs.length;
TypedArray array = getCachedStyledAttributes(len); TypedArray array = getCachedStyledAttributes(len);
array.mRsrcs = attrs; 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; return array;
} }
@@ -1285,7 +1286,7 @@ public class Resources {
int len = attrs.length; int len = attrs.length;
TypedArray array = getCachedStyledAttributes(len); TypedArray array = getCachedStyledAttributes(len);
array.mRsrcs = attrs; array.mRsrcs = attrs;
mAssets.applyStyle(themeMap, 0, resid, null, attrs, mAssets.applyStyle(theme, 0, resid, null, attrs,
array.mData, array.mIndices); array.mData, array.mIndices);
if (false) { if (false) {
int[] data = array.mData; int[] data = array.mData;
@@ -1374,7 +1375,7 @@ public class Resources {
// out the attributes from the XML file (applying type information // out the attributes from the XML file (applying type information
// contained in the resources and such). // contained in the resources and such).
ResXmlPullParser parser = (ResXmlPullParser)set; ResXmlPullParser parser = (ResXmlPullParser)set;
mAssets.applyStyle(themeMap, defStyleAttr, defStyleRes, mAssets.applyStyle(theme, defStyleAttr, defStyleRes,
set, attrs, array.mData, array.mIndices); set, attrs, array.mData, array.mIndices);
array.mRsrcs = attrs; array.mRsrcs = attrs;
array.mXml = parser; array.mXml = parser;
@@ -1428,7 +1429,7 @@ public class Resources {
*/ */
public boolean resolveAttribute(int resid, TypedValue outValue, public boolean resolveAttribute(int resid, TypedValue outValue,
boolean resolveRefs) { boolean resolveRefs) {
boolean got = mAssets.getThemeValue(themeMap, resid, outValue, resolveRefs); boolean got = mAssets.getThemeValue(theme, resid, outValue, resolveRefs);
if (false) { if (false) {
System.out.println( System.out.println(
"resolveAttribute #" + Integer.toHexString(resid) + " got=" + got + ", type=0x" + Integer.toHexString(outValue.type) + ", data=0x" + Integer.toHexString(outValue.data)); "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. * @param prefix Text to prefix each line printed.
*/ */
public void dump(int priority, String tag, String prefix) { 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 { protected void finalize() throws Throwable {
super.finalize(); super.finalize();
mAssets.releaseTheme(mTheme); mAssets.releaseTheme(theme);
} }
/*package*/ Theme() { /*package*/ Theme() {
mAssets = Resources.this.mAssets; mAssets = Resources.this.mAssets;
mTheme = 0 /*mAssets.createTheme()*/; theme = mAssets.createTheme();
} }
private final AssetManager mAssets; 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 // out the attributes from the XML file (applying type information
// contained in the resources and such). // contained in the resources and such).
ResXmlPullParser parser = (ResXmlPullParser)set; ResXmlPullParser parser = (ResXmlPullParser)set;
mAssets.applyStyle(Collections.EMPTY_MAP, 0, 0, mAssets.applyStyle(0, 0, 0,
set, attrs, array.mData, array.mIndices); set, attrs, array.mData, array.mIndices);
array.mRsrcs = attrs; array.mRsrcs = attrs;