summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Viverette <alanv@google.com>2014-10-31 00:25:37 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2014-10-31 00:25:37 +0000
commitf2ae40739a8aa5b4a48427685a66292c930f6fa0 (patch)
treebc4d5c35c86c1d25f8e308cb34b7fa65cdec61d7
parent2929579d20cd036305c764a66a2623b954327b05 (diff)
parent9a77c8a279bfe3293295ed77c775ea29b88b2916 (diff)
downloadframeworks_base-f2ae40739a8aa5b4a48427685a66292c930f6fa0.zip
frameworks_base-f2ae40739a8aa5b4a48427685a66292c930f6fa0.tar.gz
frameworks_base-f2ae40739a8aa5b4a48427685a66292c930f6fa0.tar.bz2
am 9a77c8a2: am 3c5cc234: am 674a3a21: Merge "Distinguish unspecified and explicit null values in resources" into lmp-mr1-dev
* commit '9a77c8a279bfe3293295ed77c775ea29b88b2916': Distinguish unspecified and explicit null values in resources
-rw-r--r--api/current.txt3
-rw-r--r--core/java/android/content/res/TypedArray.java24
-rw-r--r--core/java/android/util/TypedValue.java11
-rw-r--r--core/jni/android_util_AssetManager.cpp10
-rw-r--r--core/res/res/values/styles_material.xml20
-rw-r--r--include/androidfw/ResourceTypes.h11
-rw-r--r--libs/androidfw/ResourceTypes.cpp16
7 files changed, 80 insertions, 15 deletions
diff --git a/api/current.txt b/api/current.txt
index 583a3a8..b9a09f0 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -9261,6 +9261,7 @@ package android.content.res {
method public int getType(int);
method public boolean getValue(int, android.util.TypedValue);
method public boolean hasValue(int);
+ method public boolean hasValueOrEmpty(int);
method public int length();
method public android.util.TypedValue peekValue(int);
method public void recycle();
@@ -32412,6 +32413,8 @@ package android.util {
field public static final int COMPLEX_UNIT_PX = 0; // 0x0
field public static final int COMPLEX_UNIT_SHIFT = 0; // 0x0
field public static final int COMPLEX_UNIT_SP = 2; // 0x2
+ field public static final int DATA_NULL_EMPTY = 1; // 0x1
+ field public static final int DATA_NULL_UNDEFINED = 0; // 0x0
field public static final int DENSITY_DEFAULT = 0; // 0x0
field public static final int DENSITY_NONE = 65535; // 0xffff
field public static final int TYPE_ATTRIBUTE = 2; // 0x2
diff --git a/core/java/android/content/res/TypedArray.java b/core/java/android/content/res/TypedArray.java
index 73b93c6..02602fb 100644
--- a/core/java/android/content/res/TypedArray.java
+++ b/core/java/android/content/res/TypedArray.java
@@ -807,6 +807,9 @@ public class TypedArray {
/**
* Determines whether there is an attribute at <var>index</var>.
+ * <p>
+ * <strong>Note:</strong> If the attribute was set to {@code @empty} or
+ * {@code @undefined}, this method returns {@code false}.
*
* @param index Index of attribute to retrieve.
*
@@ -824,6 +827,27 @@ public class TypedArray {
}
/**
+ * Determines whether there is an attribute at <var>index</var>, returning
+ * {@code true} if the attribute was explicitly set to {@code @empty} and
+ * {@code false} only if the attribute was undefined.
+ *
+ * @param index Index of attribute to retrieve.
+ *
+ * @return True if the attribute has a value or is empty, false otherwise.
+ */
+ public boolean hasValueOrEmpty(int index) {
+ if (mRecycled) {
+ throw new RuntimeException("Cannot make calls to a recycled instance!");
+ }
+
+ index *= AssetManager.STYLE_NUM_ENTRIES;
+ final int[] data = mData;
+ final int type = data[index+AssetManager.STYLE_TYPE];
+ return type != TypedValue.TYPE_NULL
+ || data[index+AssetManager.STYLE_DATA] == TypedValue.DATA_NULL_EMPTY;
+ }
+
+ /**
* Retrieve the raw TypedValue for the attribute at <var>index</var>
* and return a temporary object holding its data. This object is only
* valid until the next call on to {@link TypedArray}.
diff --git a/core/java/android/util/TypedValue.java b/core/java/android/util/TypedValue.java
index 931fb81..d42ed03 100644
--- a/core/java/android/util/TypedValue.java
+++ b/core/java/android/util/TypedValue.java
@@ -139,6 +139,17 @@ public class TypedValue {
/* ------------------------------------------------------------ */
/**
+ * {@link #TYPE_NULL} data indicating the value was not specified.
+ */
+ public static final int DATA_NULL_UNDEFINED = 0;
+ /**
+ * {@link #TYPE_NULL} data indicating the value was explicitly set to null.
+ */
+ public static final int DATA_NULL_EMPTY = 1;
+
+ /* ------------------------------------------------------------ */
+
+ /**
* If {@link #density} is equal to this value, then the density should be
* treated as the system's default density value: {@link DisplayMetrics#DENSITY_DEFAULT}.
*/
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index 4859ee6..94098c9 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -1095,7 +1095,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
// coming from, first XML attributes, then XML style, then default
// style, and finally the theme.
value.dataType = Res_value::TYPE_NULL;
- value.data = 0;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
typeSetFlags = 0;
config.density = 0;
@@ -1157,6 +1157,7 @@ static jboolean android_content_AssetManager_resolveAttrs(JNIEnv* env, jobject c
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
DEBUG_STYLES(ALOGI("-> Setting to @null!"));
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
block = -1;
}
@@ -1319,7 +1320,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
// coming from, first XML attributes, then XML style, then default
// style, and finally the theme.
value.dataType = Res_value::TYPE_NULL;
- value.data = 0;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
typeSetFlags = 0;
config.density = 0;
@@ -1403,6 +1404,7 @@ static jboolean android_content_AssetManager_applyStyle(JNIEnv* env, jobject cla
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
DEBUG_STYLES(ALOGI("-> Setting to @null!"));
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
block = kXmlBlock;
}
@@ -1512,7 +1514,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
// Try to find a value for this attribute...
value.dataType = Res_value::TYPE_NULL;
- value.data = 0;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
typeSetFlags = 0;
config.density = 0;
@@ -1548,6 +1550,7 @@ static jboolean android_content_AssetManager_retrieveAttributes(JNIEnv* env, job
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
}
//printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
@@ -1661,6 +1664,7 @@ static jint android_content_AssetManager_retrieveArray(JNIEnv* env, jobject claz
// Deal with the special @null value -- it turns back to TYPE_NULL.
if (value.dataType == Res_value::TYPE_REFERENCE && value.data == 0) {
value.dataType = Res_value::TYPE_NULL;
+ value.data = Res_value::DATA_NULL_UNDEFINED;
}
//printf("Attribute 0x%08x: final type=0x%x, data=0x%08x\n", curIdent, value.dataType, value.data);
diff --git a/core/res/res/values/styles_material.xml b/core/res/res/values/styles_material.xml
index 6e03b3d..cc3ded5 100644
--- a/core/res/res/values/styles_material.xml
+++ b/core/res/res/values/styles_material.xml
@@ -1091,16 +1091,16 @@ please see styles_device_defaults.xml.
<!-- Dialog styles -->
<style name="AlertDialog.Material" parent="AlertDialog">
- <item name="fullDark">@null</item>
- <item name="topDark">@null</item>
- <item name="centerDark">@null</item>
- <item name="bottomDark">@null</item>
- <item name="fullBright">@null</item>
- <item name="topBright">@null</item>
- <item name="centerBright">@null</item>
- <item name="bottomBright">@null</item>
- <item name="bottomMedium">@null</item>
- <item name="centerMedium">@null</item>
+ <item name="fullDark">@empty</item>
+ <item name="topDark">@empty</item>
+ <item name="centerDark">@empty</item>
+ <item name="bottomDark">@empty</item>
+ <item name="fullBright">@empty</item>
+ <item name="topBright">@empty</item>
+ <item name="centerBright">@empty</item>
+ <item name="bottomBright">@empty</item>
+ <item name="bottomMedium">@empty</item>
+ <item name="centerMedium">@empty</item>
<item name="layout">@layout/alert_dialog_material</item>
<item name="listLayout">@layout/select_dialog_material</item>
<item name="progressLayout">@layout/progress_dialog_material</item>
diff --git a/include/androidfw/ResourceTypes.h b/include/androidfw/ResourceTypes.h
index ce30d81..051d554 100644
--- a/include/androidfw/ResourceTypes.h
+++ b/include/androidfw/ResourceTypes.h
@@ -253,7 +253,8 @@ struct Res_value
// Type of the data value.
enum {
- // Contains no data.
+ // The 'data' is either 0 or 1, specifying this resource is either
+ // undefined or empty, respectively.
TYPE_NULL = 0x00,
// The 'data' holds a ResTable_ref, a reference to another resource
// table entry.
@@ -351,6 +352,14 @@ struct Res_value
COMPLEX_MANTISSA_MASK = 0xffffff
};
+ // Possible data values for TYPE_NULL.
+ enum {
+ // The value is not defined.
+ DATA_NULL_UNDEFINED = 0,
+ // The value is explicitly defined as empty.
+ DATA_NULL_EMPTY = 1
+ };
+
// The data for this item, as interpreted according to dataType.
uint32_t data;
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp
index 26cb49d..2a7af0d 100644
--- a/libs/androidfw/ResourceTypes.cpp
+++ b/libs/androidfw/ResourceTypes.cpp
@@ -4639,8 +4639,15 @@ bool ResTable::stringToValue(Res_value* outValue, String16* outString,
// It's a reference!
if (len == 5 && s[1]=='n' && s[2]=='u' && s[3]=='l' && s[4]=='l') {
+ // Special case @null as undefined. This will be converted by
+ // AssetManager to TYPE_NULL with data DATA_NULL_UNDEFINED.
outValue->data = 0;
return true;
+ } else if (len == 6 && s[1]=='e' && s[2]=='m' && s[3]=='p' && s[4]=='t' && s[5]=='y') {
+ // Special case @empty as explicitly defined empty value.
+ outValue->dataType = Res_value::TYPE_NULL;
+ outValue->data = Res_value::DATA_NULL_EMPTY;
+ return true;
} else {
bool createIfNotFound = false;
const char16_t* resourceRefName;
@@ -6251,7 +6258,14 @@ String8 ResTable::normalizeForOutput( const char *input )
void ResTable::print_value(const Package* pkg, const Res_value& value) const
{
if (value.dataType == Res_value::TYPE_NULL) {
- printf("(null)\n");
+ if (value.data == Res_value::DATA_NULL_UNDEFINED) {
+ printf("(null)\n");
+ } else if (value.data == Res_value::DATA_NULL_EMPTY) {
+ printf("(null empty)\n");
+ } else {
+ // This should never happen.
+ printf("(null) 0x%08x\n", value.data);
+ }
} else if (value.dataType == Res_value::TYPE_REFERENCE) {
printf("(reference) 0x%08x\n", value.data);
} else if (value.dataType == Res_value::TYPE_DYNAMIC_REFERENCE) {