Merge "Enforce restrictions on recycled TypedArrays"

This commit is contained in:
Alan Viverette
2014-03-27 22:40:06 +00:00
committed by Android (Google) Code Review
2 changed files with 214 additions and 105 deletions

View File

@@ -1010,13 +1010,14 @@ public class PackageParser {
pkg.mSharedUserLabel = sa.getResourceId( pkg.mSharedUserLabel = sa.getResourceId(
com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0); com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
} }
sa.recycle();
pkg.installLocation = sa.getInteger( pkg.installLocation = sa.getInteger(
com.android.internal.R.styleable.AndroidManifest_installLocation, com.android.internal.R.styleable.AndroidManifest_installLocation,
PARSE_DEFAULT_INSTALL_LOCATION); PARSE_DEFAULT_INSTALL_LOCATION);
pkg.applicationInfo.installLocation = pkg.installLocation; pkg.applicationInfo.installLocation = pkg.installLocation;
sa.recycle();
/* Set the global "forward lock" flag */ /* Set the global "forward lock" flag */
if ((flags & PARSE_FORWARD_LOCK) != 0) { if ((flags & PARSE_FORWARD_LOCK) != 0) {
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK; pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;

View File

@@ -46,6 +46,7 @@ public class TypedArray {
attrs.mResources = res; attrs.mResources = res;
attrs.mMetrics = res.getDisplayMetrics(); attrs.mMetrics = res.getDisplayMetrics();
attrs.mAssets = res.getAssets(); attrs.mAssets = res.getAssets();
attrs.mRecycled = false;
final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES; final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
if (attrs.mData.length >= fullLen) { if (attrs.mData.length >= fullLen) {
@@ -65,6 +66,8 @@ public class TypedArray {
private Resources mResources; private Resources mResources;
private DisplayMetrics mMetrics; private DisplayMetrics mMetrics;
private AssetManager mAssets; private AssetManager mAssets;
private boolean mRecycled;
/*package*/ XmlBlock.Parser mXml; /*package*/ XmlBlock.Parser mXml;
/*package*/ Resources.Theme mTheme; /*package*/ Resources.Theme mTheme;
/*package*/ int[] mData; /*package*/ int[] mData;
@@ -76,6 +79,10 @@ public class TypedArray {
* Return the number of values in this array. * Return the number of values in this array.
*/ */
public int length() { public int length() {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
return mLength; return mLength;
} }
@@ -83,6 +90,10 @@ public class TypedArray {
* Return the number of indices in the array that actually have data. * Return the number of indices in the array that actually have data.
*/ */
public int getIndexCount() { public int getIndexCount() {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
return mIndices[0]; return mIndices[0];
} }
@@ -96,6 +107,10 @@ public class TypedArray {
* {@link #getValue} and related APIs. * {@link #getValue} and related APIs.
*/ */
public int getIndex(int at) { public int getIndex(int at) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
return mIndices[1+at]; return mIndices[1+at];
} }
@@ -103,6 +118,10 @@ public class TypedArray {
* Return the Resources object this array was loaded from. * Return the Resources object this array was loaded from.
*/ */
public Resources getResources() { public Resources getResources() {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
return mResources; return mResources;
} }
@@ -115,6 +134,10 @@ public class TypedArray {
* null if the attribute is not defined. * null if the attribute is not defined.
*/ */
public CharSequence getText(int index) { public CharSequence getText(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -143,6 +166,10 @@ public class TypedArray {
* removed. Returns null if the attribute is not defined. * removed. Returns null if the attribute is not defined.
*/ */
public String getString(int index) { public String getString(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -178,6 +205,10 @@ public class TypedArray {
* an immediate string value. * an immediate string value.
*/ */
public String getNonResourceString(int index) { public String getNonResourceString(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -204,6 +235,10 @@ public class TypedArray {
* removed. Returns null if the attribute is not defined. * removed. Returns null if the attribute is not defined.
*/ */
public String getNonConfigurationString(int index, int allowedChangingConfigs) { public String getNonConfigurationString(int index, int allowedChangingConfigs) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -236,6 +271,10 @@ public class TypedArray {
* @return Attribute boolean value, or defValue if not defined. * @return Attribute boolean value, or defValue if not defined.
*/ */
public boolean getBoolean(int index, boolean defValue) { public boolean getBoolean(int index, boolean defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -266,6 +305,10 @@ public class TypedArray {
* @return Attribute int value, or defValue if not defined. * @return Attribute int value, or defValue if not defined.
*/ */
public int getInt(int index, int defValue) { public int getInt(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -295,6 +338,10 @@ public class TypedArray {
* @return Attribute float value, or defValue if not defined.. * @return Attribute float value, or defValue if not defined..
*/ */
public float getFloat(int index, float defValue) { public float getFloat(int index, float defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -333,6 +380,10 @@ public class TypedArray {
* @return Attribute color value, or defValue if not defined. * @return Attribute color value, or defValue if not defined.
*/ */
public int getColor(int index, int defValue) { public int getColor(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -365,6 +416,10 @@ public class TypedArray {
* @return ColorStateList for the attribute, or null if not defined. * @return ColorStateList for the attribute, or null if not defined.
*/ */
public ColorStateList getColorStateList(int index) { public ColorStateList getColorStateList(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
final TypedValue value = mValue; final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return mResources.loadColorStateList(value, value.resourceId); return mResources.loadColorStateList(value, value.resourceId);
@@ -382,6 +437,10 @@ public class TypedArray {
* @return Attribute integer value, or defValue if not defined. * @return Attribute integer value, or defValue if not defined.
*/ */
public int getInteger(int index, int defValue) { public int getInteger(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -413,6 +472,10 @@ public class TypedArray {
* @see #getDimensionPixelSize * @see #getDimensionPixelSize
*/ */
public float getDimension(int index, float defValue) { public float getDimension(int index, float defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -445,6 +508,10 @@ public class TypedArray {
* @see #getDimensionPixelSize * @see #getDimensionPixelSize
*/ */
public int getDimensionPixelOffset(int index, int defValue) { public int getDimensionPixelOffset(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -478,6 +545,10 @@ public class TypedArray {
* @see #getDimensionPixelOffset * @see #getDimensionPixelOffset
*/ */
public int getDimensionPixelSize(int index, int defValue) { public int getDimensionPixelSize(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -505,6 +576,10 @@ public class TypedArray {
* metric and truncated to integer pixels. * metric and truncated to integer pixels.
*/ */
public int getLayoutDimension(int index, String name) { public int getLayoutDimension(int index, String name) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -534,6 +609,10 @@ public class TypedArray {
* metric and truncated to integer pixels. * metric and truncated to integer pixels.
*/ */
public int getLayoutDimension(int index, int defValue) { public int getLayoutDimension(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -564,6 +643,10 @@ public class TypedArray {
* base value, or defValue if not defined. * base value, or defValue if not defined.
*/ */
public float getFraction(int index, int base, int pbase, float defValue) { public float getFraction(int index, int base, int pbase, float defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -593,6 +676,10 @@ public class TypedArray {
* @return Attribute resource identifier, or defValue if not defined. * @return Attribute resource identifier, or defValue if not defined.
*/ */
public int getResourceId(int index, int defValue) { public int getResourceId(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) { if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
@@ -615,6 +702,10 @@ public class TypedArray {
* @hide * @hide
*/ */
public int getThemeAttributeId(int index, int defValue) { public int getThemeAttributeId(int index, int defValue) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) { if (data[index + AssetManager.STYLE_TYPE] == TypedValue.TYPE_ATTRIBUTE) {
@@ -634,6 +725,10 @@ public class TypedArray {
* @return Drawable for the attribute, or null if not defined. * @return Drawable for the attribute, or null if not defined.
*/ */
public Drawable getDrawable(int index) { public Drawable getDrawable(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
final TypedValue value = mValue; final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (false) { if (false) {
@@ -661,6 +756,10 @@ public class TypedArray {
* @return CharSequence[] for the attribute, or null if not defined. * @return CharSequence[] for the attribute, or null if not defined.
*/ */
public CharSequence[] getTextArray(int index) { public CharSequence[] getTextArray(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
final TypedValue value = mValue; final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
if (false) { if (false) {
@@ -687,28 +786,11 @@ public class TypedArray {
* @return Returns true if the value was retrieved, else false. * @return Returns true if the value was retrieved, else false.
*/ */
public boolean getValue(int index, TypedValue outValue) { public boolean getValue(int index, TypedValue outValue) {
return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue); if (mRecycled) {
} throw new RuntimeException("Cannot make calls to a recycled instance!");
/**
* Determines whether this TypedArray contains an attribute of the specified
* type.
*
* @param type Type of data, e.g. {@link TypedValue#TYPE_ATTRIBUTE}
* @return True if the TypedArray contains an attribute of the specified
* type.
* @hide
*/
public boolean hasType(int type) {
final int[] data = mData;
final int N = getIndexCount();
for (int i = 0; i < N; i++) {
final int index = getIndex(i) * AssetManager.STYLE_NUM_ENTRIES;
if (data[index + AssetManager.STYLE_TYPE] == type) {
return true;
}
} }
return false;
return getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, outValue);
} }
/** /**
@@ -718,6 +800,10 @@ public class TypedArray {
* @return Attribute type. * @return Attribute type.
*/ */
public int getType(int index) { public int getType(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
return mData[index + AssetManager.STYLE_TYPE]; return mData[index + AssetManager.STYLE_TYPE];
} }
@@ -730,6 +816,10 @@ public class TypedArray {
* @return True if the attribute has a value, false otherwise. * @return True if the attribute has a value, false otherwise.
*/ */
public boolean hasValue(int index) { public boolean hasValue(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
index *= AssetManager.STYLE_NUM_ENTRIES; index *= AssetManager.STYLE_NUM_ENTRIES;
final int[] data = mData; final int[] data = mData;
final int type = data[index+AssetManager.STYLE_TYPE]; final int type = data[index+AssetManager.STYLE_TYPE];
@@ -748,6 +838,10 @@ public class TypedArray {
* receive a TypedValue whose type is TYPE_NULL.) * receive a TypedValue whose type is TYPE_NULL.)
*/ */
public TypedValue peekValue(int index) { public TypedValue peekValue(int index) {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
final TypedValue value = mValue; final TypedValue value = mValue;
if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) { if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
return value; return value;
@@ -759,13 +853,23 @@ public class TypedArray {
* Returns a message about the parser state suitable for printing error messages. * Returns a message about the parser state suitable for printing error messages.
*/ */
public String getPositionDescription() { public String getPositionDescription() {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
return mXml != null ? mXml.getPositionDescription() : "<internal>"; return mXml != null ? mXml.getPositionDescription() : "<internal>";
} }
/** /**
* Give back a previously retrieved array, for later re-use. * Recycle the TypedArray, to be re-used by a later caller. After calling
* this function you must not ever touch the typed array again.
*/ */
public void recycle() { public void recycle() {
if (mRecycled) {
throw new RuntimeException(toString() + " recycled twice!");
}
mRecycled = true;
mResources = null; mResources = null;
mMetrics = null; mMetrics = null;
mAssets = null; mAssets = null;
@@ -791,6 +895,10 @@ public class TypedArray {
* @hide * @hide
*/ */
public int[] extractThemeAttrs() { public int[] extractThemeAttrs() {
if (mRecycled) {
throw new RuntimeException("Cannot make calls to a recycled instance!");
}
int[] attrs = null; int[] attrs = null;
final int N = length(); final int N = length();