Invalidate when Drawable.setState() returns true

Ensures views that manage drawables follow the contract set forth in
the Drawable.setState() documentation.

Bug: 23792020
Change-Id: I4e5a449cd6535487873fd8443da50555c38e8ed9
diff --git a/core/java/android/app/MediaRouteButton.java b/core/java/android/app/MediaRouteButton.java
index af3b565..181c907 100644
--- a/core/java/android/app/MediaRouteButton.java
+++ b/core/java/android/app/MediaRouteButton.java
@@ -256,10 +256,10 @@
     protected void drawableStateChanged() {
         super.drawableStateChanged();
 
-        if (mRemoteIndicator != null) {
-            int[] myDrawableState = getDrawableState();
-            mRemoteIndicator.setState(myDrawableState);
-            invalidate();
+        final Drawable remoteIndicator = mRemoteIndicator;
+        if (remoteIndicator != null && remoteIndicator.isStateful()
+                && remoteIndicator.setState(getDrawableState())) {
+            invalidateDrawable(remoteIndicator);
         }
     }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ed48319..f4fc6e7 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -16473,7 +16473,7 @@
      */
     void setBackgroundBounds() {
         if (mBackgroundSizeChanged && mBackground != null) {
-            mBackground.setBounds(0, 0,  mRight - mLeft, mBottom - mTop);
+            mBackground.setBounds(0, 0, mRight - mLeft, mBottom - mTop);
             mBackgroundSizeChanged = false;
             rebuildOutline();
         }
@@ -17042,27 +17042,33 @@
     @CallSuper
     protected void drawableStateChanged() {
         final int[] state = getDrawableState();
+        boolean changed = false;
 
         final Drawable bg = mBackground;
         if (bg != null && bg.isStateful()) {
-            bg.setState(state);
+            changed |= bg.setState(state);
         }
 
         final Drawable fg = mForegroundInfo != null ? mForegroundInfo.mDrawable : null;
         if (fg != null && fg.isStateful()) {
-            fg.setState(state);
+            changed |= fg.setState(state);
         }
 
         if (mScrollCache != null) {
             final Drawable scrollBar = mScrollCache.scrollBar;
             if (scrollBar != null && scrollBar.isStateful()) {
-                scrollBar.setState(state);
+                changed |= scrollBar.setState(state)
+                        && mScrollCache.state != ScrollabilityCache.OFF;
             }
         }
 
         if (mStateListAnimator != null) {
             mStateListAnimator.setState(state);
         }
+
+        if (changed) {
+            invalidate();
+        }
     }
 
     /**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 586ae77..389fc0a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2777,11 +2777,14 @@
     }
 
     void updateSelectorState() {
-        if (mSelector != null) {
+        final Drawable selector = mSelector;
+        if (selector != null && selector.isStateful()) {
             if (shouldShowSelector()) {
-                mSelector.setState(getDrawableStateForSelector());
+                if (selector.setState(getDrawableStateForSelector())) {
+                    invalidateDrawable(selector);
+                }
             } else {
-                mSelector.setState(StateSet.NOTHING);
+                selector.setState(StateSet.NOTHING);
             }
         }
     }
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 76e91d1..6883db2 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -369,8 +369,9 @@
         }
 
         final Drawable thumb = mThumb;
-        if (thumb != null && thumb.isStateful()) {
-            thumb.setState(getDrawableState());
+        if (thumb != null && thumb.isStateful()
+                && thumb.setState(getDrawableState())) {
+            invalidateDrawable(thumb);
         }
     }
 
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index c1d2756..a018d26 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -425,14 +425,11 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        
-        if (mCheckMarkDrawable != null) {
-            int[] myDrawableState = getDrawableState();
-            
-            // Set the state of the Drawable
-            mCheckMarkDrawable.setState(myDrawableState);
-            
-            invalidate();
+
+        final Drawable checkMarkDrawable = mCheckMarkDrawable;
+        if (checkMarkDrawable != null && checkMarkDrawable.isStateful()
+                && checkMarkDrawable.setState(getDrawableState())) {
+            invalidateDrawable(checkMarkDrawable);
         }
     }
 
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 602e1ab..b19fe17 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -456,14 +456,11 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        
-        if (mButtonDrawable != null) {
-            int[] myDrawableState = getDrawableState();
-            
-            // Set the state of the Drawable
-            mButtonDrawable.setState(myDrawableState);
-            
-            invalidate();
+
+        final Drawable buttonDrawable = mButtonDrawable;
+        if (buttonDrawable != null && buttonDrawable.isStateful()
+                && buttonDrawable.setState(getDrawableState())) {
+            invalidateDrawable(buttonDrawable);
         }
     }
 
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index b53af0c..245c7332 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -1165,9 +1165,10 @@
     protected void drawableStateChanged() {
         super.drawableStateChanged();
 
-        final Drawable d = mDrawable;
-        if (d != null && d.isStateful()) {
-            d.setState(getDrawableState());
+        final Drawable drawable = mDrawable;
+        if (drawable != null && drawable.isStateful()
+                && drawable.setState(getDrawableState())) {
+            invalidateDrawable(drawable);
         }
     }
 
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index b5fae4e..c3ddec7 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1528,10 +1528,10 @@
     protected void drawableStateChanged() {
         super.drawableStateChanged();
 
-        final int[] state = getDrawableState();
-
-        if (mSelectionDivider != null && mSelectionDivider.isStateful()) {
-            mSelectionDivider.setState(state);
+        final Drawable selectionDivider = mSelectionDivider;
+        if (selectionDivider != null && selectionDivider.isStateful()
+                && selectionDivider.setState(getDrawableState())) {
+            invalidateDrawable(selectionDivider);
         }
     }
 
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 4186c40..fce3754 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -1746,13 +1746,20 @@
 
     private void updateDrawableState() {
         final int[] state = getDrawableState();
+        boolean changed = false;
 
-        if (mProgressDrawable != null && mProgressDrawable.isStateful()) {
-            mProgressDrawable.setState(state);
+        final Drawable progressDrawable = mProgressDrawable;
+        if (progressDrawable != null && progressDrawable.isStateful()) {
+            changed |= progressDrawable.setState(state);
         }
 
-        if (mIndeterminateDrawable != null && mIndeterminateDrawable.isStateful()) {
-            mIndeterminateDrawable.setState(state);
+        final Drawable indeterminateDrawable = mIndeterminateDrawable;
+        if (indeterminateDrawable != null && indeterminateDrawable.isStateful()) {
+            changed |= indeterminateDrawable.setState(state);
+        }
+
+        if (changed) {
+            invalidate();
         }
     }
 
diff --git a/core/java/android/widget/QuickContactBadge.java b/core/java/android/widget/QuickContactBadge.java
index 25b301f..e241d4c 100644
--- a/core/java/android/widget/QuickContactBadge.java
+++ b/core/java/android/widget/QuickContactBadge.java
@@ -105,9 +105,11 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        if (mOverlay != null && mOverlay.isStateful()) {
-            mOverlay.setState(getDrawableState());
-            invalidate();
+
+        final Drawable overlay = mOverlay;
+        if (overlay != null && overlay.isStateful()
+                && overlay.setState(getDrawableState())) {
+            invalidateDrawable(overlay);
         }
     }
 
diff --git a/core/java/android/widget/Switch.java b/core/java/android/widget/Switch.java
index 9319af0..6f3a711 100644
--- a/core/java/android/widget/Switch.java
+++ b/core/java/android/widget/Switch.java
@@ -1339,17 +1339,22 @@
     protected void drawableStateChanged() {
         super.drawableStateChanged();
 
-        final int[] myDrawableState = getDrawableState();
+        final int[] state = getDrawableState();
+        boolean changed = false;
 
-        if (mThumbDrawable != null) {
-            mThumbDrawable.setState(myDrawableState);
+        final Drawable thumbDrawable = mThumbDrawable;
+        if (thumbDrawable != null && thumbDrawable.isStateful()) {
+            changed |= thumbDrawable.setState(state);
         }
 
-        if (mTrackDrawable != null) {
-            mTrackDrawable.setState(myDrawableState);
+        final Drawable trackDrawable = mTrackDrawable;
+        if (trackDrawable != null && trackDrawable.isStateful()) {
+            changed |= trackDrawable.setState(state);
         }
 
-        invalidate();
+        if (changed) {
+            invalidate();
+        }
     }
 
     @Override
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 61402ab..0712052 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -3996,6 +3996,7 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
+
         if (mTextColor != null && mTextColor.isStateful()
                 || (mHintTextColor != null && mHintTextColor.isStateful())
                 || (mLinkTextColor != null && mLinkTextColor.isStateful())) {
@@ -4005,8 +4006,8 @@
         if (mDrawables != null) {
             final int[] state = getDrawableState();
             for (Drawable dr : mDrawables.mShowing) {
-                if (dr != null && dr.isStateful()) {
-                    dr.setState(state);
+                if (dr != null && dr.isStateful() && dr.setState(state)) {
+                    invalidateDrawable(dr);
                 }
             }
         }
@@ -4017,9 +4018,8 @@
         super.drawableHotspotChanged(x, y);
 
         if (mDrawables != null) {
-            final int[] state = getDrawableState();
             for (Drawable dr : mDrawables.mShowing) {
-                if (dr != null && dr.isStateful()) {
+                if (dr != null) {
                     dr.setHotspot(x, y);
                 }
             }
diff --git a/core/java/com/android/internal/widget/ActionBarContainer.java b/core/java/com/android/internal/widget/ActionBarContainer.java
index 1961b4b..398bbe7 100644
--- a/core/java/com/android/internal/widget/ActionBarContainer.java
+++ b/core/java/com/android/internal/widget/ActionBarContainer.java
@@ -155,14 +155,27 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        if (mBackground != null && mBackground.isStateful()) {
-            mBackground.setState(getDrawableState());
+
+        final int[] state = getDrawableState();
+        boolean changed = false;
+
+        final Drawable background = mBackground;
+        if (background != null && background.isStateful()) {
+            changed |= background.setState(state);
         }
-        if (mStackedBackground != null && mStackedBackground.isStateful()) {
-            mStackedBackground.setState(getDrawableState());
+
+        final Drawable stackedBackground = mStackedBackground;
+        if (stackedBackground != null && stackedBackground.isStateful()) {
+            changed |= stackedBackground.setState(state);
         }
-        if (mSplitBackground != null && mSplitBackground.isStateful()) {
-            mSplitBackground.setState(getDrawableState());
+
+        final Drawable splitBackground = mSplitBackground;
+        if (splitBackground != null && splitBackground.isStateful()) {
+            changed |= splitBackground.setState(state);
+        }
+
+        if (changed) {
+            invalidate();
         }
     }
 
diff --git a/core/java/com/android/internal/widget/ViewPager.java b/core/java/com/android/internal/widget/ViewPager.java
index a2c4f6a..6217d6e 100644
--- a/core/java/com/android/internal/widget/ViewPager.java
+++ b/core/java/com/android/internal/widget/ViewPager.java
@@ -753,9 +753,10 @@
     @Override
     protected void drawableStateChanged() {
         super.drawableStateChanged();
-        final Drawable d = mMarginDrawable;
-        if (d != null && d.isStateful()) {
-            d.setState(getDrawableState());
+        final Drawable marginDrawable = mMarginDrawable;
+        if (marginDrawable != null && marginDrawable.isStateful()
+                && marginDrawable.setState(getDrawableState())) {
+            invalidateDrawable(marginDrawable);
         }
     }