You've already forked android_translation_layer
mirror of
https://gitlab.com/android_translation_layer/android_translation_layer.git
synced 2025-10-27 11:48:10 -07:00
use libandroidfw also for themes
This commit is contained in:
@@ -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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user