Merge "Update TypedArray and TypedValue to store source layouts."

This commit is contained in:
Aurimas Liutikas
2019-02-01 20:35:23 +00:00
committed by Android (Google) Code Review
9 changed files with 81 additions and 28 deletions

View File

@@ -12388,7 +12388,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;
}

View File

@@ -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;
}

View File

@@ -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);
}

View File

@@ -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;
/* ------------------------------------------------------------ */

View File

@@ -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)

View File

@@ -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++;

View File

@@ -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;

View File

@@ -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,

View File

@@ -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;