Merge "Update TypedArray and TypedValue to store source layouts."
This commit is contained in:
committed by
Android (Google) Code Review
commit
ce37d9027d
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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++;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user