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

Commit de546a48 authored by Nader Jawad's avatar Nader Jawad
Browse files

Fixed issue where GradientDrawable would fail inflation

with invalid angle parameters

Previously, GradientDrawable would fail xml parsing if
an angle measurement was not a multiple of 45 and the type
of gradient is linear. Restore the original behavior to only
verify the angle measurement only if the type is linear
instead of verifying this requirement for all gradient types.

Removed restriction that radii must be non-negative as
subsequent logic in GradientDrawable already clamps the radius
to valid parameters.

Bug: 130309904
Test: Updated tests in CtsGradientDrawableTest
Change-Id: Ib1b3a0bb80639ddc00be7e630c62e781dfa6d9cf
parent ae05e55d
Loading
Loading
Loading
Loading
+77 −44
Original line number Original line Diff line number Diff line
@@ -637,6 +637,7 @@ public class GradientDrawable extends Drawable {
     * @see #setOrientation(Orientation)
     * @see #setOrientation(Orientation)
     */
     */
    public Orientation getOrientation() {
    public Orientation getOrientation() {
        updateGradientStateOrientation();
        return mGradientState.mOrientation;
        return mGradientState.mOrientation;
    }
    }


@@ -653,6 +654,9 @@ public class GradientDrawable extends Drawable {
     * @see #getOrientation()
     * @see #getOrientation()
     */
     */
    public void setOrientation(Orientation orientation) {
    public void setOrientation(Orientation orientation) {
        // Update the angle here so that subsequent attempts to obtain the orientation
        // from the angle overwrite previously configured values during inflation
        mGradientState.mAngle = getAngleFromOrientation(orientation);
        mGradientState.mOrientation = orientation;
        mGradientState.mOrientation = orientation;
        mGradientIsDirty = true;
        mGradientIsDirty = true;
        invalidateSelf();
        invalidateSelf();
@@ -1241,6 +1245,76 @@ public class GradientDrawable extends Drawable {
        return true;
        return true;
    }
    }


    /**
     * Update the orientation of the gradient based on the given angle only if the type is
     * {@link #LINEAR_GRADIENT}
     */
    private void updateGradientStateOrientation() {
        if (mGradientState.mGradient == LINEAR_GRADIENT) {
            int angle = mGradientState.mAngle;
            if (angle % 45 != 0) {
                throw new IllegalArgumentException("Linear gradient requires 'angle' attribute to "
                     + "be a multiple of 45");
            }

            Orientation orientation;
            switch (angle) {
                case 0:
                    orientation = Orientation.LEFT_RIGHT;
                    break;
                case 45:
                    orientation = Orientation.BL_TR;
                    break;
                case 90:
                    orientation = Orientation.BOTTOM_TOP;
                    break;
                case 135:
                    orientation = Orientation.BR_TL;
                    break;
                case 180:
                    orientation = Orientation.RIGHT_LEFT;
                    break;
                case 225:
                    orientation = Orientation.TR_BL;
                    break;
                case 270:
                    orientation = Orientation.TOP_BOTTOM;
                    break;
                case 315:
                    orientation = Orientation.TL_BR;
                    break;
                default:
                    // Should not get here as exception is thrown above if angle is not multiple
                    // of 45 degrees
                    orientation = Orientation.LEFT_RIGHT;
                    break;
            }
            mGradientState.mOrientation = orientation;
        }
    }

    private int getAngleFromOrientation(Orientation orientation) {
        switch (orientation) {
            default:
            case LEFT_RIGHT:
                return 0;
            case BL_TR:
                return 45;
            case BOTTOM_TOP:
                return 90;
            case BR_TL:
                return 135;
            case RIGHT_LEFT:
                return 180;
            case TR_BL:
                return 225;
            case TOP_BOTTOM:
                return 270;
            case TL_BR:
                return 315;
        }
    }

    /**
    /**
     * This checks mGradientIsDirty, and if it is true, recomputes both our drawing
     * This checks mGradientIsDirty, and if it is true, recomputes both our drawing
     * rectangle (mRect) and the gradient itself, since it depends on our
     * rectangle (mRect) and the gradient itself, since it depends on our
@@ -1270,6 +1344,7 @@ public class GradientDrawable extends Drawable {


                if (st.mGradient == LINEAR_GRADIENT) {
                if (st.mGradient == LINEAR_GRADIENT) {
                    final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
                    final float level = st.mUseLevel ? getLevel() / 10000.0f : 1.0f;
                    updateGradientStateOrientation();
                    switch (st.mOrientation) {
                    switch (st.mOrientation) {
                    case TOP_BOTTOM:
                    case TOP_BOTTOM:
                        x0 = r.left;            y0 = r.top;
                        x0 = r.left;            y0 = r.top;
@@ -1312,10 +1387,6 @@ public class GradientDrawable extends Drawable {
                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;
                    y0 = r.top + (r.bottom - r.top) * st.mCenterY;


                    float radius = st.mGradientRadius;
                    float radius = st.mGradientRadius;
                    if (Float.compare(radius, 0.0f) == -1 || Float.isNaN(radius)) {
                        throw new IllegalArgumentException("Gradient radius must be a valid "
                                + "number greater than or equal to 0");
                    }
                    if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) {
                    if (st.mGradientRadiusType == RADIUS_TYPE_FRACTION) {
                        // Fall back to parent width or height if intrinsic
                        // Fall back to parent width or height if intrinsic
                        // size is not specified.
                        // size is not specified.
@@ -1511,8 +1582,6 @@ public class GradientDrawable extends Drawable {
                    st.mAttrGradient, R.styleable.GradientDrawableGradient);
                    st.mAttrGradient, R.styleable.GradientDrawableGradient);
            try {
            try {
                updateGradientDrawableGradient(t.getResources(), a);
                updateGradientDrawableGradient(t.getResources(), a);
            } catch (XmlPullParserException e) {
                rethrowAsRuntimeException(e);
            } finally {
            } finally {
                a.recycle();
                a.recycle();
            }
            }
@@ -1700,8 +1769,7 @@ public class GradientDrawable extends Drawable {
        }
        }
    }
    }


    private void updateGradientDrawableGradient(Resources r, TypedArray a)
    private void updateGradientDrawableGradient(Resources r, TypedArray a) {
            throws XmlPullParserException {
        final GradientState st = mGradientState;
        final GradientState st = mGradientState;


        // Account for any configuration changes.
        // Account for any configuration changes.
@@ -1764,42 +1832,7 @@ public class GradientDrawable extends Drawable {
        }
        }


        int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle);
        int angle = (int) a.getFloat(R.styleable.GradientDrawableGradient_angle, st.mAngle);
        angle %= 360;
        st.mAngle = angle % 360;

        if (angle % 45 != 0) {
            throw new XmlPullParserException(a.getPositionDescription()
                    + "<gradient> tag requires 'angle' attribute to "
                    + "be a multiple of 45");
        }

        st.mAngle = angle;

        switch (angle) {
            case 0:
                st.mOrientation = Orientation.LEFT_RIGHT;
                break;
            case 45:
                st.mOrientation = Orientation.BL_TR;
                break;
            case 90:
                st.mOrientation = Orientation.BOTTOM_TOP;
                break;
            case 135:
                st.mOrientation = Orientation.BR_TL;
                break;
            case 180:
                st.mOrientation = Orientation.RIGHT_LEFT;
                break;
            case 225:
                st.mOrientation = Orientation.TR_BL;
                break;
            case 270:
                st.mOrientation = Orientation.TOP_BOTTOM;
                break;
            case 315:
                st.mOrientation = Orientation.TL_BR;
                break;
        }


        final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
        final TypedValue tv = a.peekValue(R.styleable.GradientDrawableGradient_gradientRadius);
        if (tv != null) {
        if (tv != null) {