am 07a08010: am 425b1dc8: Merge "Add theme and config change support to more Drawable types" into lmp-mr1-dev

* commit '07a08010a87daec2091b643a8fcf2f7a27588098':
  Add theme and config change support to more Drawable types
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index c2e93a7..d2799e1 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -16,6 +16,8 @@
 
 package android.graphics.drawable;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.ColorFilter;
@@ -41,6 +43,7 @@
  */
 public class AnimatedRotateDrawable extends Drawable implements Drawable.Callback, Runnable,
         Animatable {
+    private static final String TAG = "AnimatedRotateDrawable";
 
     private AnimatedRotateState mState;
     private boolean mMutated;
@@ -186,6 +189,11 @@
     }
 
     @Override
+    public boolean canApplyTheme() {
+        return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
+    }
+
+    @Override
     public void invalidateDrawable(Drawable who) {
         final Callback callback = getCallback();
         if (callback != null) {
@@ -254,67 +262,21 @@
     }
 
     @Override
-    public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
+    public void inflate(@NonNull Resources r, @NonNull XmlPullParser parser,
+            @NonNull AttributeSet attrs, @Nullable Theme theme)
             throws XmlPullParserException, IOException {
-
         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimatedRotateDrawable);
-
         super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedRotateDrawable_visible);
-
-        TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
-        final boolean pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
-        final float pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
-
-        tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
-        final boolean pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
-        final float pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
-
-        setFramesCount(a.getInt(R.styleable.AnimatedRotateDrawable_framesCount, 12));
-        setFramesDuration(a.getInt(R.styleable.AnimatedRotateDrawable_frameDuration, 150));
-
-        final int res = a.getResourceId(R.styleable.AnimatedRotateDrawable_drawable, 0);
-        Drawable drawable = null;
-        if (res > 0) {
-            drawable = r.getDrawable(res, theme);
-        }
-
+        updateStateFromTypedArray(a);
         a.recycle();
 
-        int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
-               (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-
-            if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
-                Log.w("drawable", "Bad element under <animated-rotate>: "
-                        + parser .getName());
-            }
-        }
-
-        if (drawable == null) {
-            Log.w("drawable", "No drawable specified for <animated-rotate>");
-        }
-
-        final AnimatedRotateState rotateState = mState;
-        rotateState.mDrawable = drawable;
-        rotateState.mPivotXRel = pivotXRel;
-        rotateState.mPivotX = pivotX;
-        rotateState.mPivotYRel = pivotYRel;
-        rotateState.mPivotY = pivotY;
+        inflateChildElements(r, parser, attrs, theme);
 
         init();
-
-        if (drawable != null) {
-            drawable.setCallback(this);
-        }
     }
 
     @Override
-    public void applyTheme(Theme t) {
+    public void applyTheme(@Nullable Theme t) {
         super.applyTheme(t);
 
         final AnimatedRotateState state = mState;
@@ -322,15 +284,91 @@
             return;
         }
 
-        if (state.mDrawable != null) {
+        if (state.mThemeAttrs != null) {
+            final TypedArray a = t.resolveAttributes(
+                    state.mThemeAttrs, R.styleable.AnimatedRotateDrawable);
+            try {
+                updateStateFromTypedArray(a);
+                verifyRequiredAttributes(a);
+            } catch (XmlPullParserException e) {
+                throw new RuntimeException(e);
+            } finally {
+                a.recycle();
+            }
+        }
+
+        if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
             state.mDrawable.applyTheme(t);
         }
+
+        init();
+    }
+
+    private void updateStateFromTypedArray(TypedArray a) {
+        final AnimatedRotateState state = mState;
+
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mThemeAttrs = a.extractThemeAttrs();
+
+        if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotX)) {
+            final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotX);
+            state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION;
+            state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+        }
+
+        if (a.hasValue(R.styleable.AnimatedRotateDrawable_pivotY)) {
+            final TypedValue tv = a.peekValue(R.styleable.AnimatedRotateDrawable_pivotY);
+            state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION;
+            state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+        }
+
+        setFramesCount(a.getInt(
+                R.styleable.AnimatedRotateDrawable_framesCount, state.mFramesCount));
+        setFramesDuration(a.getInt(
+                R.styleable.AnimatedRotateDrawable_frameDuration, state.mFrameDuration));
+
+        final Drawable dr = a.getDrawable(R.styleable.AnimatedRotateDrawable_drawable);
+        if (dr != null) {
+            state.mDrawable = dr;
+            dr.setCallback(this);
+        }
     }
 
-    @Override
-    public boolean canApplyTheme() {
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
         final AnimatedRotateState state = mState;
-        return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+
+        Drawable dr = null;
+        int outerDepth = parser.getDepth();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+
+            if ((dr = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
+                Log.w(TAG, "Bad element under <animated-rotate>: " + parser.getName());
+            }
+        }
+
+        if (dr != null) {
+            state.mDrawable = dr;
+            dr.setCallback(this);
+        }
+    }
+
+    private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+        // If we're not waiting on a theme, verify required attributes.
+        if (mState.mDrawable == null && (mState.mThemeAttrs == null
+                || mState.mThemeAttrs[R.styleable.AnimatedRotateDrawable_drawable] == 0)) {
+            throw new XmlPullParserException(a.getPositionDescription()
+                    + ": <animated-rotate> tag requires a 'drawable' attribute or "
+                    + "child tag defining a drawable");
+        }
     }
 
     public void setFramesCount(int framesCount) {
@@ -362,15 +400,16 @@
 
     final static class AnimatedRotateState extends Drawable.ConstantState {
         Drawable mDrawable;
+        int[] mThemeAttrs;
 
         int mChangingConfigurations;
 
-        boolean mPivotXRel;
-        float mPivotX;
-        boolean mPivotYRel;
-        float mPivotY;
-        int mFrameDuration;
-        int mFramesCount;
+        boolean mPivotXRel = false;
+        float mPivotX = 0;
+        boolean mPivotYRel = false;
+        float mPivotY = 0;
+        int mFrameDuration = 150;
+        int mFramesCount = 12;
 
         private boolean mCanConstantState;
         private boolean mCheckedConstantState;
@@ -387,6 +426,7 @@
                 mDrawable.setLayoutDirection(orig.mDrawable.getLayoutDirection());
                 mDrawable.setBounds(orig.mDrawable.getBounds());
                 mDrawable.setLevel(orig.mDrawable.getLevel());
+                mThemeAttrs = orig.mThemeAttrs;
                 mPivotXRel = orig.mPivotXRel;
                 mPivotX = orig.mPivotX;
                 mPivotYRel = orig.mPivotYRel;
@@ -408,6 +448,12 @@
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+                    || super.canApplyTheme();
+        }
+
+        @Override
         public int getChangingConfigurations() {
             return mChangingConfigurations;
         }
diff --git a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
index 849faec..3b125fd 100644
--- a/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedStateListDrawable.java
@@ -347,24 +347,62 @@
             throws XmlPullParserException, IOException {
         final TypedArray a = obtainAttributes(
                 r, theme, attrs, R.styleable.AnimatedStateListDrawable);
-
         super.inflateWithAttributes(r, parser, a, R.styleable.AnimatedStateListDrawable_visible);
-
-        final StateListState stateListState = getStateListState();
-        stateListState.setVariablePadding(a.getBoolean(
-                R.styleable.AnimatedStateListDrawable_variablePadding, false));
-        stateListState.setConstantSize(a.getBoolean(
-                R.styleable.AnimatedStateListDrawable_constantSize, false));
-        stateListState.setEnterFadeDuration(a.getInt(
-                R.styleable.AnimatedStateListDrawable_enterFadeDuration, 0));
-        stateListState.setExitFadeDuration(a.getInt(
-                R.styleable.AnimatedStateListDrawable_exitFadeDuration, 0));
-
-        setDither(a.getBoolean(R.styleable.AnimatedStateListDrawable_dither, true));
-        setAutoMirrored(a.getBoolean(R.styleable.AnimatedStateListDrawable_autoMirrored, false));
-
+        updateStateFromTypedArray(a);
         a.recycle();
 
+        inflateChildElements(r, parser, attrs, theme);
+
+        init();
+    }
+
+    @Override
+    public void applyTheme(@Nullable Theme theme) {
+        super.applyTheme(theme);
+
+        final AnimatedStateListState state = mState;
+        if (state == null || !state.canApplyTheme()) {
+            return;
+        }
+
+        final TypedArray a = theme.resolveAttributes(
+                state.mAnimThemeAttrs, R.styleable.AnimatedRotateDrawable);
+        updateStateFromTypedArray(a);
+        a.recycle();
+
+        init();
+    }
+
+    private void updateStateFromTypedArray(TypedArray a) {
+        final AnimatedStateListState state = mState;
+
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mAnimThemeAttrs = a.extractThemeAttrs();
+
+        state.setVariablePadding(a.getBoolean(
+                R.styleable.AnimatedStateListDrawable_variablePadding, state.mVariablePadding));
+        state.setConstantSize(a.getBoolean(
+                R.styleable.AnimatedStateListDrawable_constantSize, state.mConstantSize));
+        state.setEnterFadeDuration(a.getInt(
+                R.styleable.AnimatedStateListDrawable_enterFadeDuration, state.mEnterFadeDuration));
+        state.setExitFadeDuration(a.getInt(
+                R.styleable.AnimatedStateListDrawable_exitFadeDuration, state.mExitFadeDuration));
+
+        setDither(a.getBoolean(
+                R.styleable.AnimatedStateListDrawable_dither, state.mDither));
+        setAutoMirrored(a.getBoolean(
+                R.styleable.AnimatedStateListDrawable_autoMirrored, state.mAutoMirrored));
+    }
+
+    private void init() {
+        onStateChange(getState());
+    }
+
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
         int type;
 
         final int innerDepth = parser.getDepth() + 1;
@@ -386,8 +424,6 @@
                 parseTransition(r, parser, attrs, theme);
             }
         }
-
-        onStateChange(getState());
     }
 
     private int parseTransition(@NonNull Resources r, @NonNull XmlPullParser parser,
@@ -507,6 +543,8 @@
         private static final int REVERSE_SHIFT = 32;
         private static final int REVERSE_MASK = 0x1;
 
+        int[] mAnimThemeAttrs;
+
         final LongSparseLongArray mTransitions;
         final SparseIntArray mStateIds;
 
@@ -515,6 +553,7 @@
             super(orig, owner, res);
 
             if (orig != null) {
+                mAnimThemeAttrs = orig.mAnimThemeAttrs;
                 mTransitions = orig.mTransitions.clone();
                 mStateIds = orig.mStateIds.clone();
             } else {
@@ -566,6 +605,11 @@
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return mAnimThemeAttrs != null || super.canApplyTheme();
+        }
+
+        @Override
         public Drawable newDrawable() {
             return new AnimatedStateListDrawable(this, null);
         }
diff --git a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
index a904067..e65dbaf 100644
--- a/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedVectorDrawable.java
@@ -316,9 +316,8 @@
 
     @Override
     public boolean canApplyTheme() {
-        return super.canApplyTheme() || mAnimatedVectorState != null
-                && mAnimatedVectorState.mVectorDrawable != null
-                && mAnimatedVectorState.mVectorDrawable.canApplyTheme();
+        return (mAnimatedVectorState != null && mAnimatedVectorState.canApplyTheme())
+                || super.canApplyTheme();
     }
 
     @Override
@@ -374,6 +373,12 @@
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return (mVectorDrawable != null && mVectorDrawable.canApplyTheme())
+                    || super.canApplyTheme();
+        }
+
+        @Override
         public Drawable newDrawable() {
             return new AnimatedVectorDrawable(this, null);
         }
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index c730a20..a8b6c94 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -16,6 +16,8 @@
 
 package android.graphics.drawable;
 
+import com.android.internal.R;
+
 import java.io.IOException;
 
 import org.xmlpull.v1.XmlPullParser;
@@ -271,27 +273,25 @@
     @Override
     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
-
-        TypedArray a = obtainAttributes(r, theme, attrs,
-                com.android.internal.R.styleable.AnimationDrawable);
-
-        super.inflateWithAttributes(r, parser, a,
-                com.android.internal.R.styleable.AnimationDrawable_visible);
-
-        mAnimationState.setVariablePadding(a.getBoolean(
-                com.android.internal.R.styleable.AnimationDrawable_variablePadding, false));
-
-        mAnimationState.mOneShot = a.getBoolean(
-                com.android.internal.R.styleable.AnimationDrawable_oneshot, false);
-
+        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawable);
+        super.inflateWithAttributes(r, parser, a, R.styleable.AnimationDrawable_visible);
+        updateStateFromTypedArray(a);
         a.recycle();
 
+        inflateChildElements(r, parser, attrs, theme);
+
+        setFrame(0, true, false);
+    }
+
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        TypedArray a;
         int type;
 
         final int innerDepth = parser.getDepth()+1;
         int depth;
-        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT &&
-                ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
+        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
+                && ((depth = parser.getDepth()) >= innerDepth || type != XmlPullParser.END_TAG)) {
             if (type != XmlPullParser.START_TAG) {
                 continue;
             }
@@ -300,17 +300,15 @@
                 continue;
             }
 
-            a = obtainAttributes(
-                    r, theme, attrs, com.android.internal.R.styleable.AnimationDrawableItem);
-            int duration = a.getInt(
-                    com.android.internal.R.styleable.AnimationDrawableItem_duration, -1);
+            a = obtainAttributes(r, theme, attrs, R.styleable.AnimationDrawableItem);
+
+            final int duration = a.getInt(R.styleable.AnimationDrawableItem_duration, -1);
             if (duration < 0) {
-                throw new XmlPullParserException(
-                        parser.getPositionDescription()
+                throw new XmlPullParserException(parser.getPositionDescription()
                         + ": <item> tag requires a 'duration' attribute");
             }
-            int drawableRes = a.getResourceId(
-                    com.android.internal.R.styleable.AnimationDrawableItem_drawable, 0);
+
+            final int drawableRes = a.getResourceId(R.styleable.AnimationDrawableItem_drawable, 0);
 
             a.recycle();
 
@@ -322,9 +320,9 @@
                     // Empty
                 }
                 if (type != XmlPullParser.START_TAG) {
-                    throw new XmlPullParserException(parser.getPositionDescription() +
-                            ": <item> tag requires a 'drawable' attribute or child tag" +
-                            " defining a drawable");
+                    throw new XmlPullParserException(parser.getPositionDescription()
+                            + ": <item> tag requires a 'drawable' attribute or child tag"
+                            + " defining a drawable");
                 }
                 dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
             }
@@ -334,8 +332,14 @@
                 dr.setCallback(this);
             }
         }
+    }
 
-        setFrame(0, true, false);
+    private void updateStateFromTypedArray(TypedArray a) {
+        mAnimationState.mVariablePadding = a.getBoolean(
+                R.styleable.AnimationDrawable_variablePadding, mAnimationState.mVariablePadding);
+
+        mAnimationState.mOneShot = a.getBoolean(
+                R.styleable.AnimationDrawable_oneshot, mAnimationState.mOneShot);
     }
 
     @Override
@@ -357,7 +361,7 @@
 
     private final static class AnimationState extends DrawableContainerState {
         private int[] mDurations;
-        private boolean mOneShot;
+        private boolean mOneShot = false;
 
         AnimationState(AnimationState orig, AnimationDrawable owner,
                 Resources res) {
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 669cef2..f80a5f4 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -16,6 +16,8 @@
 
 package android.graphics.drawable;
 
+import com.android.internal.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -49,7 +51,7 @@
  * @attr ref android.R.styleable#ClipDrawable_drawable
  */
 public class ClipDrawable extends Drawable implements Drawable.Callback {
-    private ClipState mClipState;
+    private ClipState mState;
     private final Rect mTmpRect = new Rect();
 
     public static final int HORIZONTAL = 1;
@@ -67,9 +69,9 @@
     public ClipDrawable(Drawable drawable, int gravity, int orientation) {
         this(null, null);
 
-        mClipState.mDrawable = drawable;
-        mClipState.mGravity = gravity;
-        mClipState.mOrientation = orientation;
+        mState.mDrawable = drawable;
+        mState.mGravity = gravity;
+        mState.mOrientation = orientation;
 
         if (drawable != null) {
             drawable.setCallback(this);
@@ -81,19 +83,22 @@
             throws XmlPullParserException, IOException {
         super.inflate(r, parser, attrs, theme);
 
-        int type;
+        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ClipDrawable);
 
-        TypedArray a = obtainAttributes(
-                r, theme, attrs, com.android.internal.R.styleable.ClipDrawable);
+        // Reset mDrawable to preserve old multiple-inflate behavior. This is
+        // silly, but we have CTS tests that rely on it.
+        mState.mDrawable = null;
 
-        int orientation = a.getInt(
-                com.android.internal.R.styleable.ClipDrawable_clipOrientation,
-                HORIZONTAL);
-        int g = a.getInt(com.android.internal.R.styleable.ClipDrawable_gravity, Gravity.LEFT);
-        Drawable dr = a.getDrawable(com.android.internal.R.styleable.ClipDrawable_drawable);
-
+        updateStateFromTypedArray(a);
+        inflateChildElements(r, parser, attrs, theme);
+        verifyRequiredAttributes(a);
         a.recycle();
+    }
 
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        Drawable dr = null;
+        int type;
         final int outerDepth = parser.getDepth();
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -103,35 +108,68 @@
             dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
         }
 
-        if (dr == null) {
-            throw new IllegalArgumentException("No drawable specified for <clip>");
+        if (dr != null) {
+            mState.mDrawable = dr;
+            dr.setCallback(this);
         }
+    }
 
-        mClipState.mDrawable = dr;
-        mClipState.mOrientation = orientation;
-        mClipState.mGravity = g;
+    private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+        // If we're not waiting on a theme, verify required attributes.
+        if (mState.mDrawable == null && (mState.mThemeAttrs == null
+                || mState.mThemeAttrs[R.styleable.ClipDrawable_drawable] == 0)) {
+            throw new XmlPullParserException(a.getPositionDescription()
+                    + ": <clip> tag requires a 'drawable' attribute or "
+                    + "child tag defining a drawable");
+        }
+    }
 
-        dr.setCallback(this);
+    private void updateStateFromTypedArray(TypedArray a) {
+        final ClipState state = mState;
+
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mThemeAttrs = a.extractThemeAttrs();
+
+        state.mOrientation = a.getInt(R.styleable.ClipDrawable_clipOrientation, state.mOrientation);
+        state.mGravity = a.getInt(R.styleable.ClipDrawable_gravity, state.mGravity);
+
+        final Drawable dr = a.getDrawable(R.styleable.ClipDrawable_drawable);
+        if (dr != null) {
+            state.mDrawable = dr;
+            dr.setCallback(this);
+        }
     }
 
     @Override
     public void applyTheme(Theme t) {
         super.applyTheme(t);
 
-        final ClipState state = mClipState;
+        final ClipState state = mState;
         if (state == null) {
             return;
         }
 
-        if (state.mDrawable != null) {
+        final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ClipDrawable);
+        try {
+            updateStateFromTypedArray(a);
+            verifyRequiredAttributes(a);
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException(e);
+        } finally {
+            a.recycle();
+        }
+
+        if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
             state.mDrawable.applyTheme(t);
         }
     }
 
     @Override
     public boolean canApplyTheme() {
-        final ClipState state = mClipState;
-        return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+        return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
     }
 
     // overrides from Drawable.Callback
@@ -165,78 +203,78 @@
     @Override
     public int getChangingConfigurations() {
         return super.getChangingConfigurations()
-                | mClipState.mChangingConfigurations
-                | mClipState.mDrawable.getChangingConfigurations();
+                | mState.mChangingConfigurations
+                | mState.mDrawable.getChangingConfigurations();
     }
 
     @Override
     public boolean getPadding(Rect padding) {
         // XXX need to adjust padding!
-        return mClipState.mDrawable.getPadding(padding);
+        return mState.mDrawable.getPadding(padding);
     }
 
     @Override
     public boolean setVisible(boolean visible, boolean restart) {
-        mClipState.mDrawable.setVisible(visible, restart);
+        mState.mDrawable.setVisible(visible, restart);
         return super.setVisible(visible, restart);
     }
 
     @Override
     public void setAlpha(int alpha) {
-        mClipState.mDrawable.setAlpha(alpha);
+        mState.mDrawable.setAlpha(alpha);
     }
 
     @Override
     public int getAlpha() {
-        return mClipState.mDrawable.getAlpha();
+        return mState.mDrawable.getAlpha();
     }
 
     @Override
     public void setColorFilter(ColorFilter cf) {
-        mClipState.mDrawable.setColorFilter(cf);
+        mState.mDrawable.setColorFilter(cf);
     }
 
     @Override
     public void setTintList(ColorStateList tint) {
-        mClipState.mDrawable.setTintList(tint);
+        mState.mDrawable.setTintList(tint);
     }
 
     @Override
     public void setTintMode(Mode tintMode) {
-        mClipState.mDrawable.setTintMode(tintMode);
+        mState.mDrawable.setTintMode(tintMode);
     }
 
     @Override
     public int getOpacity() {
-        return mClipState.mDrawable.getOpacity();
+        return mState.mDrawable.getOpacity();
     }
 
     @Override
     public boolean isStateful() {
-        return mClipState.mDrawable.isStateful();
+        return mState.mDrawable.isStateful();
     }
 
     @Override
     protected boolean onStateChange(int[] state) {
-        return mClipState.mDrawable.setState(state);
+        return mState.mDrawable.setState(state);
     }
 
     @Override
     protected boolean onLevelChange(int level) {
-        mClipState.mDrawable.setLevel(level);
+        mState.mDrawable.setLevel(level);
         invalidateSelf();
         return true;
     }
 
     @Override
     protected void onBoundsChange(Rect bounds) {
-        mClipState.mDrawable.setBounds(bounds);
+        mState.mDrawable.setBounds(bounds);
     }
 
     @Override
     public void draw(Canvas canvas) {
 
-        if (mClipState.mDrawable.getLevel() == 0) {
+        if (mState.mDrawable.getLevel() == 0) {
             return;
         }
 
@@ -244,41 +282,41 @@
         final Rect bounds = getBounds();
         int level = getLevel();
         int w = bounds.width();
-        final int iw = 0; //mClipState.mDrawable.getIntrinsicWidth();
-        if ((mClipState.mOrientation & HORIZONTAL) != 0) {
+        final int iw = 0; //mState.mDrawable.getIntrinsicWidth();
+        if ((mState.mOrientation & HORIZONTAL) != 0) {
             w -= (w - iw) * (10000 - level) / 10000;
         }
         int h = bounds.height();
-        final int ih = 0; //mClipState.mDrawable.getIntrinsicHeight();
-        if ((mClipState.mOrientation & VERTICAL) != 0) {
+        final int ih = 0; //mState.mDrawable.getIntrinsicHeight();
+        if ((mState.mOrientation & VERTICAL) != 0) {
             h -= (h - ih) * (10000 - level) / 10000;
         }
         final int layoutDirection = getLayoutDirection();
-        Gravity.apply(mClipState.mGravity, w, h, bounds, r, layoutDirection);
+        Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
 
         if (w > 0 && h > 0) {
             canvas.save();
             canvas.clipRect(r);
-            mClipState.mDrawable.draw(canvas);
+            mState.mDrawable.draw(canvas);
             canvas.restore();
         }
     }
 
     @Override
     public int getIntrinsicWidth() {
-        return mClipState.mDrawable.getIntrinsicWidth();
+        return mState.mDrawable.getIntrinsicWidth();
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return mClipState.mDrawable.getIntrinsicHeight();
+        return mState.mDrawable.getIntrinsicHeight();
     }
 
     @Override
     public ConstantState getConstantState() {
-        if (mClipState.canConstantState()) {
-            mClipState.mChangingConfigurations = getChangingConfigurations();
-            return mClipState;
+        if (mState.canConstantState()) {
+            mState.mChangingConfigurations = getChangingConfigurations();
+            return mState;
         }
         return null;
     }
@@ -286,14 +324,14 @@
     /** @hide */
     @Override
     public void setLayoutDirection(int layoutDirection) {
-        mClipState.mDrawable.setLayoutDirection(layoutDirection);
+        mState.mDrawable.setLayoutDirection(layoutDirection);
         super.setLayoutDirection(layoutDirection);
     }
 
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            mClipState.mDrawable.mutate();
+            mState.mDrawable.mutate();
             mMutated = true;
         }
         return this;
@@ -304,21 +342,26 @@
      */
     public void clearMutated() {
         super.clearMutated();
-        mClipState.mDrawable.clearMutated();
+        mState.mDrawable.clearMutated();
         mMutated = false;
     }
 
     final static class ClipState extends ConstantState {
-        Drawable mDrawable;
+        int[] mThemeAttrs;
         int mChangingConfigurations;
-        int mOrientation;
-        int mGravity;
+
+        Drawable mDrawable;
+
+        int mOrientation = HORIZONTAL;
+        int mGravity = Gravity.LEFT;
 
         private boolean mCheckedConstantState;
         private boolean mCanConstantState;
 
         ClipState(ClipState orig, ClipDrawable owner, Resources res) {
             if (orig != null) {
+                mThemeAttrs = orig.mThemeAttrs;
+                mChangingConfigurations = orig.mChangingConfigurations;
                 if (res != null) {
                     mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
                 } else {
@@ -335,6 +378,12 @@
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+                    || super.canApplyTheme();
+        }
+
+        @Override
         public Drawable newDrawable() {
             return new ClipDrawable(this, null);
         }
@@ -360,7 +409,7 @@
     }
 
     private ClipDrawable(ClipState state, Resources res) {
-        mClipState = new ClipState(state, this, res);
+        mState = new ClipState(state, this, res);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index a903288..326490f 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -600,11 +600,11 @@
         Drawable[] mDrawables;
         int mNumChildren;
 
-        boolean mVariablePadding;
+        boolean mVariablePadding = false;
         boolean mPaddingChecked;
         Rect mConstantPadding;
 
-        boolean mConstantSize;
+        boolean mConstantSize = false;
         boolean mComputedConstantSize;
         int mConstantWidth;
         int mConstantHeight;
@@ -625,8 +625,8 @@
         boolean mMutated;
         int mLayoutDirection;
 
-        int mEnterFadeDuration;
-        int mExitFadeDuration;
+        int mEnterFadeDuration = 0;
+        int mExitFadeDuration = 0;
 
         boolean mAutoMirrored;
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index 2071cf7..30afe70 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -1089,7 +1089,7 @@
 
     @Override
     public boolean canApplyTheme() {
-        return super.canApplyTheme() || mGradientState != null && mGradientState.canApplyTheme();
+        return (mGradientState != null && mGradientState.canApplyTheme()) || super.canApplyTheme();
     }
 
     private void applyThemeChildElements(Theme t) {
@@ -1632,7 +1632,7 @@
         public boolean canApplyTheme() {
             return mThemeAttrs != null || mAttrSize != null || mAttrGradient != null
                     || mAttrSolid != null || mAttrStroke != null || mAttrCorners != null
-                    || mAttrPadding != null;
+                    || mAttrPadding != null || super.canApplyTheme();
         }
 
         @Override
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index f1800e5..b88d9e6 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -55,7 +55,8 @@
 public class InsetDrawable extends Drawable implements Drawable.Callback {
     private final Rect mTmpRect = new Rect();
 
-    private InsetState mInsetState;
+    private final InsetState mState;
+
     private boolean mMutated;
 
     /*package*/ InsetDrawable() {
@@ -70,11 +71,11 @@
                          int insetRight, int insetBottom) {
         this(null, null);
 
-        mInsetState.mDrawable = drawable;
-        mInsetState.mInsetLeft = insetLeft;
-        mInsetState.mInsetTop = insetTop;
-        mInsetState.mInsetRight = insetRight;
-        mInsetState.mInsetBottom = insetBottom;
+        mState.mDrawable = drawable;
+        mState.mInsetLeft = insetLeft;
+        mState.mInsetTop = insetTop;
+        mState.mInsetRight = insetRight;
+        mState.mInsetBottom = insetBottom;
 
         if (drawable != null) {
             drawable.setCallback(this);
@@ -87,11 +88,20 @@
         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.InsetDrawable);
         super.inflateWithAttributes(r, parser, a, R.styleable.InsetDrawable_visible);
 
-        mInsetState.mDrawable = null;
-        updateStateFromTypedArray(a);
+        // Reset mDrawable to preserve old multiple-inflate behavior. This is
+        // silly, but we have CTS tests that rely on it.
+        mState.mDrawable = null;
 
+        updateStateFromTypedArray(a);
+        inflateChildElements(r, parser, attrs, theme);
+        verifyRequiredAttributes(a);
+        a.recycle();
+    }
+
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
         // Load inner XML elements.
-        if (mInsetState.mDrawable == null) {
+        if (mState.mDrawable == null) {
             int type;
             while ((type=parser.next()) == XmlPullParser.TEXT) {
             }
@@ -102,26 +112,23 @@
                                 + "child tag defining a drawable");
             }
             final Drawable dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
-            mInsetState.mDrawable = dr;
+            mState.mDrawable = dr;
             dr.setCallback(this);
         }
-
-        verifyRequiredAttributes(a);
-        a.recycle();
     }
 
     private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
         // If we're not waiting on a theme, verify required attributes.
-        if (mInsetState.mDrawable == null && (mInsetState.mThemeAttrs == null
-                || mInsetState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
-            throw new XmlPullParserException(a.getPositionDescription() +
-                    ": <inset> tag requires a 'drawable' attribute or "
+        if (mState.mDrawable == null && (mState.mThemeAttrs == null
+                || mState.mThemeAttrs[R.styleable.InsetDrawable_drawable] == 0)) {
+            throw new XmlPullParserException(a.getPositionDescription()
+                    + ": <inset> tag requires a 'drawable' attribute or "
                     + "child tag defining a drawable");
         }
     }
 
     private void updateStateFromTypedArray(TypedArray a) throws XmlPullParserException {
-        final InsetState state = mInsetState;
+        final InsetState state = mState;
 
         // Account for any configuration changes.
         state.mChangingConfigurations |= a.getChangingConfigurations();
@@ -169,7 +176,7 @@
     public void applyTheme(Theme t) {
         super.applyTheme(t);
 
-        final InsetState state = mInsetState;
+        final InsetState state = mState;
         if (state == null) {
             return;
         }
@@ -193,7 +200,7 @@
 
     @Override
     public boolean canApplyTheme() {
-        return super.canApplyTheme() || mInsetState != null && mInsetState.canApplyTheme();
+        return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
     }
 
     @Override
@@ -222,112 +229,112 @@
 
     @Override
     public void draw(Canvas canvas) {
-        mInsetState.mDrawable.draw(canvas);
+        mState.mDrawable.draw(canvas);
     }
 
     @Override
     public int getChangingConfigurations() {
         return super.getChangingConfigurations()
-                | mInsetState.mChangingConfigurations
-                | mInsetState.mDrawable.getChangingConfigurations();
+                | mState.mChangingConfigurations
+                | mState.mDrawable.getChangingConfigurations();
     }
 
     @Override
     public boolean getPadding(Rect padding) {
-        boolean pad = mInsetState.mDrawable.getPadding(padding);
+        boolean pad = mState.mDrawable.getPadding(padding);
 
-        padding.left += mInsetState.mInsetLeft;
-        padding.right += mInsetState.mInsetRight;
-        padding.top += mInsetState.mInsetTop;
-        padding.bottom += mInsetState.mInsetBottom;
+        padding.left += mState.mInsetLeft;
+        padding.right += mState.mInsetRight;
+        padding.top += mState.mInsetTop;
+        padding.bottom += mState.mInsetBottom;
 
-        return pad || (mInsetState.mInsetLeft | mInsetState.mInsetRight |
-                mInsetState.mInsetTop | mInsetState.mInsetBottom) != 0;
+        return pad || (mState.mInsetLeft | mState.mInsetRight |
+                mState.mInsetTop | mState.mInsetBottom) != 0;
     }
 
     /** @hide */
     @Override
     public Insets getOpticalInsets() {
         final Insets contentInsets = super.getOpticalInsets();
-        return Insets.of(contentInsets.left + mInsetState.mInsetLeft,
-                contentInsets.top + mInsetState.mInsetTop,
-                contentInsets.right + mInsetState.mInsetRight,
-                contentInsets.bottom + mInsetState.mInsetBottom);
+        return Insets.of(contentInsets.left + mState.mInsetLeft,
+                contentInsets.top + mState.mInsetTop,
+                contentInsets.right + mState.mInsetRight,
+                contentInsets.bottom + mState.mInsetBottom);
     }
 
     @Override
     public void setHotspot(float x, float y) {
-        mInsetState.mDrawable.setHotspot(x, y);
+        mState.mDrawable.setHotspot(x, y);
     }
 
     @Override
     public void setHotspotBounds(int left, int top, int right, int bottom) {
-        mInsetState.mDrawable.setHotspotBounds(left, top, right, bottom);
+        mState.mDrawable.setHotspotBounds(left, top, right, bottom);
     }
 
     /** @hide */
     @Override
     public void getHotspotBounds(Rect outRect) {
-        mInsetState.mDrawable.getHotspotBounds(outRect);
+        mState.mDrawable.getHotspotBounds(outRect);
     }
 
     @Override
     public boolean setVisible(boolean visible, boolean restart) {
-        mInsetState.mDrawable.setVisible(visible, restart);
+        mState.mDrawable.setVisible(visible, restart);
         return super.setVisible(visible, restart);
     }
 
     @Override
     public void setAlpha(int alpha) {
-        mInsetState.mDrawable.setAlpha(alpha);
+        mState.mDrawable.setAlpha(alpha);
     }
 
     @Override
     public int getAlpha() {
-        return mInsetState.mDrawable.getAlpha();
+        return mState.mDrawable.getAlpha();
     }
 
     @Override
     public void setColorFilter(ColorFilter cf) {
-        mInsetState.mDrawable.setColorFilter(cf);
+        mState.mDrawable.setColorFilter(cf);
     }
 
     @Override
     public void setTintList(ColorStateList tint) {
-        mInsetState.mDrawable.setTintList(tint);
+        mState.mDrawable.setTintList(tint);
     }
 
     @Override
     public void setTintMode(Mode tintMode) {
-        mInsetState.mDrawable.setTintMode(tintMode);
+        mState.mDrawable.setTintMode(tintMode);
     }
 
     /** {@hide} */
     @Override
     public void setLayoutDirection(int layoutDirection) {
-        mInsetState.mDrawable.setLayoutDirection(layoutDirection);
+        mState.mDrawable.setLayoutDirection(layoutDirection);
     }
 
     @Override
     public int getOpacity() {
-        return mInsetState.mDrawable.getOpacity();
+        return mState.mDrawable.getOpacity();
     }
 
     @Override
     public boolean isStateful() {
-        return mInsetState.mDrawable.isStateful();
+        return mState.mDrawable.isStateful();
     }
 
     @Override
     protected boolean onStateChange(int[] state) {
-        boolean changed = mInsetState.mDrawable.setState(state);
+        boolean changed = mState.mDrawable.setState(state);
         onBoundsChange(getBounds());
         return changed;
     }
 
     @Override
     protected boolean onLevelChange(int level) {
-        return mInsetState.mDrawable.setLevel(level);
+        return mState.mDrawable.setLevel(level);
     }
 
     @Override
@@ -335,36 +342,36 @@
         final Rect r = mTmpRect;
         r.set(bounds);
 
-        r.left += mInsetState.mInsetLeft;
-        r.top += mInsetState.mInsetTop;
-        r.right -= mInsetState.mInsetRight;
-        r.bottom -= mInsetState.mInsetBottom;
+        r.left += mState.mInsetLeft;
+        r.top += mState.mInsetTop;
+        r.right -= mState.mInsetRight;
+        r.bottom -= mState.mInsetBottom;
 
-        mInsetState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+        mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
     }
 
     @Override
     public int getIntrinsicWidth() {
-        return mInsetState.mDrawable.getIntrinsicWidth()
-                + mInsetState.mInsetLeft + mInsetState.mInsetRight;
+        return mState.mDrawable.getIntrinsicWidth()
+                + mState.mInsetLeft + mState.mInsetRight;
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return mInsetState.mDrawable.getIntrinsicHeight()
-                + mInsetState.mInsetTop + mInsetState.mInsetBottom;
+        return mState.mDrawable.getIntrinsicHeight()
+                + mState.mInsetTop + mState.mInsetBottom;
     }
 
     @Override
     public void getOutline(@NonNull Outline outline) {
-        mInsetState.mDrawable.getOutline(outline);
+        mState.mDrawable.getOutline(outline);
     }
 
     @Override
     public ConstantState getConstantState() {
-        if (mInsetState.canConstantState()) {
-            mInsetState.mChangingConfigurations = getChangingConfigurations();
-            return mInsetState;
+        if (mState.canConstantState()) {
+            mState.mChangingConfigurations = getChangingConfigurations();
+            return mState;
         }
         return null;
     }
@@ -372,7 +379,7 @@
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            mInsetState.mDrawable.mutate();
+            mState.mDrawable.mutate();
             mMutated = true;
         }
         return this;
@@ -383,7 +390,7 @@
      */
     public void clearMutated() {
         super.clearMutated();
-        mInsetState.mDrawable.clearMutated();
+        mState.mDrawable.clearMutated();
         mMutated = false;
     }
 
@@ -391,7 +398,7 @@
      * Returns the drawable wrapped by this InsetDrawable. May be null.
      */
     public Drawable getDrawable() {
-        return mInsetState.mDrawable;
+        return mState.mDrawable;
     }
 
     final static class InsetState extends ConstantState {
@@ -400,13 +407,13 @@
 
         Drawable mDrawable;
 
-        int mInsetLeft;
-        int mInsetTop;
-        int mInsetRight;
-        int mInsetBottom;
+        int mInsetLeft = 0;
+        int mInsetTop = 0;
+        int mInsetRight = 0;
+        int mInsetBottom = 0;
 
-        boolean mCheckedConstantState;
-        boolean mCanConstantState;
+        private boolean mCheckedConstantState;
+        private boolean mCanConstantState;
 
         InsetState(InsetState orig, InsetDrawable owner, Resources res) {
             if (orig != null) {
@@ -430,6 +437,12 @@
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+                    || super.canApplyTheme();
+        }
+
+        @Override
         public Drawable newDrawable() {
             return new InsetDrawable(this, null);
         }
@@ -444,12 +457,6 @@
             return mChangingConfigurations;
         }
 
-        @Override
-        public boolean canApplyTheme() {
-            return super.canApplyTheme() || mThemeAttrs != null
-                    || mDrawable != null && mDrawable.canApplyTheme();
-        }
-
         boolean canConstantState() {
             if (!mCheckedConstantState) {
                 mCanConstantState = mDrawable.getConstantState() != null;
@@ -461,7 +468,7 @@
     }
 
     private InsetDrawable(InsetState state, Resources res) {
-        mInsetState = new InsetState(state, this, res);
+        mState = new InsetState(state, this, res);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index 5107e10..689d225 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -275,7 +275,7 @@
 
     @Override
     public boolean canApplyTheme() {
-        return super.canApplyTheme() || mLayerState != null && mLayerState.canApplyTheme();
+        return (mLayerState != null && mLayerState.canApplyTheme()) || super.canApplyTheme();
     }
 
     /**
@@ -1020,7 +1020,7 @@
 
         @Override
         public boolean canApplyTheme() {
-            if (mThemeAttrs != null) {
+            if (mThemeAttrs != null || super.canApplyTheme()) {
                 return true;
             }
 
diff --git a/graphics/java/android/graphics/drawable/RippleDrawable.java b/graphics/java/android/graphics/drawable/RippleDrawable.java
index 316139b..e658279 100644
--- a/graphics/java/android/graphics/drawable/RippleDrawable.java
+++ b/graphics/java/android/graphics/drawable/RippleDrawable.java
@@ -473,7 +473,7 @@
 
     @Override
     public boolean canApplyTheme() {
-        return super.canApplyTheme() || mState != null && mState.canApplyTheme();
+        return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
     }
 
     @Override
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index 3f75bc3..9208a0a 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -31,7 +31,6 @@
 import android.content.res.Resources.Theme;
 import android.util.TypedValue;
 import android.util.AttributeSet;
-import android.util.Log;
 
 import java.io.IOException;
 
@@ -314,6 +313,11 @@
     }
 
     @Override
+    public boolean canApplyTheme() {
+        return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
+    }
+
+    @Override
     public void invalidateDrawable(Drawable who) {
         final Callback callback = getCallback();
         if (callback != null) {
@@ -401,80 +405,17 @@
     @Override
     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
-        final TypedArray a = obtainAttributes(r, theme, attrs,
-                com.android.internal.R.styleable.RotateDrawable);
+        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.RotateDrawable);
+        super.inflateWithAttributes(r, parser, a, R.styleable.RotateDrawable_visible);
 
-        super.inflateWithAttributes(r, parser, a,
-                com.android.internal.R.styleable.RotateDrawable_visible);
+        // Reset mDrawable to preserve old multiple-inflate behavior. This is
+        // silly, but we have CTS tests that rely on it.
+        mState.mDrawable = null;
 
-        TypedValue tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotX);
-        final boolean pivotXRel;
-        final float pivotX;
-        if (tv == null) {
-            pivotXRel = true;
-            pivotX = 0.5f;
-        } else {
-            pivotXRel = tv.type == TypedValue.TYPE_FRACTION;
-            pivotX = pivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
-        }
-
-        tv = a.peekValue(com.android.internal.R.styleable.RotateDrawable_pivotY);
-        final boolean pivotYRel;
-        final float pivotY;
-        if (tv == null) {
-            pivotYRel = true;
-            pivotY = 0.5f;
-        } else {
-            pivotYRel = tv.type == TypedValue.TYPE_FRACTION;
-            pivotY = pivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
-        }
-
-        final float fromDegrees = a.getFloat(
-                com.android.internal.R.styleable.RotateDrawable_fromDegrees, 0.0f);
-        final float toDegrees = a.getFloat(
-                com.android.internal.R.styleable.RotateDrawable_toDegrees, 360.0f);
-
-        final int res = a.getResourceId(
-                com.android.internal.R.styleable.RotateDrawable_drawable, 0);
-        Drawable drawable = null;
-        if (res > 0) {
-            drawable = r.getDrawable(res, theme);
-        }
-
+        updateStateFromTypedArray(a);
+        inflateChildElements(r, parser, attrs, theme);
+        verifyRequiredAttributes(a);
         a.recycle();
-
-        final int outerDepth = parser.getDepth();
-        int type;
-        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT &&
-               (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
-
-            if (type != XmlPullParser.START_TAG) {
-                continue;
-            }
-
-            if ((drawable = Drawable.createFromXmlInner(r, parser, attrs, theme)) == null) {
-                Log.w("drawable", "Bad element under <rotate>: "
-                        + parser .getName());
-            }
-        }
-
-        if (drawable == null) {
-            Log.w("drawable", "No drawable specified for <rotate>");
-        }
-
-        final RotateState st = mState;
-        st.mDrawable = drawable;
-        st.mPivotXRel = pivotXRel;
-        st.mPivotX = pivotX;
-        st.mPivotYRel = pivotYRel;
-        st.mPivotY = pivotY;
-        st.mFromDegrees = fromDegrees;
-        st.mCurrentDegrees = fromDegrees;
-        st.mToDegrees = toDegrees;
-
-        if (drawable != null) {
-            drawable.setCallback(this);
-        }
     }
 
     @Override
@@ -486,15 +427,79 @@
             return;
         }
 
-        if (state.mDrawable != null) {
+        final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.RotateDrawable);
+        try {
+            updateStateFromTypedArray(a);
+            verifyRequiredAttributes(a);
+        } catch (XmlPullParserException e) {
+            throw new RuntimeException(e);
+        } finally {
+            a.recycle();
+        }
+
+        if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
             state.mDrawable.applyTheme(t);
         }
     }
 
-    @Override
-    public boolean canApplyTheme() {
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        Drawable dr = null;
+        int type;
+        final int outerDepth = parser.getDepth();
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
+                && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
+            if (type != XmlPullParser.START_TAG) {
+                continue;
+            }
+            dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
+        }
+
+        if (dr != null) {
+            mState.mDrawable = dr;
+            dr.setCallback(this);
+        }
+    }
+
+    private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+        // If we're not waiting on a theme, verify required attributes.
+        if (mState.mDrawable == null && (mState.mThemeAttrs == null
+                || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
+            throw new XmlPullParserException(a.getPositionDescription()
+                    + ": <rotate> tag requires a 'drawable' attribute or "
+                    + "child tag defining a drawable");
+        }
+    }
+
+    private void updateStateFromTypedArray(TypedArray a) {
         final RotateState state = mState;
-        return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mThemeAttrs = a.extractThemeAttrs();
+
+        if (a.hasValue(R.styleable.RotateDrawable_pivotX)) {
+            final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotX);
+            state.mPivotXRel = tv.type == TypedValue.TYPE_FRACTION;
+            state.mPivotX = state.mPivotXRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+        }
+
+        if (a.hasValue(R.styleable.RotateDrawable_pivotY)) {
+            final TypedValue tv = a.peekValue(R.styleable.RotateDrawable_pivotY);
+            state.mPivotYRel = tv.type == TypedValue.TYPE_FRACTION;
+            state.mPivotY = state.mPivotYRel ? tv.getFraction(1.0f, 1.0f) : tv.getFloat();
+        }
+
+        state.mFromDegrees = a.getFloat(R.styleable.RotateDrawable_fromDegrees, state.mFromDegrees);
+        state.mToDegrees = a.getFloat(R.styleable.RotateDrawable_toDegrees, state.mToDegrees);
+
+        final Drawable dr = a.getDrawable(R.styleable.RotateDrawable_drawable);
+        if (dr != null) {
+            state.mDrawable = dr;
+            dr.setCallback(this);
+        }
     }
 
     @Override
@@ -521,25 +526,28 @@
      * rotations at the same time.
      */
     final static class RotateState extends Drawable.ConstantState {
-        Drawable mDrawable;
-
+        int[] mThemeAttrs;
         int mChangingConfigurations;
 
-        boolean mPivotXRel;
-        float mPivotX;
-        boolean mPivotYRel;
-        float mPivotY;
+        Drawable mDrawable;
 
-        float mFromDegrees;
-        float mToDegrees;
+        boolean mPivotXRel = true;
+        float mPivotX = 0.5f;
+        boolean mPivotYRel = true;
+        float mPivotY = 0.5f;
 
-        float mCurrentDegrees;
+        float mFromDegrees = 0.0f;
+        float mToDegrees = 360.0f;
 
-        private boolean mCanConstantState;
+        float mCurrentDegrees = 0.0f;
+
         private boolean mCheckedConstantState;
+        private boolean mCanConstantState;
 
-        public RotateState(RotateState orig, RotateDrawable owner, Resources res) {
+        RotateState(RotateState orig, RotateDrawable owner, Resources res) {
             if (orig != null) {
+                mThemeAttrs = orig.mThemeAttrs;
+                mChangingConfigurations = orig.mChangingConfigurations;
                 if (res != null) {
                     mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
                 } else {
@@ -553,13 +561,20 @@
                 mPivotX = orig.mPivotX;
                 mPivotYRel = orig.mPivotYRel;
                 mPivotY = orig.mPivotY;
-                mFromDegrees = mCurrentDegrees = orig.mFromDegrees;
+                mFromDegrees = orig.mFromDegrees;
                 mToDegrees = orig.mToDegrees;
-                mCanConstantState = mCheckedConstantState = true;
+                mCurrentDegrees = orig.mCurrentDegrees;
+                mCheckedConstantState = mCanConstantState = true;
             }
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+                    || super.canApplyTheme();
+        }
+
+        @Override
         public Drawable newDrawable() {
             return new RotateDrawable(this, null);
         }
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 9a5b8fb..fbe38b4 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -16,6 +16,8 @@
 
 package android.graphics.drawable;
 
+import com.android.internal.R;
+
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
@@ -47,7 +49,7 @@
  * @attr ref android.R.styleable#ScaleDrawable_drawable
  */
 public class ScaleDrawable extends Drawable implements Drawable.Callback {
-    private ScaleState mScaleState;
+    private ScaleState mState;
     private boolean mMutated;
     private final Rect mTmpRect = new Rect();
 
@@ -58,10 +60,10 @@
     public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) {
         this(null, null);
 
-        mScaleState.mDrawable = drawable;
-        mScaleState.mGravity = gravity;
-        mScaleState.mScaleWidth = scaleWidth;
-        mScaleState.mScaleHeight = scaleHeight;
+        mState.mDrawable = drawable;
+        mState.mGravity = gravity;
+        mState.mScaleWidth = scaleWidth;
+        mState.mScaleHeight = scaleHeight;
 
         if (drawable != null) {
             drawable.setCallback(this);
@@ -72,18 +74,18 @@
      * Returns the drawable scaled by this ScaleDrawable.
      */
     public Drawable getDrawable() {
-        return mScaleState.mDrawable;
+        return mState.mDrawable;
     }
 
-    private static float getPercent(TypedArray a, int name) {
-        String s = a.getString(name);
+    private static float getPercent(TypedArray a, int name, float defaultValue) {
+        final String s = a.getString(name);
         if (s != null) {
             if (s.endsWith("%")) {
                 String f = s.substring(0, s.length() - 1);
                 return Float.parseFloat(f) / 100.0f;
             }
         }
-        return -1;
+        return defaultValue;
     }
 
     @Override
@@ -91,20 +93,48 @@
             throws XmlPullParserException, IOException {
         super.inflate(r, parser, attrs, theme);
 
-        int type;
+        final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.ScaleDrawable);
 
-        TypedArray a = obtainAttributes(
-                r, theme, attrs, com.android.internal.R.styleable.ScaleDrawable);
+        // Reset mDrawable to preserve old multiple-inflate behavior. This is
+        // silly, but we have CTS tests that rely on it.
+        mState.mDrawable = null;
 
-        float sw = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleWidth);
-        float sh = getPercent(a, com.android.internal.R.styleable.ScaleDrawable_scaleHeight);
-        int g = a.getInt(com.android.internal.R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT);
-        boolean min = a.getBoolean(
-                com.android.internal.R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false);
-        Drawable dr = a.getDrawable(com.android.internal.R.styleable.ScaleDrawable_drawable);
-
+        updateStateFromTypedArray(a);
+        inflateChildElements(r, parser, attrs, theme);
+        verifyRequiredAttributes(a);
         a.recycle();
+    }
 
+    @Override
+    public void applyTheme(Theme t) {
+        super.applyTheme(t);
+
+        final ScaleState state = mState;
+        if (state == null) {
+            return;
+        }
+
+        if (state.mThemeAttrs == null) {
+            final TypedArray a = t.resolveAttributes(state.mThemeAttrs, R.styleable.ScaleDrawable);
+            try {
+                updateStateFromTypedArray(a);
+                verifyRequiredAttributes(a);
+            } catch (XmlPullParserException e) {
+                throw new RuntimeException(e);
+            } finally {
+                a.recycle();
+            }
+        }
+
+        if (state.mDrawable != null && state.mDrawable.canApplyTheme()) {
+            state.mDrawable.applyTheme(t);
+        }
+    }
+
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        Drawable dr = null;
+        int type;
         final int outerDepth = parser.getDepth();
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
                 && (type != XmlPullParser.END_TAG || parser.getDepth() > outerDepth)) {
@@ -114,38 +144,49 @@
             dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
         }
 
-        if (dr == null) {
-            throw new IllegalArgumentException("No drawable specified for <scale>");
-        }
-
-        mScaleState.mDrawable = dr;
-        mScaleState.mScaleWidth = sw;
-        mScaleState.mScaleHeight = sh;
-        mScaleState.mGravity = g;
-        mScaleState.mUseIntrinsicSizeAsMin = min;
         if (dr != null) {
+            mState.mDrawable = dr;
+            dr.setCallback(this);
+        }
+    }
+
+    private void verifyRequiredAttributes(TypedArray a) throws XmlPullParserException {
+        // If we're not waiting on a theme, verify required attributes.
+        if (mState.mDrawable == null && (mState.mThemeAttrs == null
+                || mState.mThemeAttrs[R.styleable.ScaleDrawable_drawable] == 0)) {
+            throw new XmlPullParserException(a.getPositionDescription()
+                    + ": <scale> tag requires a 'drawable' attribute or "
+                    + "child tag defining a drawable");
+        }
+    }
+
+    private void updateStateFromTypedArray(TypedArray a) {
+        final ScaleState state = mState;
+
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mThemeAttrs = a.extractThemeAttrs();
+
+        state.mScaleWidth = getPercent(
+                a, R.styleable.ScaleDrawable_scaleWidth, state.mScaleWidth);
+        state.mScaleHeight = getPercent(
+                a, R.styleable.ScaleDrawable_scaleHeight, state.mScaleHeight);
+        state.mGravity = a.getInt(R.styleable.ScaleDrawable_scaleGravity, Gravity.LEFT);
+        state.mUseIntrinsicSizeAsMin = a.getBoolean(
+                R.styleable.ScaleDrawable_useIntrinsicSizeAsMinimum, false);
+
+        final Drawable dr = a.getDrawable(R.styleable.ScaleDrawable_drawable);
+        if (dr != null) {
+            state.mDrawable = dr;
             dr.setCallback(this);
         }
     }
 
     @Override
-    public void applyTheme(Theme t) {
-        super.applyTheme(t);
-
-        final ScaleState state = mScaleState;
-        if (state == null) {
-            return;
-        }
-
-        if (state.mDrawable != null) {
-            state.mDrawable.applyTheme(t);
-        }
-    }
-
-    @Override
     public boolean canApplyTheme() {
-        final ScaleState state = mScaleState;
-        return state != null && state.mDrawable != null && state.mDrawable.canApplyTheme();
+        return (mState != null && mState.canApplyTheme()) || super.canApplyTheme();
     }
 
     // overrides from Drawable.Callback
@@ -172,74 +213,74 @@
 
     @Override
     public void draw(Canvas canvas) {
-        if (mScaleState.mDrawable.getLevel() != 0)
-            mScaleState.mDrawable.draw(canvas);
+        if (mState.mDrawable.getLevel() != 0)
+            mState.mDrawable.draw(canvas);
     }
 
     @Override
     public int getChangingConfigurations() {
         return super.getChangingConfigurations()
-                | mScaleState.mChangingConfigurations
-                | mScaleState.mDrawable.getChangingConfigurations();
+                | mState.mChangingConfigurations
+                | mState.mDrawable.getChangingConfigurations();
     }
 
     @Override
     public boolean getPadding(Rect padding) {
         // XXX need to adjust padding!
-        return mScaleState.mDrawable.getPadding(padding);
+        return mState.mDrawable.getPadding(padding);
     }
 
     @Override
     public boolean setVisible(boolean visible, boolean restart) {
-        mScaleState.mDrawable.setVisible(visible, restart);
+        mState.mDrawable.setVisible(visible, restart);
         return super.setVisible(visible, restart);
     }
 
     @Override
     public void setAlpha(int alpha) {
-        mScaleState.mDrawable.setAlpha(alpha);
+        mState.mDrawable.setAlpha(alpha);
     }
 
     @Override
     public int getAlpha() {
-        return mScaleState.mDrawable.getAlpha();
+        return mState.mDrawable.getAlpha();
     }
 
     @Override
     public void setColorFilter(ColorFilter cf) {
-        mScaleState.mDrawable.setColorFilter(cf);
+        mState.mDrawable.setColorFilter(cf);
     }
 
     @Override
     public void setTintList(ColorStateList tint) {
-        mScaleState.mDrawable.setTintList(tint);
+        mState.mDrawable.setTintList(tint);
     }
 
     @Override
     public void setTintMode(Mode tintMode) {
-        mScaleState.mDrawable.setTintMode(tintMode);
+        mState.mDrawable.setTintMode(tintMode);
     }
 
     @Override
     public int getOpacity() {
-        return mScaleState.mDrawable.getOpacity();
+        return mState.mDrawable.getOpacity();
     }
 
     @Override
     public boolean isStateful() {
-        return mScaleState.mDrawable.isStateful();
+        return mState.mDrawable.isStateful();
     }
 
     @Override
     protected boolean onStateChange(int[] state) {
-        boolean changed = mScaleState.mDrawable.setState(state);
+        boolean changed = mState.mDrawable.setState(state);
         onBoundsChange(getBounds());
         return changed;
     }
 
     @Override
     protected boolean onLevelChange(int level) {
-        mScaleState.mDrawable.setLevel(level);
+        mState.mDrawable.setLevel(level);
         onBoundsChange(getBounds());
         invalidateSelf();
         return true;
@@ -248,41 +289,41 @@
     @Override
     protected void onBoundsChange(Rect bounds) {
         final Rect r = mTmpRect;
-        final boolean min = mScaleState.mUseIntrinsicSizeAsMin;
+        final boolean min = mState.mUseIntrinsicSizeAsMin;
         int level = getLevel();
         int w = bounds.width();
-        if (mScaleState.mScaleWidth > 0) {
-            final int iw = min ? mScaleState.mDrawable.getIntrinsicWidth() : 0;
-            w -= (int) ((w - iw) * (10000 - level) * mScaleState.mScaleWidth / 10000);
+        if (mState.mScaleWidth > 0) {
+            final int iw = min ? mState.mDrawable.getIntrinsicWidth() : 0;
+            w -= (int) ((w - iw) * (10000 - level) * mState.mScaleWidth / 10000);
         }
         int h = bounds.height();
-        if (mScaleState.mScaleHeight > 0) {
-            final int ih = min ? mScaleState.mDrawable.getIntrinsicHeight() : 0;
-            h -= (int) ((h - ih) * (10000 - level) * mScaleState.mScaleHeight / 10000);
+        if (mState.mScaleHeight > 0) {
+            final int ih = min ? mState.mDrawable.getIntrinsicHeight() : 0;
+            h -= (int) ((h - ih) * (10000 - level) * mState.mScaleHeight / 10000);
         }
         final int layoutDirection = getLayoutDirection();
-        Gravity.apply(mScaleState.mGravity, w, h, bounds, r, layoutDirection);
+        Gravity.apply(mState.mGravity, w, h, bounds, r, layoutDirection);
 
         if (w > 0 && h > 0) {
-            mScaleState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
+            mState.mDrawable.setBounds(r.left, r.top, r.right, r.bottom);
         }
     }
 
     @Override
     public int getIntrinsicWidth() {
-        return mScaleState.mDrawable.getIntrinsicWidth();
+        return mState.mDrawable.getIntrinsicWidth();
     }
 
     @Override
     public int getIntrinsicHeight() {
-        return mScaleState.mDrawable.getIntrinsicHeight();
+        return mState.mDrawable.getIntrinsicHeight();
     }
 
     @Override
     public ConstantState getConstantState() {
-        if (mScaleState.canConstantState()) {
-            mScaleState.mChangingConfigurations = getChangingConfigurations();
-            return mScaleState;
+        if (mState.canConstantState()) {
+            mState.mChangingConfigurations = getChangingConfigurations();
+            return mState;
         }
         return null;
     }
@@ -290,7 +331,7 @@
     @Override
     public Drawable mutate() {
         if (!mMutated && super.mutate() == this) {
-            mScaleState.mDrawable.mutate();
+            mState.mDrawable.mutate();
             mMutated = true;
         }
         return this;
@@ -301,23 +342,28 @@
      */
     public void clearMutated() {
         super.clearMutated();
-        mScaleState.mDrawable.clearMutated();
+        mState.mDrawable.clearMutated();
         mMutated = false;
     }
 
     final static class ScaleState extends ConstantState {
-        Drawable mDrawable;
+        int[] mThemeAttrs;
         int mChangingConfigurations;
-        float mScaleWidth;
-        float mScaleHeight;
-        int mGravity;
-        boolean mUseIntrinsicSizeAsMin;
+
+        Drawable mDrawable;
+
+        float mScaleWidth = 1.0f;
+        float mScaleHeight = 1.0f;
+        int mGravity = Gravity.LEFT;
+        boolean mUseIntrinsicSizeAsMin = false;
 
         private boolean mCheckedConstantState;
         private boolean mCanConstantState;
 
         ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) {
             if (orig != null) {
+                mThemeAttrs = orig.mThemeAttrs;
+                mChangingConfigurations = orig.mChangingConfigurations;
                 if (res != null) {
                     mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
                 } else {
@@ -336,6 +382,12 @@
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null || (mDrawable != null && mDrawable.canApplyTheme())
+                    || super.canApplyTheme();
+        }
+
+        @Override
         public Drawable newDrawable() {
             return new ScaleDrawable(this, null);
         }
@@ -361,7 +413,7 @@
     }
 
     private ScaleDrawable(ScaleState state, Resources res) {
-        mScaleState = new ScaleState(state, this, res);
+        mState = new ScaleState(state, this, res);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index a299b3c..963943b 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -117,26 +117,48 @@
     @Override
     public void inflate(Resources r, XmlPullParser parser, AttributeSet attrs, Theme theme)
             throws XmlPullParserException, IOException {
-
         final TypedArray a = obtainAttributes(r, theme, attrs, R.styleable.StateListDrawable);
-
-        super.inflateWithAttributes(r, parser, a,
-                R.styleable.StateListDrawable_visible);
-
-        mStateListState.setVariablePadding(a.getBoolean(
-                R.styleable.StateListDrawable_variablePadding, false));
-        mStateListState.setConstantSize(a.getBoolean(
-                R.styleable.StateListDrawable_constantSize, false));
-        mStateListState.setEnterFadeDuration(a.getInt(
-                R.styleable.StateListDrawable_enterFadeDuration, 0));
-        mStateListState.setExitFadeDuration(a.getInt(
-                R.styleable.StateListDrawable_exitFadeDuration, 0));
-
-        setDither(a.getBoolean(R.styleable.StateListDrawable_dither, DEFAULT_DITHER));
-        setAutoMirrored(a.getBoolean(R.styleable.StateListDrawable_autoMirrored, false));
-
+        super.inflateWithAttributes(r, parser, a, R.styleable.StateListDrawable_visible);
+        updateStateFromTypedArray(a);
         a.recycle();
 
+        inflateChildElements(r, parser, attrs, theme);
+
+        onStateChange(getState());
+    }
+
+    /**
+     * Updates the constant state from the values in the typed array.
+     */
+    private void updateStateFromTypedArray(TypedArray a) {
+        final StateListState state = mStateListState;
+
+        // Account for any configuration changes.
+        state.mChangingConfigurations |= a.getChangingConfigurations();
+
+        // Extract the theme attributes, if any.
+        state.mThemeAttrs = a.extractThemeAttrs();
+
+        state.mVariablePadding = a.getBoolean(
+                R.styleable.StateListDrawable_variablePadding, state.mVariablePadding);
+        state.mConstantSize = a.getBoolean(
+                R.styleable.StateListDrawable_constantSize, state.mConstantSize);
+        state.mEnterFadeDuration = a.getInt(
+                R.styleable.StateListDrawable_enterFadeDuration, state.mEnterFadeDuration);
+        state.mExitFadeDuration = a.getInt(
+                R.styleable.StateListDrawable_exitFadeDuration, state.mExitFadeDuration);
+        state.mDither = a.getBoolean(
+                R.styleable.StateListDrawable_dither, state.mDither);
+        state.mAutoMirrored = a.getBoolean(
+                R.styleable.StateListDrawable_autoMirrored, state.mAutoMirrored);
+    }
+
+    /**
+     * Inflates child elements from XML.
+     */
+    private void inflateChildElements(Resources r, XmlPullParser parser, AttributeSet attrs,
+            Theme theme) throws XmlPullParserException, IOException {
+        final StateListState state = mStateListState;
         final int innerDepth = parser.getDepth() + 1;
         int type;
         int depth;
@@ -185,10 +207,8 @@
                 dr = Drawable.createFromXmlInner(r, parser, attrs, theme);
             }
 
-            mStateListState.addStateSet(states, dr);
+            state.addStateSet(states, dr);
         }
-
-        onStateChange(getState());
     }
 
     StateListState getStateListState() {
@@ -282,6 +302,7 @@
     }
 
     static class StateListState extends DrawableContainerState {
+        int[] mThemeAttrs;
         int[][] mStateSets;
 
         StateListState(StateListState orig, StateListDrawable owner, Resources res) {
@@ -298,7 +319,11 @@
                         mStateSets[i] = set.clone();
                     }
                 }
+
+                mThemeAttrs = orig.mThemeAttrs;
+                mStateSets = Arrays.copyOf(orig.mStateSets, orig.mStateSets.length);
             } else {
+                mThemeAttrs = null;
                 mStateSets = new int[getCapacity()][];
             }
         }
@@ -331,6 +356,11 @@
         }
 
         @Override
+        public boolean canApplyTheme() {
+            return mThemeAttrs != null || super.canApplyTheme();
+        }
+
+        @Override
         public void growArray(int oldSize, int newSize) {
             super.growArray(oldSize, newSize);
             final int[][] newStateSets = new int[newSize][];
diff --git a/graphics/java/android/graphics/drawable/VectorDrawable.java b/graphics/java/android/graphics/drawable/VectorDrawable.java
index 848fc53..8b0f635 100644
--- a/graphics/java/android/graphics/drawable/VectorDrawable.java
+++ b/graphics/java/android/graphics/drawable/VectorDrawable.java
@@ -361,7 +361,7 @@
 
     @Override
     public boolean canApplyTheme() {
-        return super.canApplyTheme() || mVectorState != null && mVectorState.canApplyTheme();
+        return (mVectorState != null && mVectorState.canApplyTheme()) || super.canApplyTheme();
     }
 
     @Override
@@ -750,8 +750,8 @@
 
         @Override
         public boolean canApplyTheme() {
-            return super.canApplyTheme() || mThemeAttrs != null
-                    || (mVPathRenderer != null && mVPathRenderer.canApplyTheme());
+            return mThemeAttrs != null || (mVPathRenderer != null && mVPathRenderer.canApplyTheme())
+                    || super.canApplyTheme();
         }
 
         public VectorDrawableState() {