Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd274a0d authored by Alan Viverette's avatar Alan Viverette
Browse files

Enforce restrictions on recycled TypedArrays

No calls may be made to recycled TypedArrays, and we'll throw a
detailed exception if developers attempt to do so. Also fixes the
place where we were doin' it wrong.

BUG: 13673783
Change-Id: Ia7a382d90fce8aef7741d926028b2d01b57435ae
parent 9ad8a533
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -1010,13 +1010,14 @@ public class PackageParser {
            pkg.mSharedUserLabel = sa.getResourceId(
                    com.android.internal.R.styleable.AndroidManifest_sharedUserLabel, 0);
        }
        sa.recycle();

        pkg.installLocation = sa.getInteger(
                com.android.internal.R.styleable.AndroidManifest_installLocation,
                PARSE_DEFAULT_INSTALL_LOCATION);
        pkg.applicationInfo.installLocation = pkg.installLocation;

        sa.recycle();

        /* Set the global "forward lock" flag */
        if ((flags & PARSE_FORWARD_LOCK) != 0) {
            pkg.applicationInfo.flags |= ApplicationInfo.FLAG_FORWARD_LOCK;
+212 −104
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@ public class TypedArray {
            attrs.mResources = res;
            attrs.mMetrics = res.getDisplayMetrics();
            attrs.mAssets = res.getAssets();
            attrs.mRecycled = false;

            final int fullLen = len * AssetManager.STYLE_NUM_ENTRIES;
            if (attrs.mData.length >= fullLen) {
@@ -65,6 +66,8 @@ public class TypedArray {
    private Resources mResources;
    private DisplayMetrics mMetrics;
    private AssetManager mAssets;
    private boolean mRecycled;

    /*package*/ XmlBlock.Parser mXml;
    /*package*/ Resources.Theme mTheme;
    /*package*/ int[] mData;
@@ -76,6 +79,10 @@ public class TypedArray {
     * Return the number of values in this array.
     */
    public int length() {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        return mLength;
    }

@@ -83,6 +90,10 @@ public class TypedArray {
     * Return the number of indices in the array that actually have data.
     */
    public int getIndexCount() {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        return mIndices[0];
    }

@@ -96,6 +107,10 @@ public class TypedArray {
     * {@link #getValue} and related APIs.
     */
    public int getIndex(int at) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        return mIndices[1+at];
    }

@@ -103,6 +118,10 @@ public class TypedArray {
     * Return the Resources object this array was loaded from.
     */
    public Resources getResources() {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        return mResources;
    }

@@ -115,6 +134,10 @@ public class TypedArray {
     *         null if the attribute is not defined.
     */
    public CharSequence getText(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];
@@ -143,6 +166,10 @@ public class TypedArray {
     * removed.  Returns null if the attribute is not defined.
     */
    public String getString(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];
@@ -178,6 +205,10 @@ public class TypedArray {
     * an immediate string value.
     */
    public String getNonResourceString(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];
@@ -204,6 +235,10 @@ public class TypedArray {
     * removed.  Returns null if the attribute is not defined.
     */
    public String getNonConfigurationString(int index, int allowedChangingConfigs) {
        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];
@@ -236,6 +271,10 @@ public class TypedArray {
     * @return Attribute boolean value, or defValue if not defined.
     */
    public boolean getBoolean(int index, boolean defValue) {
        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];
@@ -266,6 +305,10 @@ public class TypedArray {
     * @return Attribute int value, or defValue if not defined.
     */
    public int getInt(int index, int defValue) {
        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];
@@ -295,6 +338,10 @@ public class TypedArray {
     * @return Attribute float value, or defValue if not defined..
     */
    public float getFloat(int index, float defValue) {
        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];
@@ -333,6 +380,10 @@ public class TypedArray {
     * @return Attribute color value, or defValue if not defined.
     */
    public int getColor(int index, int defValue) {
        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];
@@ -365,6 +416,10 @@ public class TypedArray {
     * @return ColorStateList for the attribute, or null if not defined.
     */
    public ColorStateList getColorStateList(int index) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        final TypedValue value = mValue;
        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
            return mResources.loadColorStateList(value, value.resourceId);
@@ -382,6 +437,10 @@ public class TypedArray {
     * @return Attribute integer value, or defValue if not defined.
     */
    public int getInteger(int index, int defValue) {
        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];
@@ -413,6 +472,10 @@ public class TypedArray {
     * @see #getDimensionPixelSize
     */
    public float getDimension(int index, float defValue) {
        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];
@@ -445,6 +508,10 @@ public class TypedArray {
     * @see #getDimensionPixelSize
     */
    public int getDimensionPixelOffset(int index, int defValue) {
        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];
@@ -478,6 +545,10 @@ public class TypedArray {
     * @see #getDimensionPixelOffset
     */
    public int getDimensionPixelSize(int index, int defValue) {
        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];
@@ -505,6 +576,10 @@ public class TypedArray {
     * metric and truncated to integer pixels.
     */
    public int getLayoutDimension(int index, String name) {
        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];
@@ -534,6 +609,10 @@ public class TypedArray {
     * metric and truncated to integer pixels.
     */
    public int getLayoutDimension(int index, int defValue) {
        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];
@@ -564,6 +643,10 @@ public class TypedArray {
     * base value, or defValue if not defined.
     */
    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;
        final int[] data = mData;
        final int type = data[index+AssetManager.STYLE_TYPE];
@@ -593,6 +676,10 @@ public class TypedArray {
     * @return Attribute resource identifier, or defValue if not defined.
     */
    public int getResourceId(int index, int defValue) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        index *= AssetManager.STYLE_NUM_ENTRIES;
        final int[] data = mData;
        if (data[index+AssetManager.STYLE_TYPE] != TypedValue.TYPE_NULL) {
@@ -615,6 +702,10 @@ public class TypedArray {
     * @hide
     */
    public int getThemeAttributeId(int index, int defValue) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        index *= AssetManager.STYLE_NUM_ENTRIES;
        final int[] data = mData;
        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.
     */
    public Drawable getDrawable(int index) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        final TypedValue value = mValue;
        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
            if (false) {
@@ -661,6 +756,10 @@ public class TypedArray {
     * @return CharSequence[] for the attribute, or null if not defined.
     */
    public CharSequence[] getTextArray(int index) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        final TypedValue value = mValue;
        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
            if (false) {
@@ -687,28 +786,11 @@ public class TypedArray {
     * @return Returns true if the value was retrieved, else false.
     */
    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.
     */
    public int getType(int index) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        index *= AssetManager.STYLE_NUM_ENTRIES;
        return mData[index + AssetManager.STYLE_TYPE];
    }
@@ -730,6 +816,10 @@ public class TypedArray {
     * @return True if the attribute has a value, false otherwise.
     */
    public boolean hasValue(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];
@@ -748,6 +838,10 @@ public class TypedArray {
     *         receive a TypedValue whose type is TYPE_NULL.)
     */
    public TypedValue peekValue(int index) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        final TypedValue value = mValue;
        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
            return value;
@@ -759,13 +853,23 @@ public class TypedArray {
     * Returns a message about the parser state suitable for printing error messages.
     */
    public String getPositionDescription() {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        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() {
        if (mRecycled) {
            throw new RuntimeException(toString() + " recycled twice!");
        }

        mRecycled = true;
        mResources = null;
        mMetrics = null;
        mAssets = null;
@@ -791,6 +895,10 @@ public class TypedArray {
     * @hide
     */
    public int[] extractThemeAttrs() {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        int[] attrs = null;

        final int N = length();