Merge change 1825 into donut

* changes:
  Fixes #1855461, #1857290 and #1857365. Certain scrollbar styles make an opaque view not be opaque. ListView and View now account for this when indicating whether they are opaque or not.
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 1564fd0..1f72eea 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1443,6 +1443,27 @@
     static final int DIRTY_MASK                     = 0x00600000;
 
     /**
+     * Indicates whether the background is opaque.
+     *
+     * @hide
+     */
+    static final int OPAQUE_BACKGROUND              = 0x00800000;
+
+    /**
+     * Indicates whether the scrollbars are opaque.
+     *
+     * @hide
+     */
+    static final int OPAQUE_SCROLLBARS              = 0x01000000;
+
+    /**
+     * Indicates whether the view is opaque.
+     *
+     * @hide
+     */
+    static final int OPAQUE_MASK                    = 0x01800000;
+
+    /**
      * The parent this view is attached to.
      * {@hide}
      *
@@ -1721,7 +1742,7 @@
     public View(Context context) {
         mContext = context;
         mResources = context != null ? context.getResources() : null;
-        mViewFlags = SOUND_EFFECTS_ENABLED|HAPTIC_FEEDBACK_ENABLED;
+        mViewFlags = SOUND_EFFECTS_ENABLED | HAPTIC_FEEDBACK_ENABLED;
         ++sInstanceCount;
     }
 
@@ -2013,7 +2034,9 @@
         if (!setScrollContainer && (viewFlagValues&SCROLLBARS_VERTICAL) != 0) {
             setScrollContainer(true);
         }
-  
+
+        computeOpaqueFlags();
+
         a.recycle();
     }
 
@@ -4700,7 +4723,35 @@
      */
     @ViewDebug.ExportedProperty
     public boolean isOpaque() {
-        return mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE;
+        return (mPrivateFlags & OPAQUE_MASK) == OPAQUE_MASK;
+    }
+
+    private void computeOpaqueFlags() {
+        // Opaque if:
+        //   - Has a background
+        //   - Background is opaque
+        //   - Doesn't have scrollbars or scrollbars are inside overlay
+
+        if (mBGDrawable != null && mBGDrawable.getOpacity() == PixelFormat.OPAQUE) {
+            mPrivateFlags |= OPAQUE_BACKGROUND;
+        } else {
+            mPrivateFlags &= ~OPAQUE_BACKGROUND;
+        }
+
+        final int flags = mViewFlags;
+        if (((flags & SCROLLBARS_VERTICAL) == 0 && (flags & SCROLLBARS_HORIZONTAL) == 0) ||
+                (flags & SCROLLBARS_STYLE_MASK) == SCROLLBARS_INSIDE_OVERLAY) {
+            mPrivateFlags |= OPAQUE_SCROLLBARS;
+        } else {
+            mPrivateFlags &= ~OPAQUE_SCROLLBARS;
+        }
+    }
+
+    /**
+     * @hide
+     */
+    protected boolean hasOpaqueScrollbars() {
+        return (mPrivateFlags & OPAQUE_SCROLLBARS) == OPAQUE_SCROLLBARS;
     }
 
     /**
@@ -5027,6 +5078,7 @@
     public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
         if (isHorizontalScrollBarEnabled() != horizontalScrollBarEnabled) {
             mViewFlags ^= SCROLLBARS_HORIZONTAL;
+            computeOpaqueFlags();
             recomputePadding();
         }
     }
@@ -5056,6 +5108,7 @@
     public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
         if (isVerticalScrollBarEnabled() != verticalScrollBarEnabled) {
             mViewFlags ^= SCROLLBARS_VERTICAL;
+            computeOpaqueFlags();
             recomputePadding();
         }
     }
@@ -5084,6 +5137,7 @@
     public void setScrollBarStyle(int style) {
         if (style != (mViewFlags & SCROLLBARS_STYLE_MASK)) {
             mViewFlags = (mViewFlags & ~SCROLLBARS_STYLE_MASK) | (style & SCROLLBARS_STYLE_MASK);
+            computeOpaqueFlags();
             recomputePadding();
         }
     }
@@ -6848,6 +6902,8 @@
             requestLayout = true;
         }
 
+        computeOpaqueFlags();
+
         if (requestLayout) {
             requestLayout();
         }
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index c21c7fa..6686f75 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -21,6 +21,7 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.PixelFormat;
+import android.graphics.Paint;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.ColorDrawable;
 import android.os.Parcel;
@@ -133,6 +134,7 @@
 
     // used for temporary calculations.
     private final Rect mTempRect = new Rect();
+    private Paint mDividerPaint;
 
     // the single allocated result per list view; kinda cheesey but avoids
     // allocating these thingies too often.
@@ -2813,12 +2815,20 @@
      */
     @Override
     public boolean isOpaque() {
-        return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque) || super.isOpaque();
+        return (mCachingStarted && mIsCacheColorOpaque && mDividerIsOpaque &&
+                hasOpaqueScrollbars()) || super.isOpaque();
     }
 
     @Override
     public void setCacheColorHint(int color) {
-        mIsCacheColorOpaque = (color >>> 24) == 0xFF;
+        final boolean opaque = (color >>> 24) == 0xFF;
+        mIsCacheColorOpaque = opaque;
+        if (opaque) {
+            if (mDividerPaint == null) {
+                mDividerPaint = new Paint();
+            }
+            mDividerPaint.setColor(color);
+        }
         super.setCacheColorHint(color);
     }
 
@@ -2841,6 +2851,8 @@
             final int first = mFirstPosition;
             final boolean areAllItemsSelectable = mAreAllItemsSelectable;
             final ListAdapter adapter = mAdapter;
+            final boolean isOpaque = isOpaque();
+            final Paint paint = mDividerPaint;
 
             if (!mStackFromBottom) {
                 int bottom;
@@ -2852,12 +2864,18 @@
                         View child = getChildAt(i);
                         bottom = child.getBottom();
                         // Don't draw dividers next to items that are not enabled
-                        if (bottom < listBottom && (areAllItemsSelectable ||
-                                (adapter.isEnabled(first + i) && (i == count - 1 ||
-                                        adapter.isEnabled(first + i + 1))))) {
-                            bounds.top = bottom;
-                            bounds.bottom = bottom + dividerHeight;
-                            drawDivider(canvas, bounds, i);
+                        if (bottom < listBottom) {
+                            if ((areAllItemsSelectable ||
+                                    (adapter.isEnabled(first + i) && (i == count - 1 ||
+                                            adapter.isEnabled(first + i + 1))))) {
+                                bounds.top = bottom;
+                                bounds.bottom = bottom + dividerHeight;
+                                drawDivider(canvas, bounds, i);
+                            } else if (isOpaque) {
+                                bounds.top = bottom;
+                                bounds.bottom = bottom + dividerHeight;
+                                canvas.drawRect(bounds, paint);
+                            }
                         }
                     }
                 }
@@ -2871,16 +2889,22 @@
                         View child = getChildAt(i);
                         top = child.getTop();
                         // Don't draw dividers next to items that are not enabled
-                        if (top > listTop && (areAllItemsSelectable ||
-                                (adapter.isEnabled(first + i) && (i == count - 1 ||
-                                        adapter.isEnabled(first + i + 1))))) {
-                            bounds.top = top - dividerHeight;
-                            bounds.bottom = top;
-                            // Give the method the child ABOVE the divider, so we
-                            // subtract one from our child
-                            // position. Give -1 when there is no child above the
-                            // divider.
-                            drawDivider(canvas, bounds, i - 1);
+                        if (top > listTop) {
+                            if ((areAllItemsSelectable ||
+                                    (adapter.isEnabled(first + i) && (i == count - 1 ||
+                                            adapter.isEnabled(first + i + 1))))) {
+                                bounds.top = top - dividerHeight;
+                                bounds.bottom = top;
+                                // Give the method the child ABOVE the divider, so we
+                                // subtract one from our child
+                                // position. Give -1 when there is no child above the
+                                // divider.
+                                drawDivider(canvas, bounds, i - 1);
+                            } else if (isOpaque) {
+                                bounds.top = top - dividerHeight;
+                                bounds.bottom = top;
+                                canvas.drawRect(bounds, paint);
+                            }
                         }
                     }
                 }