diff options
author | Aurimas Liutikas <aurimas@google.com> | 2019-01-30 17:20:41 -0800 |
---|---|---|
committer | Aurimas Liutikas <aurimas@google.com> | 2019-01-31 15:44:51 -0800 |
commit | 949b05dbdcefb95c44c5c40f19ceae1336021a61 (patch) | |
tree | 061dc86de2ea3810976ea4dcbe01f2f7c607ab2f | |
parent | c7829fcab8093359bea69406cb00943a063381a5 (diff) |
Update TypedArray and TypedValue to store source layouts.
In ag/5859897 we started tracking source styles for each TypedValue.
It is also useful to keep track of source layouts if the attribute
was resolved against a layout (attribute set in XML layout inside
of <View> tag).
Test: atest CtsContentTestCases:android.content.res.cts.TypedArrayTest
Bug: 111439551
Change-Id: Ie6bc6ecd9a22b536a2f3288263b896f9cec67d38
-rw-r--r-- | api/current.txt | 4 | ||||
-rw-r--r-- | core/java/android/content/res/TypedArray.java | 43 | ||||
-rw-r--r-- | core/java/android/content/res/XmlBlock.java | 12 | ||||
-rw-r--r-- | core/java/android/util/TypedValue.java | 6 | ||||
-rw-r--r-- | core/jni/android_util_XmlBlock.cpp | 18 | ||||
-rw-r--r-- | libs/androidfw/AttributeResolution.cpp | 10 | ||||
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 10 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/AttributeResolution.h | 2 | ||||
-rw-r--r-- | libs/androidfw/include/androidfw/ResourceTypes.h | 4 |
9 files changed, 81 insertions, 28 deletions
diff --git a/api/current.txt b/api/current.txt index cb62ffc770e1..31edcb5b1e50 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12387,7 +12387,7 @@ package android.content.res { method public String getPositionDescription(); method @AnyRes public int getResourceId(@StyleableRes int, int); method public android.content.res.Resources getResources(); - method @StyleRes public int getSourceStyleResourceId(@StyleableRes int, @StyleRes int); + method @StyleRes public int getSourceResourceId(@StyleableRes int, @StyleRes int); method @Nullable public String getString(@StyleableRes int); method public CharSequence getText(@StyleableRes int); method public CharSequence[] getTextArray(@StyleableRes int); @@ -48534,7 +48534,7 @@ package android.util { field public int data; field public int density; field @AnyRes public int resourceId; - field public int sourceStyleResourceId; + field public int sourceResourceId; field public CharSequence string; field public int type; } diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java index d53834c657cc..d36e076381eb 100644 --- a/core/java/android/content/res/TypedArray.java +++ b/core/java/android/content/res/TypedArray.java @@ -72,7 +72,7 @@ public class TypedArray { static final int STYLE_RESOURCE_ID = 3; static final int STYLE_CHANGING_CONFIGURATIONS = 4; static final int STYLE_DENSITY = 5; - static final int SYTLE_SOURCE_STYLE_RESOURCE_ID = 6; + static final int SYTLE_SOURCE_RESOURCE_ID = 6; @UnsupportedAppUsage private final Resources mResources; @@ -1101,28 +1101,51 @@ public class TypedArray { } /** - * Returns the resource ID of the style against which the specified attribute was resolved, - * otherwise returns defValue. + * Returns the resource ID of the style or layout against which the specified attribute was + * resolved, otherwise returns defValue. + * + * For example, if you we resolving two attributes {@code android:attribute1} and + * {@code android:attribute2} and you were inflating a {@link android.view.View} from + * {@code layout/my_layout.xml}: + * <pre> + * <View + * style="@style/viewStyle" + * android:layout_width="wrap_content" + * android:layout_height="wrap_content" + * android:attribute1="foo"/> + * </pre> + * + * and {@code @style/viewStyle} is: + * <pre> + * <style android:name="viewStyle"> + * <item name="android:attribute2">bar<item/> + * <style/> + * </pre> + * + * then resolved {@link TypedArray} will have values that return source resource ID of + * {@code R.layout.my_layout} for {@code android:attribute1} and {@code R.style.viewStyle} for + * {@code android:attribute2}. * * @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. + * @param defaultValue 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. + * @return Either a style resource ID, layout resource ID, or defaultValue if it was not + * resolved in a style or layout. * @throws RuntimeException if the TypedArray has already been recycled. */ @StyleRes - public int getSourceStyleResourceId(@StyleableRes int index, @StyleRes int defValue) { + public int getSourceResourceId(@StyleableRes int index, @StyleRes int defaultValue) { if (mRecycled) { throw new RuntimeException("Cannot make calls to a recycled instance!"); } index *= STYLE_NUM_ENTRIES; - final int resid = mData[index + SYTLE_SOURCE_STYLE_RESOURCE_ID]; + final int resid = mData[index + SYTLE_SOURCE_RESOURCE_ID]; if (resid != 0) { return resid; } - return defValue; + return defaultValue; } /** @@ -1337,7 +1360,7 @@ public class TypedArray { data[index + STYLE_CHANGING_CONFIGURATIONS]); outValue.density = data[index + STYLE_DENSITY]; outValue.string = (type == TypedValue.TYPE_STRING) ? loadStringValueAt(index) : null; - outValue.sourceStyleResourceId = data[index + SYTLE_SOURCE_STYLE_RESOURCE_ID]; + outValue.sourceResourceId = data[index + SYTLE_SOURCE_RESOURCE_ID]; return true; } diff --git a/core/java/android/content/res/XmlBlock.java b/core/java/android/content/res/XmlBlock.java index d8c3ddec66f8..626bf77046bf 100644 --- a/core/java/android/content/res/XmlBlock.java +++ b/core/java/android/content/res/XmlBlock.java @@ -82,23 +82,22 @@ final class XmlBlock implements AutoCloseable { public XmlResourceParser newParser(@AnyRes int resId) { synchronized (this) { if (mNative != 0) { - return new Parser(nativeCreateParseState(mNative), this, resId); + return new Parser(nativeCreateParseState(mNative, resId), this); } return null; } } /*package*/ final class Parser implements XmlResourceParser { - Parser(long parseState, XmlBlock block, @AnyRes int sourceResId) { + Parser(long parseState, XmlBlock block) { mParseState = parseState; mBlock = block; block.mOpenCount++; - mSourceResId = sourceResId; } @AnyRes public int getSourceResId() { - return mSourceResId; + return nativeGetSourceResId(mParseState); } public void setFeature(String name, boolean state) throws XmlPullParserException { @@ -486,7 +485,6 @@ final class XmlBlock implements AutoCloseable { private boolean mDecNextDepth = false; private int mDepth = 0; private int mEventType = START_DOCUMENT; - private @AnyRes int mSourceResId; } protected void finalize() throws Throwable { @@ -515,7 +513,7 @@ final class XmlBlock implements AutoCloseable { int offset, int size); private static final native long nativeGetStringBlock(long obj); - private static final native long nativeCreateParseState(long obj); + private static final native long nativeCreateParseState(long obj, int resId); private static final native void nativeDestroyParseState(long state); private static final native void nativeDestroy(long obj); @@ -553,4 +551,6 @@ final class XmlBlock implements AutoCloseable { private static final native int nativeGetStyleAttribute(long state); @FastNative private static final native int nativeGetAttributeIndex(long state, String namespace, String name); + @FastNative + private static final native int nativeGetSourceResId(long state); } diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java index 99106bedb314..7f1ee302903b 100644 --- a/core/java/android/util/TypedValue.java +++ b/core/java/android/util/TypedValue.java @@ -217,10 +217,10 @@ 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. + * If the Value came from a style resource or a layout resource (set in an XML layout), this + * holds the corresponding style or layout resource id against which the attribute was resolved. */ - public int sourceStyleResourceId; + public int sourceResourceId; /* ------------------------------------------------------------ */ diff --git a/core/jni/android_util_XmlBlock.cpp b/core/jni/android_util_XmlBlock.cpp index ad6bad2dfb79..1dc68343047b 100644 --- a/core/jni/android_util_XmlBlock.cpp +++ b/core/jni/android_util_XmlBlock.cpp @@ -72,7 +72,7 @@ static jlong android_content_XmlBlock_nativeGetStringBlock(JNIEnv* env, jobject } static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobject clazz, - jlong token) + jlong token, jint res_id) { ResXMLTree* osb = reinterpret_cast<ResXMLTree*>(token); if (osb == NULL) { @@ -81,6 +81,7 @@ static jlong android_content_XmlBlock_nativeCreateParseState(JNIEnv* env, jobjec } ResXMLParser* st = new ResXMLParser(*osb); + st->setSourceResourceId(res_id); if (st == NULL) { jniThrowException(env, "java/lang/OutOfMemoryError", NULL); return 0; @@ -335,6 +336,17 @@ static jint android_content_XmlBlock_nativeGetStyleAttribute(JNIEnv* env, jobjec ? value.data : 0; } +static jint android_content_XmlBlock_nativeGetSourceResId(JNIEnv* env, jobject clazz, + jlong token) +{ + ResXMLParser* st = reinterpret_cast<ResXMLParser*>(token); + if (st == NULL) { + return 0; + } else { + return st->getSourceResourceId(); + } +} + static void android_content_XmlBlock_nativeDestroyParseState(JNIEnv* env, jobject clazz, jlong token) { @@ -370,7 +382,7 @@ static const JNINativeMethod gXmlBlockMethods[] = { (void*) android_content_XmlBlock_nativeCreate }, { "nativeGetStringBlock", "(J)J", (void*) android_content_XmlBlock_nativeGetStringBlock }, - { "nativeCreateParseState", "(J)J", + { "nativeCreateParseState", "(JI)J", (void*) android_content_XmlBlock_nativeCreateParseState }, { "nativeDestroyParseState", "(J)V", (void*) android_content_XmlBlock_nativeDestroyParseState }, @@ -411,6 +423,8 @@ static const JNINativeMethod gXmlBlockMethods[] = { (void*) android_content_XmlBlock_nativeGetClassAttribute }, { "nativeGetStyleAttribute", "(J)I", (void*) android_content_XmlBlock_nativeGetStyleAttribute }, + { "nativeGetSourceResId", "(J)I", + (void*) android_content_XmlBlock_nativeGetSourceResId}, }; int register_android_content_XmlBlock(JNIEnv* env) diff --git a/libs/androidfw/AttributeResolution.cpp b/libs/androidfw/AttributeResolution.cpp index 18d74efdbacf..cc177af7be6f 100644 --- a/libs/androidfw/AttributeResolution.cpp +++ b/libs/androidfw/AttributeResolution.cpp @@ -286,7 +286,7 @@ void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, value.dataType = Res_value::TYPE_NULL; value.data = Res_value::DATA_NULL_UNDEFINED; config.density = 0; - uint32_t source_style_resid = 0; + uint32_t value_source_resid = 0; // Try to find a value for this attribute... we prioritize values // coming from, first XML attributes, then XML style, then default @@ -300,6 +300,7 @@ void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, if (kDebugStyles) { ALOGI("-> From XML: type=0x%x, data=0x%08x", value.dataType, value.data); } + value_source_resid = xml_parser->getSourceResourceId(); } if (value.dataType == Res_value::TYPE_NULL && value.data != Res_value::DATA_NULL_EMPTY) { @@ -310,7 +311,7 @@ void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, cookie = entry->cookie; type_set_flags = style_flags; value = entry->value; - source_style_resid = entry->style; + value_source_resid = entry->style; if (kDebugStyles) { ALOGI("-> From style: type=0x%x, data=0x%08x, style=0x%08x", value.dataType, value.data, entry->style); @@ -330,7 +331,7 @@ void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, ALOGI("-> From def style: type=0x%x, data=0x%08x, style=0x%08x", value.dataType, value.data, entry->style); } - source_style_resid = entry->style; + value_source_resid = entry->style; } } @@ -349,6 +350,7 @@ void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, } else if (value.data != Res_value::DATA_NULL_EMPTY) { // If we still don't have a value for this attribute, try to find it in the theme! ApkAssetsCookie new_cookie = theme->GetAttribute(cur_ident, &value, &type_set_flags); + // TODO: set value_source_resid for the style in the theme that was used. if (new_cookie != kInvalidCookie) { if (kDebugStyles) { ALOGI("-> From theme: type=0x%x, data=0x%08x", value.dataType, value.data); @@ -386,7 +388,7 @@ void ApplyStyle(Theme* theme, ResXMLParser* xml_parser, uint32_t def_style_attr, out_values[STYLE_RESOURCE_ID] = resid; out_values[STYLE_CHANGING_CONFIGURATIONS] = type_set_flags; out_values[STYLE_DENSITY] = config.density; - out_values[SYTLE_SOURCE_STYLE] = source_style_resid; + out_values[SYTLE_SOURCE_RESOURCE_ID] = value_source_resid; if (value.dataType != Res_value::TYPE_NULL || value.data == Res_value::DATA_NULL_EMPTY) { indices_idx++; diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index 63b25270f116..11e4cb835d65 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -1594,6 +1594,16 @@ void ResXMLParser::setPosition(const ResXMLParser::ResXMLPosition& pos) mCurExt = pos.curExt; } +void ResXMLParser::setSourceResourceId(const uint32_t resId) +{ + mSourceResourceId = resId; +} + +uint32_t ResXMLParser::getSourceResourceId() const +{ + return mSourceResourceId; +} + // -------------------------------------------------------------------- static volatile int32_t gCount = 0; diff --git a/libs/androidfw/include/androidfw/AttributeResolution.h b/libs/androidfw/include/androidfw/AttributeResolution.h index c88004c70687..0cc1d3c56cc4 100644 --- a/libs/androidfw/include/androidfw/AttributeResolution.h +++ b/libs/androidfw/include/androidfw/AttributeResolution.h @@ -33,7 +33,7 @@ enum { STYLE_RESOURCE_ID = 3, STYLE_CHANGING_CONFIGURATIONS = 4, STYLE_DENSITY = 5, - SYTLE_SOURCE_STYLE = 6 + SYTLE_SOURCE_RESOURCE_ID = 6 }; // These are all variations of the same method. They each perform the exact same operation, diff --git a/libs/androidfw/include/androidfw/ResourceTypes.h b/libs/androidfw/include/androidfw/ResourceTypes.h index 1655e89a9b97..742813e58129 100644 --- a/libs/androidfw/include/androidfw/ResourceTypes.h +++ b/libs/androidfw/include/androidfw/ResourceTypes.h @@ -782,6 +782,9 @@ public: void getPosition(ResXMLPosition* pos) const; void setPosition(const ResXMLPosition& pos); + void setSourceResourceId(const uint32_t resId); + uint32_t getSourceResourceId() const; + private: friend class ResXMLTree; @@ -791,6 +794,7 @@ private: event_code_t mEventCode; const ResXMLTree_node* mCurNode; const void* mCurExt; + uint32_t mSourceResourceId; }; class DynamicRefTable; |