summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAurimas Liutikas <aurimas@google.com>2019-01-30 17:20:41 -0800
committerAurimas Liutikas <aurimas@google.com>2019-01-31 15:44:51 -0800
commit949b05dbdcefb95c44c5c40f19ceae1336021a61 (patch)
tree061dc86de2ea3810976ea4dcbe01f2f7c607ab2f
parentc7829fcab8093359bea69406cb00943a063381a5 (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.txt4
-rw-r--r--core/java/android/content/res/TypedArray.java43
-rw-r--r--core/java/android/content/res/XmlBlock.java12
-rw-r--r--core/java/android/util/TypedValue.java6
-rw-r--r--core/jni/android_util_XmlBlock.cpp18
-rw-r--r--libs/androidfw/AttributeResolution.cpp10
-rw-r--r--libs/androidfw/ResourceTypes.cpp10
-rw-r--r--libs/androidfw/include/androidfw/AttributeResolution.h2
-rw-r--r--libs/androidfw/include/androidfw/ResourceTypes.h4
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>
+ * &lt;View
+ * style="@style/viewStyle"
+ * android:layout_width="wrap_content"
+ * android:layout_height="wrap_content"
+ * android:attribute1="foo"/&gt;
+ * </pre>
+ *
+ * and {@code @style/viewStyle} is:
+ * <pre>
+ * &lt;style android:name="viewStyle"&gt;
+ * &lt;item name="android:attribute2"&gt;bar&lt;item/&gt;
+ * &lt;style/&gt;
+ * </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;