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);
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
* 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

View File

@@ -301,51 +301,10 @@ public final class AssetManager {
return map;
}
/*package*/ final boolean getThemeValue(Map<Integer,ValueItem> 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<Integer,ValueItem> 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<Integer,ValueItem> 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);

View File

@@ -1198,7 +1198,8 @@ public class Resources {
* retrieve XML attributes with style and theme information applied.
*/
public final class Theme {
private Map<Integer,ValueItem> themeMap = new HashMap<>();
private long theme;
/**
* Place new attribute values into the theme. The style resource
* 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.
*/
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;