Merge "Tweak action bar metrics."
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 5216c49..04f35dc 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -161,10 +161,11 @@
     // Hardware layers
     ///////////////////////////////////////////////////////////////////////////
     
-    static native int nCreateTextureLayer(int[] layerInfo);
+    static native int nCreateTextureLayer(boolean opaque, int[] layerInfo);
     static native int nCreateLayer(int width, int height, boolean isOpaque, int[] layerInfo);
     static native void nResizeLayer(int layerId, int width, int height, int[] layerInfo);
-    static native void nUpdateTextureLayer(int layerId, int width, int height, SurfaceTexture surface);
+    static native void nUpdateTextureLayer(int layerId, int width, int height, boolean opaque,
+            SurfaceTexture surface);
     static native void nDestroyLayer(int layerId);
     static native void nDestroyLayerDeferred(int layerId);
     static native boolean nCopyLayer(int layerId, int bitmap);
diff --git a/core/java/android/view/GLES20TextureLayer.java b/core/java/android/view/GLES20TextureLayer.java
index 063eee7..3ac4459 100644
--- a/core/java/android/view/GLES20TextureLayer.java
+++ b/core/java/android/view/GLES20TextureLayer.java
@@ -28,9 +28,9 @@
     private int mTexture;
     private SurfaceTexture mSurface;
 
-    GLES20TextureLayer() {
+    GLES20TextureLayer(boolean isOpaque) {
         int[] layerInfo = new int[2];
-        mLayer = GLES20Canvas.nCreateTextureLayer(layerInfo);
+        mLayer = GLES20Canvas.nCreateTextureLayer(isOpaque, layerInfo);
 
         if (mLayer != 0) {
             mTexture = layerInfo[0];
@@ -70,7 +70,7 @@
         return mSurface;
     }
 
-    void update(int width, int height) {
-        GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, mSurface);
+    void update(int width, int height, boolean isOpaque) {
+        GLES20Canvas.nUpdateTextureLayer(mLayer, width, height, isOpaque, mSurface);
     }
 }
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index 5ceb12a..c6d011e 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -170,9 +170,11 @@
      * Creates a new hardware layer. A hardware layer built by calling this
      * method will be treated as a texture layer, instead of as a render target.
      * 
+     * @param isOpaque Whether the layer should be opaque or not
+     * 
      * @return A hardware layer
      */    
-    abstract HardwareLayer createHardwareLayer();
+    abstract HardwareLayer createHardwareLayer(boolean isOpaque);
     
     /**
      * Creates a new hardware layer.
@@ -202,8 +204,9 @@
      * @param layer The hardware layer to update
      * @param width The layer's width
      * @param height The layer's height
+     * @param isOpaque Whether the layer is opaque
      */
-    abstract void updateTextureLayer(HardwareLayer layer, int width, int height);
+    abstract void updateTextureLayer(HardwareLayer layer, int width, int height, boolean isOpaque);
 
     /**
      * Copies the content of the specified layer into the specified bitmap.
@@ -803,8 +806,8 @@
         }
 
         @Override
-        HardwareLayer createHardwareLayer() {
-            return new GLES20TextureLayer();
+        HardwareLayer createHardwareLayer(boolean isOpaque) {
+            return new GLES20TextureLayer(isOpaque);
         }
 
         @Override
@@ -818,8 +821,8 @@
         }
 
         @Override
-        void updateTextureLayer(HardwareLayer layer, int width, int height) {
-            ((GLES20TextureLayer) layer).update(width, height);
+        void updateTextureLayer(HardwareLayer layer, int width, int height, boolean isOpaque) {
+            ((GLES20TextureLayer) layer).update(width, height, isOpaque);
         }
 
         @Override
diff --git a/core/java/android/view/TextureView.java b/core/java/android/view/TextureView.java
index 2f598f4..4790289 100644
--- a/core/java/android/view/TextureView.java
+++ b/core/java/android/view/TextureView.java
@@ -96,9 +96,14 @@
     private SurfaceTexture mSurface;
     private SurfaceTextureListener mListener;
 
-    private final Object[] mLock = new Object[0];
-    private boolean mUpdateLayer;
+    private boolean mOpaque = true;
 
+    private final Runnable mUpdateLayerAction = new Runnable() {
+        @Override
+        public void run() {
+            updateLayer();
+        }
+    };
     private SurfaceTexture.OnFrameAvailableListener mUpdateListener;
 
     /**
@@ -143,6 +148,28 @@
         mLayerPaint = new Paint();
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public boolean isOpaque() {
+        return mOpaque;
+    }
+
+    /**
+     * Indicates whether the content of this TextureView is opaque. The
+     * content is assumed to be opaque by default.
+     * 
+     * @param opaque True if the content of this TextureView is opaque,
+     *               false otherwise
+     */
+    public void setOpaque(boolean opaque) {
+        if (opaque != mOpaque) {
+            mOpaque = opaque;
+            if (mLayer != null) updateLayer();
+        }
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -212,7 +239,6 @@
      */
     @Override
     public final void draw(Canvas canvas) {
-        super.draw(canvas);
     }
 
     /**
@@ -229,8 +255,6 @@
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         super.onSizeChanged(w, h, oldw, oldh);
         if (mSurface != null) {
-            // No need to synchronize here, we set update layer to false only on the UI thread
-            mUpdateLayer = true;
             nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
             if (mListener != null) {
                 mListener.onSurfaceTextureSizeChanged(mSurface, getWidth(), getHeight());
@@ -245,7 +269,7 @@
         }
 
         if (mLayer == null) {
-            mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer();
+            mLayer = mAttachInfo.mHardwareRenderer.createHardwareLayer(mOpaque);
             mSurface = mAttachInfo.mHardwareRenderer.createSurfaceTexture(mLayer);
             nSetDefaultBufferSize(mSurface, getWidth(), getHeight());
 
@@ -254,10 +278,7 @@
                 public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                     // Per SurfaceTexture's documentation, the callback may be invoked
                     // from an arbitrary thread
-                    synchronized (mLock) {
-                        mUpdateLayer = true;
-                        postInvalidate();
-                    }
+                    post(mUpdateLayerAction);
                 }
             };
             mSurface.setOnFrameAvailableListener(mUpdateListener);
@@ -267,13 +288,6 @@
             }
         }
 
-        synchronized (mLock) {
-            if (mUpdateLayer) {
-                mAttachInfo.mHardwareRenderer.updateTextureLayer(mLayer, getWidth(), getHeight());
-                mUpdateLayer = false;
-            }
-        }
-
         return mLayer;
     }
 
@@ -287,15 +301,23 @@
             // updates listener
             if (visibility == VISIBLE) {
                 mSurface.setOnFrameAvailableListener(mUpdateListener);
-                // No need to synchronize here, we set update layer to false only on the UI thread
-                mUpdateLayer = true;
-                invalidate();
+                updateLayer();
             } else {
                 mSurface.setOnFrameAvailableListener(null);
             }
         }
     }
 
+    private void updateLayer() {
+        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+            return;
+        }
+
+        mAttachInfo.mHardwareRenderer.updateTextureLayer(mLayer, getWidth(), getHeight(), mOpaque);
+
+        invalidate();
+    }
+
     /**
      * <p>Returns a {@link android.graphics.Bitmap} representation of the content
      * of the associated surface texture. If the surface texture is not available,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f70ca90..8184643 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -9674,10 +9674,10 @@
                 computeScroll();
                 canvas.translate(-mScrollX, -mScrollY);
                 mPrivateFlags |= DRAWN | DRAWING_CACHE_VALID;
+                mPrivateFlags &= ~DIRTY_MASK;
 
                 // Fast path for layouts with no backgrounds
                 if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                    mPrivateFlags &= ~DIRTY_MASK;
                     dispatchDraw(canvas);
                 } else {
                     draw(canvas);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index e928f80..b9474e6 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1233,6 +1233,7 @@
     /**
      * {@inheritDoc}
      */
+    @SuppressWarnings({"ConstantConditions"})
     @Override
     protected boolean dispatchHoverEvent(MotionEvent event) {
         final int action = event.getAction();
@@ -3876,8 +3877,10 @@
                 if (!childMatrix.isIdentity()) {
                     RectF boundingRect = attachInfo.mTmpTransformRect;
                     boundingRect.set(dirty);
+                    //boundingRect.inset(-0.5f, -0.5f);
                     childMatrix.mapRect(boundingRect);
-                    dirty.set((int) boundingRect.left, (int) boundingRect.top,
+                    dirty.set((int) (boundingRect.left - 0.5f),
+                            (int) (boundingRect.top - 0.5f),
                             (int) (boundingRect.right + 0.5f),
                             (int) (boundingRect.bottom + 0.5f));
                 }
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index 16992997..aff4394 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -608,8 +608,8 @@
 }
 
 static Layer* android_view_GLES20Canvas_createTextureLayer(JNIEnv* env, jobject clazz,
-        jintArray layerInfo) {
-    Layer* layer = LayerRenderer::createTextureLayer();
+        jboolean isOpaque, jintArray layerInfo) {
+    Layer* layer = LayerRenderer::createTextureLayer(isOpaque);
 
     if (layer) {
         jint* storage = env->GetIntArrayElements(layerInfo, NULL);
@@ -645,7 +645,7 @@
 }
 
 static void android_view_GLES20Canvas_updateTextureLayer(JNIEnv* env, jobject clazz,
-        Layer* layer, jint width, jint height, jobject surface) {
+        Layer* layer, jint width, jint height, jboolean isOpaque, jobject surface) {
     float transform[16];
     sp<SurfaceTexture> surfaceTexture(SurfaceTexture_getSurfaceTexture(env, surface));
 
@@ -655,7 +655,7 @@
     surfaceTexture->getTransformMatrix(transform);
     GLenum renderTarget = surfaceTexture->getCurrentTextureTarget();
 
-    LayerRenderer::updateTextureLayer(layer, width, height, renderTarget, transform);
+    LayerRenderer::updateTextureLayer(layer, width, height, isOpaque, renderTarget, transform);
 }
 
 static void android_view_GLES20Canvas_destroyLayer(JNIEnv* env, jobject clazz, Layer* layer) {
@@ -797,8 +797,8 @@
     { "nCreateLayerRenderer",    "(I)I",       (void*) android_view_GLES20Canvas_createLayerRenderer },
     { "nCreateLayer",            "(IIZ[I)I",   (void*) android_view_GLES20Canvas_createLayer },
     { "nResizeLayer",            "(III[I)V" ,  (void*) android_view_GLES20Canvas_resizeLayer },
-    { "nCreateTextureLayer",     "([I)I",      (void*) android_view_GLES20Canvas_createTextureLayer },
-    { "nUpdateTextureLayer",     "(IIILandroid/graphics/SurfaceTexture;)V",
+    { "nCreateTextureLayer",     "(Z[I)I",     (void*) android_view_GLES20Canvas_createTextureLayer },
+    { "nUpdateTextureLayer",     "(IIIZLandroid/graphics/SurfaceTexture;)V",
                                                (void*) android_view_GLES20Canvas_updateTextureLayer },
     { "nDestroyLayer",           "(I)V",       (void*) android_view_GLES20Canvas_destroyLayer },
     { "nDestroyLayerDeferred",   "(I)V",       (void*) android_view_GLES20Canvas_destroyLayerDeferred },
diff --git a/libs/hwui/LayerRenderer.cpp b/libs/hwui/LayerRenderer.cpp
index 77e63d7..dfb5d3b 100644
--- a/libs/hwui/LayerRenderer.cpp
+++ b/libs/hwui/LayerRenderer.cpp
@@ -166,13 +166,13 @@
 // Layers management
 ///////////////////////////////////////////////////////////////////////////////
 
-Layer* LayerRenderer::createTextureLayer() {
+Layer* LayerRenderer::createTextureLayer(bool isOpaque) {
     LAYER_RENDERER_LOGD("Creating new texture layer");
 
     Layer* layer = new Layer(0, 0);
     layer->isCacheable = false;
     layer->isTextureLayer = true;
-    layer->blend = true;
+    layer->blend = !isOpaque;
     layer->empty = true;
     layer->fbo = 0;
     layer->colorFilter = NULL;
@@ -270,8 +270,9 @@
 }
 
 void LayerRenderer::updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-        GLenum renderTarget, float* transform) {
+        bool isOpaque, GLenum renderTarget, float* transform) {
     if (layer) {
+        layer->blend = !isOpaque;
         layer->width = width;
         layer->height = height;
         layer->layer.set(0.0f, 0.0f, width, height);
diff --git a/libs/hwui/LayerRenderer.h b/libs/hwui/LayerRenderer.h
index 797dfc6..2246573 100644
--- a/libs/hwui/LayerRenderer.h
+++ b/libs/hwui/LayerRenderer.h
@@ -55,11 +55,11 @@
     Region* getRegion();
     GLint getTargetFbo();
 
-    static Layer* createTextureLayer();
+    static Layer* createTextureLayer(bool isOpaque);
     static Layer* createLayer(uint32_t width, uint32_t height, bool isOpaque = false);
     static bool resizeLayer(Layer* layer, uint32_t width, uint32_t height);
     static void updateTextureLayer(Layer* layer, uint32_t width, uint32_t height,
-            GLenum renderTarget, float* transform);
+            bool isOpaque, GLenum renderTarget, float* transform);
     static void destroyLayer(Layer* layer);
     static void destroyLayerDeferred(Layer* layer);
     static bool copyLayer(Layer* layer, SkBitmap* bitmap);
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 88774c6..1c06a0b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -639,7 +639,7 @@
     setupDrawTextureTransform();
     setupDrawColor(alpha, alpha, alpha, alpha);
     setupDrawColorFilter();
-    setupDrawBlending(layer->blend, layer->mode);
+    setupDrawBlending(layer->blend || layer->alpha < 255, layer->mode);
     setupDrawProgram();
     setupDrawModelView(rect.left, rect.top, rect.right, rect.bottom);
     setupDrawPureColorUniforms();
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
index fa2e39a..9bc1fe0 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/TextureViewActivity.java
@@ -18,7 +18,6 @@
 
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
-import android.animation.ValueAnimator;
 import android.app.Activity;
 import android.graphics.SurfaceTexture;
 import android.hardware.Camera;
@@ -55,7 +54,7 @@
             @Override
             public void onClick(View v) {
                 if (mAdded) {
-                    mAnimatorSet.cancel();
+                    if (mAnimatorSet != null) mAnimatorSet.cancel();
                     mContent.removeView(mTextureView);
                 } else {
                     mContent.addView(mTextureView);
@@ -85,25 +84,19 @@
 
         mTextureView.setCameraDistance(5000);
 
-        ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
-        rotationY.setRepeatMode(ObjectAnimator.REVERSE);
-        rotationY.setRepeatCount(ObjectAnimator.INFINITE);
-        rotationY.setDuration(4000);
-        rotationY.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator animation) {
-                ((View) mTextureView.getParent()).invalidate();
-            }
-        });
+//        ObjectAnimator rotationY = ObjectAnimator.ofFloat(mTextureView, "rotationY", 0.0f, 360.0f);
+//        rotationY.setRepeatMode(ObjectAnimator.REVERSE);
+//        rotationY.setRepeatCount(ObjectAnimator.INFINITE);
+//        rotationY.setDuration(4000);
 
-        ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
-        alpha.setRepeatMode(ObjectAnimator.REVERSE);
-        alpha.setRepeatCount(ObjectAnimator.INFINITE);
-        alpha.setDuration(4000);
+//        ObjectAnimator alpha = ObjectAnimator.ofFloat(mTextureView, "alpha", 1.0f, 0.0f);
+//        alpha.setRepeatMode(ObjectAnimator.REVERSE);
+//        alpha.setRepeatCount(ObjectAnimator.INFINITE);
+//        alpha.setDuration(4000);
 
-        mAnimatorSet = new AnimatorSet();
-        mAnimatorSet.play(alpha).with(rotationY);
-        mAnimatorSet.start();
+//        mAnimatorSet = new AnimatorSet();
+//        mAnimatorSet.play(alpha).with(rotationY);
+//        mAnimatorSet.start();
     }
 
     @Override