replace our implementation of applyStyle with a native function that calls into libandroidfw

also change a few things to work with latest libandroidfw, since we are now using
it's helper functions that need to agree on e.g STYLE_NUM_ENTRIES with the Java
code.
This commit is contained in:
Mis012
2025-02-27 22:21:14 +01:00
parent d97c3ee048
commit f0fcd47c80
6 changed files with 139 additions and 202 deletions

View File

@@ -349,6 +349,38 @@ JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs(JN
return ret; return ret;
} }
JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_retrieveAttributes(JNIEnv *env, jobject this,
jlong parser_ptr,
jintArray java_attrs, jint attrs_len,
long out_values, long out_indices)
{
struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(this, "mObject"));
struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr);
jint *attrs = (*env)->GetIntArrayElements(env, java_attrs, 0);
return RetrieveAttributes(asset_manager, parser, (uint32_t *)attrs, attrs_len, (uint32_t *)_PTR(out_values), (uint32_t *)_PTR(out_indices));
(*env)->ReleaseIntArrayElements(env, java_attrs, attrs, JNI_ABORT);
}
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyStyle(JNIEnv *env, jclass this,
jlong theme_ptr, jlong parser_ptr,
jint def_style_attr, jint def_style_res,
jintArray java_attrs, jint attrs_len,
long out_values, long out_indices)
{
struct Theme *theme = _PTR(theme_ptr);
struct ResXMLParser *parser = (struct ResXMLParser *)_PTR(parser_ptr);
jint *attrs = (*env)->GetIntArrayElements(env, java_attrs, 0);
ApplyStyle(theme, parser, def_style_attr, def_style_res, (uint32_t *)attrs, attrs_len, (uint32_t *)_PTR(out_values), (uint32_t *)_PTR(out_indices));
(*env)->ReleaseIntArrayElements(env, java_attrs, attrs, JNI_ABORT);
}
JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_getArraySize(JNIEnv *env, jobject this, jint ident) 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")); struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(this, "mObject"));

View File

@@ -20,7 +20,7 @@ extern "C" {
#undef android_content_res_AssetManager_DEBUG_REFS #undef android_content_res_AssetManager_DEBUG_REFS
#define android_content_res_AssetManager_DEBUG_REFS 0L #define android_content_res_AssetManager_DEBUG_REFS 0L
#undef android_content_res_AssetManager_STYLE_NUM_ENTRIES #undef android_content_res_AssetManager_STYLE_NUM_ENTRIES
#define android_content_res_AssetManager_STYLE_NUM_ENTRIES 6L #define android_content_res_AssetManager_STYLE_NUM_ENTRIES 7L
#undef android_content_res_AssetManager_STYLE_TYPE #undef android_content_res_AssetManager_STYLE_TYPE
#define android_content_res_AssetManager_STYLE_TYPE 0L #define android_content_res_AssetManager_STYLE_TYPE 0L
#undef android_content_res_AssetManager_STYLE_DATA #undef android_content_res_AssetManager_STYLE_DATA
@@ -33,6 +33,8 @@ extern "C" {
#define android_content_res_AssetManager_STYLE_CHANGING_CONFIGURATIONS 4L #define android_content_res_AssetManager_STYLE_CHANGING_CONFIGURATIONS 4L
#undef android_content_res_AssetManager_STYLE_DENSITY #undef android_content_res_AssetManager_STYLE_DENSITY
#define android_content_res_AssetManager_STYLE_DENSITY 5L #define android_content_res_AssetManager_STYLE_DENSITY 5L
#undef android_content_res_AssetManager_STYLE_SOURCE_RESOURCE_ID
#define android_content_res_AssetManager_STYLE_SOURCE_RESOURCE_ID 6L
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: getPooledString * Method: getPooledString
@@ -209,6 +211,14 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceValue
JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValue JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValue
(JNIEnv *, jobject, jint, jint, jobject, jboolean); (JNIEnv *, jobject, jint, jint, jobject, jboolean);
/*
* Class: android_content_res_AssetManager
* Method: applyStyle
* Signature: (JJII[IIJJ)V
*/
JNIEXPORT void JNICALL Java_android_content_res_AssetManager_applyStyle
(JNIEnv *, jclass, jlong, jlong, jint, jint, jintArray, jint, jlong, jlong);
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: resolveAttrs * Method: resolveAttrs
@@ -217,6 +227,14 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValu
JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs
(JNIEnv *, jclass, jlong, jint, jint, jintArray, jintArray, jintArray, jintArray); (JNIEnv *, jclass, jlong, jint, jint, jintArray, jintArray, jintArray, jintArray);
/*
* Class: android_content_res_AssetManager
* Method: retrieveAttributes
* Signature: (J[IIJJ)Z
*/
JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_retrieveAttributes
(JNIEnv *, jobject, jlong, jintArray, jint, jlong, jlong);
/* /*
* Class: android_content_res_AssetManager * Class: android_content_res_AssetManager
* Method: getArraySize * Method: getArraySize

View File

@@ -700,101 +700,28 @@ public final class AssetManager {
*/ */
private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue, private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue,
boolean resolve); boolean resolve);
/*package*/ static final int STYLE_NUM_ENTRIES = 6; /*package*/ static final int STYLE_NUM_ENTRIES = 7;
/*package*/ static final int STYLE_TYPE = 0; /*package*/ static final int STYLE_TYPE = 0;
/*package*/ static final int STYLE_DATA = 1; /*package*/ static final int STYLE_DATA = 1;
/*package*/ static final int STYLE_ASSET_COOKIE = 2; /*package*/ static final int STYLE_ASSET_COOKIE = 2;
/*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(long theme, /*package*/ static final int STYLE_SOURCE_RESOURCE_ID = 6;
int defStyleAttr, int defStyleRes, AttributeSet set,
int[] inAttrs, int[] outValues, int[] outIndices) {
TypedValue value = new TypedValue();
XmlResourceParser parser = (XmlResourceParser)set;
if (defStyleRes == 0 && theme != 0 && loadThemeAttributeValue(theme, defStyleAttr, value, true) >= 0)
defStyleRes = value.data;
if (defStyleRes == 0 && set != null) {
defStyleRes = parser.getStyleAttribute();
}
outIndices[0] = 0; /*package*/ native static final void applyStyle(long theme, long parser,
int defStyleAttr, int defStyleRes,
Map<Integer,Integer> xmlCache = new HashMap<>(); int[] inAttrs, int length,
if (set != null) { long outValuesAddress, long outIndicesAddress);
for (int j=0; j<set.getAttributeCount(); j++) {
xmlCache.put(set.getAttributeNameResource(j), j);
}
}
for (int i = 0; i < inAttrs.length; i++) {
int d = i*AssetManager.STYLE_NUM_ENTRIES;
// reset values in case of cached array
int resId = inAttrs[i];
boolean found = false;
value.resourceId = 0;
value.type = -1;
value.data = 0;
value.assetCookie = -1;
while (true) {
if (resId == 0) {
value.type = 0;
value.data = 0;
value.resourceId = 0;
value.assetCookie = -1;
found = true;
} else if (xmlCache.containsKey(resId)) {
value.type = XmlBlock.nativeGetAttributeDataType(((XmlBlock.Parser)parser).mParseState, xmlCache.get(resId));
value.data = XmlBlock.nativeGetAttributeData(((XmlBlock.Parser)parser).mParseState, xmlCache.get(resId));
value.resourceId = 0;
value.assetCookie = -1;
if (value.type != TypedValue.TYPE_ATTRIBUTE)
found = true;
} else {
int block = -1;
if (theme != 0 && (value.type == TypedValue.TYPE_ATTRIBUTE || value.type == -1))
block = loadThemeAttributeValue(theme, resId, value, true);
if (block < 0 && defStyleRes != 0 && (value.type == TypedValue.TYPE_ATTRIBUTE || value.type == -1))
block = loadResourceBagValue(defStyleRes, resId, value, true);
if (block < 0 && value.type == TypedValue.TYPE_REFERENCE)
block = loadResourceValue(resId, (short)0, value, true);
if (block >= 0) {
found = true;
}
}
if (value.type == TypedValue.TYPE_REFERENCE && value.data != 0) {
String typeName = getResourceTypeName(value.data);
if ("style".equals(typeName) || "array".equals(typeName)) {
// style and array are complex types, which can't be stored in a TypedArray
value.resourceId = value.data;
break;
}
}
if ((value.type == TypedValue.TYPE_REFERENCE || value.type == TypedValue.TYPE_ATTRIBUTE) && value.data != resId) {
resId = value.data;
} else {
break;
}
}
if (found) {
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] = value.assetCookie;
outIndices[++outIndices[0]] = i;
} else {
outValues[d+AssetManager.STYLE_RESOURCE_ID] = 0;
outValues[d+AssetManager.STYLE_TYPE] = 0;
outValues[d+AssetManager.STYLE_DATA] = 0;
outValues[d+AssetManager.STYLE_ASSET_COOKIE] = -1;
}
}
return true;
}
/*package*/ native static final boolean resolveAttrs(long theme, int defStyleAttr, /*package*/ native static final boolean resolveAttrs(long theme, int defStyleAttr,
int defStyleRes, int[] inValues, int defStyleRes, int[] inValues,
int[] inAttrs, int[] outValues, int[] inAttrs, int[] outValues,
int[] outIndices); int[] outIndices);
/*package*/ native final boolean retrieveAttributes(long xmlParser,
int[] inAttrs, int length,
long outValuesAddress, long outIndicesAddress);
/*package*/ native final int getArraySize(int resource); /*package*/ native final int getArraySize(int resource);
/*package*/ native final int retrieveArray(int resource, int[] outValues); /*package*/ native final int retrieveArray(int resource, int[] outValues);
private native final int getStringBlockCount(); private native final int getStringBlockCount();

View File

@@ -527,7 +527,7 @@ public class Resources {
throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id)); throw new NotFoundException("Array resource ID #0x" + Integer.toHexString(id));
} }
TypedArray array = getCachedStyledAttributes(len); TypedArray array = TypedArray.obtain(this, len);
array.mLength = mAssets.retrieveArray(id, array.mData); array.mLength = mAssets.retrieveArray(id, array.mData);
array.mIndices[0] = 0; array.mIndices[0] = 0;
@@ -1213,6 +1213,8 @@ public class Resources {
public final class Theme { public final class Theme {
private long theme; private long theme;
private boolean debug = false;
/** /**
* 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
@@ -1267,12 +1269,7 @@ public class Resources {
* @see #obtainStyledAttributes(AttributeSet, int[], int, int) * @see #obtainStyledAttributes(AttributeSet, int[], int, int)
*/ */
public TypedArray obtainStyledAttributes(int[] attrs) { public TypedArray obtainStyledAttributes(int[] attrs) {
int len = attrs.length; return obtainStyledAttributes(null, attrs, 0, 0);
TypedArray array = getCachedStyledAttributes(len);
array.mRsrcs = attrs;
array.mTheme = this;
mAssets.applyStyle(theme, 0, 0, null, attrs, array.mData, array.mIndices);
return array;
} }
/** /**
@@ -1297,39 +1294,7 @@ public class Resources {
*/ */
public TypedArray obtainStyledAttributes(int resid, int[] attrs) public TypedArray obtainStyledAttributes(int resid, int[] attrs)
throws NotFoundException { throws NotFoundException {
int len = attrs.length; return obtainStyledAttributes(null, attrs, 0, resid);
TypedArray array = getCachedStyledAttributes(len);
array.mRsrcs = attrs;
array.mTheme = this;
mAssets.applyStyle(theme, 0, resid, null, attrs,
array.mData, array.mIndices);
if (false) {
int[] data = array.mData;
System.out.println("**********************************************************");
System.out.println("**********************************************************");
System.out.println("**********************************************************");
System.out.println("Attributes:");
String s = " Attrs:";
int i;
for (i=0; i<attrs.length; i++) {
s = s + " 0x" + Integer.toHexString(attrs[i]);
}
System.out.println(s);
s = " Found:";
TypedValue value = new TypedValue();
for (i=0; i<attrs.length; i++) {
int d = i*AssetManager.STYLE_NUM_ENTRIES;
value.type = data[d+AssetManager.STYLE_TYPE];
value.data = data[d+AssetManager.STYLE_DATA];
value.assetCookie = data[d+AssetManager.STYLE_ASSET_COOKIE];
value.resourceId = data[d+AssetManager.STYLE_RESOURCE_ID];
s = s + " 0x" + Integer.toHexString(attrs[i])
+ "=" + value;
}
System.out.println(s);
}
return array;
} }
/** /**
@@ -1383,19 +1348,21 @@ public class Resources {
public TypedArray obtainStyledAttributes(AttributeSet set, public TypedArray obtainStyledAttributes(AttributeSet set,
int[] attrs, int defStyleAttr, int defStyleRes) { int[] attrs, int defStyleAttr, int defStyleRes) {
int len = attrs.length; int len = attrs.length;
TypedArray array = getCachedStyledAttributes(len); TypedArray array = TypedArray.obtain(getResources(), len);
// XXX note that for now we only work with compiled XML files. // XXX note that for now we only work with compiled XML files.
// To support generic XML files we will need to manually parse // To support generic XML files we will need to manually parse
// 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).
XmlResourceParser parser = (XmlResourceParser)set; XmlResourceParser parser = (XmlResourceParser)set;
mAssets.applyStyle(theme, defStyleAttr, defStyleRes, AssetManager.applyStyle(theme, set != null ? ((XmlBlock.Parser)set).mParseState : 0,
set, attrs, array.mData, array.mIndices); defStyleAttr, defStyleRes,
attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
array.mRsrcs = attrs; array.mRsrcs = attrs;
array.mXml = parser; array.mXml = parser;
array.mTheme = this; array.mTheme = this;
if (false && set != null) { // TODO: set should probably never be null...?
if (debug && set != null) {
int[] data = array.mData; int[] data = array.mData;
System.out.println("Attributes:"); System.out.println("Attributes:");
@@ -1478,7 +1445,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(theme, resid, outValue, resolveRefs); boolean got = mAssets.getThemeValue(theme, resid, outValue, resolveRefs);
if (false) { if (debug) {
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));
} }
@@ -1623,17 +1590,15 @@ public class Resources {
*/ */
public TypedArray obtainAttributes(AttributeSet set, int[] attrs) { public TypedArray obtainAttributes(AttributeSet set, int[] attrs) {
int len = attrs.length; int len = attrs.length;
TypedArray array = getCachedStyledAttributes(len); TypedArray array = TypedArray.obtain(this, len);
// XXX note that for now we only work with compiled XML files. // XXX note that for now we only work with compiled XML files.
// To support generic XML files we will need to manually parse // To support generic XML files we will need to manually parse
// 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).
XmlResourceParser parser = (XmlResourceParser)set; XmlBlock.Parser parser = (XmlBlock.Parser)set;
mAssets.applyStyle(0, 0, 0, getAssets().retrieveAttributes(parser.mParseState, attrs, attrs.length, array.mDataAddress, array.mIndicesAddress);
set, attrs, array.mData, array.mIndices);
array.mRsrcs = attrs;
array.mXml = parser; array.mXml = parser;
return array; return array;
@@ -1653,7 +1618,7 @@ public class Resources {
public void updateConfiguration(Configuration config, public void updateConfiguration(Configuration config,
DisplayMetrics metrics, CompatibilityInfo compat) { DisplayMetrics metrics, CompatibilityInfo compat) {
synchronized (mAccessLock) { synchronized (mAccessLock) {
if (false) { if (DEBUG_CONFIG) {
Slog.i(TAG, "**** Updating config of " + this + ": old config is " + mConfiguration + " old compat is " + mCompatibilityInfo); Slog.i(TAG, "**** Updating config of " + this + ": old config is " + mConfiguration + " old compat is " + mCompatibilityInfo);
Slog.i(TAG, "**** Updating config of " + this + ": new config is " + config + " new compat is " + compat); Slog.i(TAG, "**** Updating config of " + this + ": new config is " + config + " new compat is " + compat);
} }
@@ -2581,40 +2546,6 @@ public class Resources {
+ Integer.toHexString(id));*/ + Integer.toHexString(id));*/
} }
private TypedArray getCachedStyledAttributes(int len) {
synchronized (mAccessLock) {
TypedArray attrs = mCachedStyledAttributes;
if (attrs != null) {
mCachedStyledAttributes = null;
if (DEBUG_ATTRIBUTES_CACHE) {
mLastRetrievedAttrs = new RuntimeException("here");
mLastRetrievedAttrs.fillInStackTrace();
}
attrs.mLength = len;
int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
if (attrs.mData.length >= fullLen) {
return attrs;
}
attrs.mData = new int[fullLen];
attrs.mIndices = new int[1 + len];
return attrs;
}
if (DEBUG_ATTRIBUTES_CACHE) {
RuntimeException here = new RuntimeException("here");
here.fillInStackTrace();
if (mLastRetrievedAttrs != null) {
Log.i(TAG, "Allocated new TypedArray of " + len + " in " + this, here);
Log.i(TAG, "Last retrieved attributes here", mLastRetrievedAttrs);
}
mLastRetrievedAttrs = here;
}
return new TypedArray(this,
new int[len * AssetManager.STYLE_NUM_ENTRIES],
new int[1 + len], len);
}
}
/** /**
* Obtains styled attributes from the theme, if available, or unstyled * Obtains styled attributes from the theme, if available, or unstyled
@@ -2630,15 +2561,4 @@ public class Resources {
return theme.obtainStyledAttributes(set, attrs, 0, 0); return theme.obtainStyledAttributes(set, attrs, 0, 0);
} }
private Resources() {
mAssets = AssetManager.getSystem();
// NOTE: Intentionally leaving this uninitialized (all values set
// to zero), so that anyone who tries to do something that requires
// metrics will get a very wrong value.
mConfiguration.setToDefaults();
mMetrics.setToDefaults();
updateConfiguration(null, null);
mAssets.ensureStringBlocks();
}
} }

View File

@@ -25,6 +25,8 @@ import android.os.StrictMode;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.DisplayMetrics; import android.util.DisplayMetrics;
import android.util.TypedValue; import android.util.TypedValue;
import dalvik.system.VMRuntime;
import com.android.internal.util.XmlUtils; import com.android.internal.util.XmlUtils;
import java.util.Arrays; import java.util.Arrays;
@@ -40,29 +42,22 @@ import java.util.Arrays;
public class TypedArray { public class TypedArray {
static TypedArray obtain(Resources res, int len) { static TypedArray obtain(Resources res, int len) {
final TypedArray attrs = res.mTypedArrayPool.acquire(); TypedArray attrs = res.mTypedArrayPool.acquire();
if (attrs != null) { if (attrs == null) {
attrs.mLength = len; attrs = new TypedArray(res);
attrs.mRecycled = false;
final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
if (attrs.mData.length >= fullLen) {
return attrs;
}
attrs.mData = new int[fullLen];
attrs.mIndices = new int[1 + len];
return attrs;
} }
return new TypedArray(res, attrs.mRecycled = false;
new int[len * AssetManager.STYLE_NUM_ENTRIES], // Reset the assets, which may have changed due to configuration changes
new int[1 + len], len); // or further resource loading.
attrs.mAssets = res.getAssets();
attrs.resize(len);
return attrs;
} }
private final Resources mResources; private final Resources mResources;
private final DisplayMetrics mMetrics; private final DisplayMetrics mMetrics;
private final AssetManager mAssets; private AssetManager mAssets;
private boolean mRecycled; private boolean mRecycled;
@@ -71,10 +66,26 @@ public class TypedArray {
/*package*/ XmlResourceParser mXml; /*package*/ XmlResourceParser mXml;
/*package*/ Resources.Theme mTheme; /*package*/ Resources.Theme mTheme;
/*package*/ int[] mData; /*package*/ int[] mData;
/*package*/ long mDataAddress;
/*package*/ int[] mIndices; /*package*/ int[] mIndices;
/*package*/ long mIndicesAddress;
/*package*/ int mLength; /*package*/ int mLength;
/*package*/ TypedValue mValue = new TypedValue(); /*package*/ TypedValue mValue = new TypedValue();
private void resize(int len) {
mLength = len;
final int dataLen = len * AssetManager.STYLE_NUM_ENTRIES;
final int indicesLen = len + 1;
final VMRuntime runtime = VMRuntime.getRuntime();
if (mData == null || mData.length < dataLen) {
mData = (int[]) runtime.newNonMovableArray(int.class, dataLen);
mDataAddress = runtime.addressOf(mData);
mIndices = (int[]) runtime.newNonMovableArray(int.class, indicesLen);
mIndicesAddress = runtime.addressOf(mIndices);
}
}
/** /**
* Returns the number of values in this array. * Returns the number of values in this array.
* *
@@ -954,6 +965,31 @@ public class TypedArray {
return mData[index + AssetManager.STYLE_TYPE]; return mData[index + AssetManager.STYLE_TYPE];
} }
/**
* Returns the resource ID of the style against which the specified attribute was resolved,
* otherwise returns defValue.
*
* @param index Index of attribute whose source style to retrieve.
* @param defValue Value to return if the attribute is not defined or
* not a resource.
*
* @return Attribute source style resource ID or defValue if it was not resolved in any style.
* @throws RuntimeException if the TypedArray has already been recycled.
*/
public int getSourceStyleResourceId(/*@StyleableRes*/ int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES;
final int resid = mData[index + AssetManager.STYLE_SOURCE_RESOURCE_ID];
if (resid != 0) {
return resid;
}
return defValue;
}
/** /**
* Determines whether there is an attribute at <var>index</var>. * Determines whether there is an attribute at <var>index</var>.
* <p> * <p>
@@ -1159,6 +1195,7 @@ public class TypedArray {
outValue.changingConfigurations = data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]; outValue.changingConfigurations = data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS];
outValue.density = data[index + AssetManager.STYLE_DENSITY]; outValue.density = data[index + AssetManager.STYLE_DENSITY];
outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null; outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null;
outValue.sourceStyleResourceId = data[index + AssetManager.STYLE_SOURCE_RESOURCE_ID];
return true; return true;
} }
@@ -1175,14 +1212,10 @@ public class TypedArray {
return mAssets.getPooledString(cookie, data[index + AssetManager.STYLE_DATA]); return mAssets.getPooledString(cookie, data[index + AssetManager.STYLE_DATA]);
} }
// FIXME protected TypedArray(Resources resources) {
public /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) {
mResources = resources; mResources = resources;
mMetrics = mResources.mMetrics; mMetrics = mResources.mMetrics;
mAssets = mResources.mAssets; mAssets = mResources.mAssets;
mData = data;
mIndices = indices;
mLength = len;
} }
@Override @Override

View File

@@ -273,6 +273,13 @@ public class TypedValue {
* */ * */
public int density; public int density;
/**
* If the Value came from a style resource, this holds the corresponding style resource id
* against which the attribute was resolved.
*/
public int sourceStyleResourceId;
/* ------------------------------------------------------------ */ /* ------------------------------------------------------------ */
/** /**