diff --git a/src/api-impl-jni/android_content_res_AssetManager.c b/src/api-impl-jni/android_content_res_AssetManager.c index 17b69e42..27472a45 100644 --- a/src/api-impl-jni/android_content_res_AssetManager.c +++ b/src/api-impl-jni/android_content_res_AssetManager.c @@ -349,6 +349,38 @@ JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs(JN 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) { struct AssetManager *asset_manager = _PTR(_GET_LONG_FIELD(this, "mObject")); 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 4cd59fb9..912545a3 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 @@ -20,7 +20,7 @@ extern "C" { #undef android_content_res_AssetManager_DEBUG_REFS #define android_content_res_AssetManager_DEBUG_REFS 0L #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 #define android_content_res_AssetManager_STYLE_TYPE 0L #undef android_content_res_AssetManager_STYLE_DATA @@ -33,6 +33,8 @@ extern "C" { #define android_content_res_AssetManager_STYLE_CHANGING_CONFIGURATIONS 4L #undef android_content_res_AssetManager_STYLE_DENSITY #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 * Method: getPooledString @@ -209,6 +211,14 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceValue JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValue (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 * Method: resolveAttrs @@ -217,6 +227,14 @@ JNIEXPORT jint JNICALL Java_android_content_res_AssetManager_loadResourceBagValu JNIEXPORT jboolean JNICALL Java_android_content_res_AssetManager_resolveAttrs (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 * Method: getArraySize diff --git a/src/api-impl/android/content/res/AssetManager.java b/src/api-impl/android/content/res/AssetManager.java index f4905b5a..fd6d84b6 100644 --- a/src/api-impl/android/content/res/AssetManager.java +++ b/src/api-impl/android/content/res/AssetManager.java @@ -700,101 +700,28 @@ public final class AssetManager { */ private native final int loadResourceBagValue(int ident, int bagEntryId, TypedValue outValue, 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_DATA = 1; /*package*/ static final int STYLE_ASSET_COOKIE = 2; /*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(long theme, - 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(); - } + /*package*/ static final int STYLE_SOURCE_RESOURCE_ID = 6; - outIndices[0] = 0; - - Map xmlCache = new HashMap<>(); - if (set != null) { - for (int j=0; j= 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 void applyStyle(long theme, long parser, + int defStyleAttr, int defStyleRes, + int[] inAttrs, int length, + long outValuesAddress, long outIndicesAddress); /*package*/ native static final boolean resolveAttrs(long theme, int defStyleAttr, int defStyleRes, int[] inValues, int[] inAttrs, int[] outValues, 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 retrieveArray(int resource, int[] outValues); private native final int getStringBlockCount(); diff --git a/src/api-impl/android/content/res/Resources.java b/src/api-impl/android/content/res/Resources.java index 0700d46f..fd8fc3b3 100644 --- a/src/api-impl/android/content/res/Resources.java +++ b/src/api-impl/android/content/res/Resources.java @@ -527,7 +527,7 @@ public class Resources { 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.mIndices[0] = 0; @@ -1213,6 +1213,8 @@ public class Resources { public final class Theme { private long theme; + private boolean debug = false; + /** * Place new attribute values into the theme. The style resource * specified by resid will be retrieved from this Theme's @@ -1267,12 +1269,7 @@ public class Resources { * @see #obtainStyledAttributes(AttributeSet, int[], int, int) */ public TypedArray obtainStyledAttributes(int[] attrs) { - int len = attrs.length; - TypedArray array = getCachedStyledAttributes(len); - array.mRsrcs = attrs; - array.mTheme = this; - mAssets.applyStyle(theme, 0, 0, null, attrs, array.mData, array.mIndices); - return array; + return obtainStyledAttributes(null, attrs, 0, 0); } /** @@ -1297,39 +1294,7 @@ public class Resources { */ public TypedArray obtainStyledAttributes(int resid, int[] attrs) throws NotFoundException { - int len = attrs.length; - 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= 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 @@ -2630,15 +2561,4 @@ public class Resources { 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(); - } } diff --git a/src/api-impl/android/content/res/TypedArray.java b/src/api-impl/android/content/res/TypedArray.java index ade0787d..b6078f3a 100644 --- a/src/api-impl/android/content/res/TypedArray.java +++ b/src/api-impl/android/content/res/TypedArray.java @@ -25,6 +25,8 @@ import android.os.StrictMode; import android.util.AttributeSet; import android.util.DisplayMetrics; import android.util.TypedValue; +import dalvik.system.VMRuntime; + import com.android.internal.util.XmlUtils; import java.util.Arrays; @@ -40,29 +42,22 @@ import java.util.Arrays; public class TypedArray { static TypedArray obtain(Resources res, int len) { - final TypedArray attrs = res.mTypedArrayPool.acquire(); - if (attrs != null) { - attrs.mLength = len; - 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; + TypedArray attrs = res.mTypedArrayPool.acquire(); + if (attrs == null) { + attrs = new TypedArray(res); } - return new TypedArray(res, - new int[len * AssetManager.STYLE_NUM_ENTRIES], - new int[1 + len], len); + attrs.mRecycled = false; + // Reset the assets, which may have changed due to configuration changes + // or further resource loading. + attrs.mAssets = res.getAssets(); + attrs.resize(len); + return attrs; } private final Resources mResources; private final DisplayMetrics mMetrics; - private final AssetManager mAssets; + private AssetManager mAssets; private boolean mRecycled; @@ -71,10 +66,26 @@ public class TypedArray { /*package*/ XmlResourceParser mXml; /*package*/ Resources.Theme mTheme; /*package*/ int[] mData; + /*package*/ long mDataAddress; /*package*/ int[] mIndices; + /*package*/ long mIndicesAddress; /*package*/ int mLength; /*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. * @@ -954,6 +965,31 @@ public class TypedArray { 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 index. *

@@ -1159,6 +1195,7 @@ public class TypedArray { outValue.changingConfigurations = data[index + AssetManager.STYLE_CHANGING_CONFIGURATIONS]; outValue.density = data[index + AssetManager.STYLE_DENSITY]; outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null; + outValue.sourceStyleResourceId = data[index + AssetManager.STYLE_SOURCE_RESOURCE_ID]; return true; } @@ -1175,14 +1212,10 @@ public class TypedArray { return mAssets.getPooledString(cookie, data[index + AssetManager.STYLE_DATA]); } - // FIXME - public /*package*/ TypedArray(Resources resources, int[] data, int[] indices, int len) { + protected TypedArray(Resources resources) { mResources = resources; mMetrics = mResources.mMetrics; mAssets = mResources.mAssets; - mData = data; - mIndices = indices; - mLength = len; } @Override diff --git a/src/api-impl/android/util/TypedValue.java b/src/api-impl/android/util/TypedValue.java index e486ff29..4d23ec8e 100644 --- a/src/api-impl/android/util/TypedValue.java +++ b/src/api-impl/android/util/TypedValue.java @@ -273,6 +273,13 @@ public class TypedValue { * */ 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; + /* ------------------------------------------------------------ */ /**