View pressed state dispatching tweaks

Bugs 6075823, 6050563

Revise pressed state dispatch logic:

Only propagate pressed state to non-clickable views. This should
eliminate the "double glow" problem in some list items where a
clickable child button has a secondary glow along with a clickable
parent. This only applies to setPressed(true) calls; setPressed(false)
must propagate. Don't early-out in setPressed to support this use
case.

Change-Id: Ibbe2309f5030282fad8d23e4a9bc4616b3f5dc7c
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0675a74..e6b41da 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5048,16 +5048,17 @@
      *        the View's internal state from a previously set "pressed" state.
      */
     public void setPressed(boolean pressed) {
-        if (pressed == ((mPrivateFlags & PRESSED) == PRESSED)) {
-            return;
-        }
+        final boolean needsRefresh = pressed != ((mPrivateFlags & PRESSED) == PRESSED);
 
         if (pressed) {
             mPrivateFlags |= PRESSED;
         } else {
             mPrivateFlags &= ~PRESSED;
         }
-        refreshDrawableState();
+
+        if (needsRefresh) {
+            refreshDrawableState();
+        }
         dispatchSetPressed(pressed);
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 2848e88..05c2b57 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -2770,7 +2770,13 @@
         final View[] children = mChildren;
         final int count = mChildrenCount;
         for (int i = 0; i < count; i++) {
-            children[i].setPressed(pressed);
+            final View child = children[i];
+            // Children that are clickable on their own should not
+            // show a pressed state when their parent view does.
+            // Clearing a pressed state always propagates.
+            if (!pressed || (!child.isClickable() && !child.isLongClickable())) {
+                child.setPressed(pressed);
+            }
         }
     }