Merge "Remove obsolete OMXComponentBase class"
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index bf91700..d08a61f 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -960,6 +960,11 @@
                                 Log.d(ViewDebug.DEBUG_LATENCY_TAG, "- getDisplayList() took " +
                                         total + "ms");
                             }
+                            if (View.USE_DISPLAY_LIST_PROPERTIES) {
+                                Log.d("DLProperties", "getDisplayList():\t" +
+                                        mProfileData[mProfileCurrentFrame]);
+                            }
+
                         }
 
                         if (displayList != null) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cb73856..6d1f207 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1503,7 +1503,7 @@
      * apps.
      * @hide
      */
-    protected static final boolean USE_DISPLAY_LIST_PROPERTIES = false;
+    public static final boolean USE_DISPLAY_LIST_PROPERTIES = false;
 
     /**
      * Map used to store views' tags.
@@ -7349,8 +7349,7 @@
      * @see #setRotationY(float) 
      */
     public void setCameraDistance(float distance) {
-        invalidateParentCaches();
-        invalidate(false);
+        invalidateViewProperty(true, false);
 
         ensureTransformationInfo();
         final float dpi = mResources.getDisplayMetrics().densityDpi;
@@ -7363,7 +7362,7 @@
         info.mCamera.setLocation(0.0f, 0.0f, -Math.abs(distance) / dpi);
         info.mMatrixDirty = true;
 
-        invalidate(false);
+        invalidateViewProperty(false, false);
         if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
             mDisplayList.setCameraDistance(distance);
         }
@@ -7401,13 +7400,11 @@
         ensureTransformationInfo();
         final TransformationInfo info = mTransformationInfo;
         if (info.mRotation != rotation) {
-            invalidateParentCaches();
             // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mRotation = rotation;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setRotation(rotation);
             }
@@ -7451,13 +7448,10 @@
         ensureTransformationInfo();
         final TransformationInfo info = mTransformationInfo;
         if (info.mRotationY != rotationY) {
-            invalidateParentCaches();
-            // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mRotationY = rotationY;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setRotationY(rotationY);
             }
@@ -7501,13 +7495,10 @@
         ensureTransformationInfo();
         final TransformationInfo info = mTransformationInfo;
         if (info.mRotationX != rotationX) {
-            invalidateParentCaches();
-            // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mRotationX = rotationX;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setRotationX(rotationX);
             }
@@ -7543,13 +7534,10 @@
         ensureTransformationInfo();
         final TransformationInfo info = mTransformationInfo;
         if (info.mScaleX != scaleX) {
-            invalidateParentCaches();
-            // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mScaleX = scaleX;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setScaleX(scaleX);
             }
@@ -7585,13 +7573,10 @@
         ensureTransformationInfo();
         final TransformationInfo info = mTransformationInfo;
         if (info.mScaleY != scaleY) {
-            invalidateParentCaches();
-            // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mScaleY = scaleY;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setScaleY(scaleY);
             }
@@ -7633,13 +7618,10 @@
         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
         final TransformationInfo info = mTransformationInfo;
         if (info.mPivotX != pivotX) {
-            invalidateParentCaches();
-            // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mPivotX = pivotX;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setPivotX(pivotX);
             }
@@ -7680,13 +7662,10 @@
         mPrivateFlags |= PIVOT_EXPLICITLY_SET;
         final TransformationInfo info = mTransformationInfo;
         if (info.mPivotY != pivotY) {
-            invalidateParentCaches();
-            // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mPivotY = pivotY;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setPivotY(pivotY);
             }
@@ -7728,14 +7707,14 @@
         ensureTransformationInfo();
         if (mTransformationInfo.mAlpha != alpha) {
             mTransformationInfo.mAlpha = alpha;
-            invalidateParentCaches();
             if (onSetAlpha((int) (alpha * 255))) {
                 mPrivateFlags |= ALPHA_SET;
                 // subclass is handling alpha - don't optimize rendering cache invalidation
+                invalidateParentCaches();
                 invalidate(true);
             } else {
                 mPrivateFlags &= ~ALPHA_SET;
-                invalidate(false);
+                invalidateViewProperty(true, false);
                 if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                     mDisplayList.setAlpha(alpha);
                 }
@@ -8102,13 +8081,11 @@
         ensureTransformationInfo();
         final TransformationInfo info = mTransformationInfo;
         if (info.mTranslationX != translationX) {
-            invalidateParentCaches();
             // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mTranslationX = translationX;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setTranslationX(translationX);
             }
@@ -8142,13 +8119,10 @@
         ensureTransformationInfo();
         final TransformationInfo info = mTransformationInfo;
         if (info.mTranslationY != translationY) {
-            invalidateParentCaches();
-            // Double-invalidation is necessary to capture view's old and new areas
-            invalidate(false);
+            invalidateViewProperty(true, false);
             info.mTranslationY = translationY;
             info.mMatrixDirty = true;
-            mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-            invalidate(false);
+            invalidateViewProperty(false, true);
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.setTranslationY(translationY);
             }
@@ -8260,39 +8234,43 @@
             final boolean matrixIsIdentity = mTransformationInfo == null
                     || mTransformationInfo.mMatrixIsIdentity;
             if (matrixIsIdentity) {
-                final ViewParent p = mParent;
-                if (p != null && mAttachInfo != null) {
-                    final Rect r = mAttachInfo.mTmpInvalRect;
-                    int minTop;
-                    int maxBottom;
-                    int yLoc;
-                    if (offset < 0) {
-                        minTop = mTop + offset;
-                        maxBottom = mBottom;
-                        yLoc = offset;
-                    } else {
-                        minTop = mTop;
-                        maxBottom = mBottom + offset;
-                        yLoc = 0;
+                if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+                    invalidateViewProperty(false, false);
+                } else {
+                    final ViewParent p = mParent;
+                    if (p != null && mAttachInfo != null) {
+                        final Rect r = mAttachInfo.mTmpInvalRect;
+                        int minTop;
+                        int maxBottom;
+                        int yLoc;
+                        if (offset < 0) {
+                            minTop = mTop + offset;
+                            maxBottom = mBottom;
+                            yLoc = offset;
+                        } else {
+                            minTop = mTop;
+                            maxBottom = mBottom + offset;
+                            yLoc = 0;
+                        }
+                        r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
+                        p.invalidateChild(this, r);
                     }
-                    r.set(0, yLoc, mRight - mLeft, maxBottom - minTop);
-                    p.invalidateChild(this, r);
                 }
             } else {
-                invalidate(false);
+                invalidateViewProperty(false, false);
             }
 
             mTop += offset;
             mBottom += offset;
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.offsetTopBottom(offset);
+                invalidateViewProperty(false, false);
+            } else {
+                if (!matrixIsIdentity) {
+                    invalidateViewProperty(false, true);
+                }
+                invalidateParentIfNeeded();
             }
-
-            if (!matrixIsIdentity) {
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-                invalidate(false);
-            }
-            invalidateParentIfNeeded();
         }
     }
 
@@ -8307,36 +8285,40 @@
             final boolean matrixIsIdentity = mTransformationInfo == null
                     || mTransformationInfo.mMatrixIsIdentity;
             if (matrixIsIdentity) {
-                final ViewParent p = mParent;
-                if (p != null && mAttachInfo != null) {
-                    final Rect r = mAttachInfo.mTmpInvalRect;
-                    int minLeft;
-                    int maxRight;
-                    if (offset < 0) {
-                        minLeft = mLeft + offset;
-                        maxRight = mRight;
-                    } else {
-                        minLeft = mLeft;
-                        maxRight = mRight + offset;
+                if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
+                    invalidateViewProperty(false, false);
+                } else {
+                    final ViewParent p = mParent;
+                    if (p != null && mAttachInfo != null) {
+                        final Rect r = mAttachInfo.mTmpInvalRect;
+                        int minLeft;
+                        int maxRight;
+                        if (offset < 0) {
+                            minLeft = mLeft + offset;
+                            maxRight = mRight;
+                        } else {
+                            minLeft = mLeft;
+                            maxRight = mRight + offset;
+                        }
+                        r.set(0, 0, maxRight - minLeft, mBottom - mTop);
+                        p.invalidateChild(this, r);
                     }
-                    r.set(0, 0, maxRight - minLeft, mBottom - mTop);
-                    p.invalidateChild(this, r);
                 }
             } else {
-                invalidate(false);
+                invalidateViewProperty(false, false);
             }
 
             mLeft += offset;
             mRight += offset;
             if (USE_DISPLAY_LIST_PROPERTIES && mDisplayList != null) {
                 mDisplayList.offsetLeftRight(offset);
+                invalidateViewProperty(false, false);
+            } else {
+                if (!matrixIsIdentity) {
+                    invalidateViewProperty(false, true);
+                }
+                invalidateParentIfNeeded();
             }
-
-            if (!matrixIsIdentity) {
-                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
-                invalidate(false);
-            }
-            invalidateParentIfNeeded();
         }
     }
 
@@ -8741,6 +8723,62 @@
     }
 
     /**
+     * Quick invalidation for View property changes (alpha, translationXY, etc.). We don't want to
+     * set any flags or handle all of the cases handled by the default invalidation methods.
+     * Instead, we just want to schedule a traversal in ViewRootImpl with the appropriate
+     * dirty rect. This method calls into fast invalidation methods in ViewGroup that
+     * walk up the hierarchy, transforming the dirty rect as necessary.
+     *
+     * The method also handles normal invalidation logic if display list properties are not
+     * being used in this view. The invalidateParent and forceRedraw flags are used by that
+     * backup approach, to handle these cases used in the various property-setting methods.
+     *
+     * @param invalidateParent Force a call to invalidateParentCaches() if display list properties
+     * are not being used in this view
+     * @param forceRedraw Mark the view as DRAWN to force the invalidation to propagate, if display
+     * list properties are not being used in this view
+     */
+    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
+        if (!USE_DISPLAY_LIST_PROPERTIES || mDisplayList == null ||
+                (mPrivateFlags & DRAW_ANIMATION) == DRAW_ANIMATION) {
+            if (invalidateParent) {
+                invalidateParentCaches();
+            }
+            if (forceRedraw) {
+                mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
+            }
+            invalidate(false);
+        } else {
+            final AttachInfo ai = mAttachInfo;
+            final ViewParent p = mParent;
+            if (p != null && ai != null) {
+                final Rect r = ai.mTmpInvalRect;
+                r.set(0, 0, mRight - mLeft, mBottom - mTop);
+                if (mParent instanceof ViewGroup) {
+                    ((ViewGroup) mParent).invalidateChildFast(this, r);
+                } else {
+                    mParent.invalidateChild(this, r);
+                }
+            }
+        }
+    }
+
+    /**
+     * Utility method to transform a given Rect by the current matrix of this view.
+     */
+    void transformRect(final Rect rect) {
+        if (!getMatrix().isIdentity()) {
+            RectF boundingRect = mAttachInfo.mTmpTransformRect;
+            boundingRect.set(rect);
+            getMatrix().mapRect(boundingRect);
+            rect.set((int) (boundingRect.left - 0.5f),
+                    (int) (boundingRect.top - 0.5f),
+                    (int) (boundingRect.right + 0.5f),
+                    (int) (boundingRect.bottom + 0.5f));
+        }
+    }
+
+    /**
      * Used to indicate that the parent of this view should clear its caches. This functionality
      * is used to force the parent to rebuild its display list (when hardware-accelerated),
      * which is necessary when various parent-managed properties of the view change, such as
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1993ce6..42426b9 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -3896,6 +3896,72 @@
     }
 
     /**
+     * Quick invalidation method called by View.invalidateViewProperty. This doesn't set the
+     * DRAWN flags and doesn't handle the Animation logic that the default invalidation methods
+     * do; all we want to do here is schedule a traversal with the appropriate dirty rect.
+     *
+     * @hide
+     */
+    public void invalidateChildFast(View child, final Rect dirty) {
+        ViewParent parent = this;
+
+        final AttachInfo attachInfo = mAttachInfo;
+        if (attachInfo != null) {
+            if (child.mLayerType != LAYER_TYPE_NONE) {
+                child.mLocalDirtyRect.union(dirty);
+            }
+
+            int left = child.mLeft;
+            int top = child.mTop;
+            if (!child.getMatrix().isIdentity()) {
+                child.transformRect(dirty);
+            }
+
+            do {
+                if (parent instanceof ViewGroup) {
+                    ViewGroup parentVG = (ViewGroup) parent;
+                    parent = parentVG.invalidateChildInParentFast(left, top, dirty);
+                    left = parentVG.mLeft;
+                    top = parentVG.mTop;
+                } else {
+                    // Reached the top; this calls into the usual invalidate method in
+                    // ViewRootImpl, which schedules a traversal
+                    final int[] location = attachInfo.mInvalidateChildLocation;
+                    location[0] = left;
+                    location[1] = top;
+                    parent = parent.invalidateChildInParent(location, dirty);
+                }
+            } while (parent != null);
+        }
+    }
+
+    /**
+     * Quick invalidation method that simply transforms the dirty rect into the parent's
+     * coordinate system, pruning the invalidation if the parent has already been invalidated.
+     */
+    private ViewParent invalidateChildInParentFast(int left, int top, final Rect dirty) {
+        if ((mPrivateFlags & DRAWN) == DRAWN ||
+                (mPrivateFlags & DRAWING_CACHE_VALID) == DRAWING_CACHE_VALID) {
+            dirty.offset(left - mScrollX, top - mScrollY);
+
+            if ((mGroupFlags & FLAG_CLIP_CHILDREN) == 0 ||
+                    dirty.intersect(0, 0, mRight - mLeft, mBottom - mTop)) {
+
+                if (mLayerType != LAYER_TYPE_NONE) {
+                    mLocalDirtyRect.union(dirty);
+                }
+                if (!getMatrix().isIdentity()) {
+                    transformRect(dirty);
+                }
+
+                return mParent;
+            }
+        }
+
+        return null;
+    }
+
+    /**
      * Offset a rectangle that is in a descendant's coordinate
      * space into our coordinate space.
      * @param descendant A descendant of this view
@@ -3986,6 +4052,7 @@
             v.mBottom += offset;
             if (USE_DISPLAY_LIST_PROPERTIES && v.mDisplayList != null) {
                 v.mDisplayList.offsetTopBottom(offset);
+                invalidateViewProperty(false, false);
             }
         }
     }
diff --git a/core/java/android/view/ViewPropertyAnimator.java b/core/java/android/view/ViewPropertyAnimator.java
index fe0e659..623b567 100644
--- a/core/java/android/view/ViewPropertyAnimator.java
+++ b/core/java/android/view/ViewPropertyAnimator.java
@@ -986,17 +986,22 @@
                 // Shouldn't happen, but just to play it safe
                 return;
             }
+            boolean useDisplayListProperties = View.USE_DISPLAY_LIST_PROPERTIES &&
+                    mView.mDisplayList != null;
+
             // alpha requires slightly different treatment than the other (transform) properties.
             // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
             // logic is dependent on how the view handles an internal call to onSetAlpha().
             // We track what kinds of properties are set, and how alpha is handled when it is
             // set, and perform the invalidation steps appropriately.
             boolean alphaHandled = false;
-            mView.invalidateParentCaches();
+            if (!useDisplayListProperties) {
+                mView.invalidateParentCaches();
+            }
             float fraction = animation.getAnimatedFraction();
             int propertyMask = propertyBundle.mPropertyMask;
             if ((propertyMask & TRANSFORM_MASK) != 0) {
-                mView.invalidate(false);
+                mView.invalidateViewProperty(false, false);
             }
             ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder;
             if (valueList != null) {
@@ -1013,11 +1018,17 @@
             }
             if ((propertyMask & TRANSFORM_MASK) != 0) {
                 mView.mTransformationInfo.mMatrixDirty = true;
-                mView.mPrivateFlags |= View.DRAWN; // force another invalidation
+                if (!useDisplayListProperties) {
+                    mView.mPrivateFlags |= View.DRAWN; // force another invalidation
+                }
             }
             // invalidate(false) in all cases except if alphaHandled gets set to true
             // via the call to setAlphaNoInvalidation(), above
-            mView.invalidate(alphaHandled);
+            if (alphaHandled) {
+                mView.invalidate(true);
+            } else {
+                mView.invalidateViewProperty(false, false);
+            }
         }
     }
 }
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index a884d8e..118608d 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -671,18 +671,6 @@
         if (mLeft != 0 || mTop != 0) {
             ALOGD("%s%s %d, %d", indent, "Translate", mLeft, mTop);
         }
-        if (mAlpha < 1) {
-            // TODO: should be able to store the size of a DL at record time and not
-            // have to pass it into this call. In fact, this information might be in the
-            // location/size info that we store with the new native transform data.
-            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
-            if (mClipChildren) {
-                flags |= SkCanvas::kClipToLayer_SaveFlag;
-            }
-            ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
-                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
-                    mMultipliedAlpha, flags);
-        }
         if (mMatrixFlags != 0) {
             if (mMatrixFlags == TRANSLATION) {
                 ALOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY);
@@ -696,6 +684,18 @@
                         mTransformMatrix->get(8));
             }
         }
+        if (mAlpha < 1) {
+            // TODO: should be able to store the size of a DL at record time and not
+            // have to pass it into this call. In fact, this information might be in the
+            // location/size info that we store with the new native transform data.
+            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+            if (mClipChildren) {
+                flags |= SkCanvas::kClipToLayer_SaveFlag;
+            }
+            ALOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
+                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
+                    mMultipliedAlpha, flags);
+        }
         if (mClipChildren) {
             ALOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
                     (float) mRight - mLeft, (float) mBottom - mTop);
@@ -724,20 +724,6 @@
                     mApplicationScale, mApplicationScale);
             renderer.scale(mApplicationScale, mApplicationScale);
         }
-        if (mAlpha < 1 && !mCaching) {
-            // TODO: should be able to store the size of a DL at record time and not
-            // have to pass it into this call. In fact, this information might be in the
-            // location/size info that we store with the new native transform data.
-            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
-            if (mClipChildren) {
-                flags |= SkCanvas::kClipToLayer_SaveFlag;
-            }
-            DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
-                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
-                    mMultipliedAlpha, flags);
-            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
-                    mMultipliedAlpha, flags);
-        }
         if (mMatrixFlags != 0) {
             if (mMatrixFlags == TRANSLATION) {
                 DISPLAY_LIST_LOGD("%s%s %f, %f", indent, "Translate", mTranslationX, mTranslationY);
@@ -754,6 +740,20 @@
                 renderer.concatMatrix(mTransformMatrix);
             }
         }
+        if (mAlpha < 1 && !mCaching) {
+            // TODO: should be able to store the size of a DL at record time and not
+            // have to pass it into this call. In fact, this information might be in the
+            // location/size info that we store with the new native transform data.
+            int flags = SkCanvas::kHasAlphaLayer_SaveFlag;
+            if (mClipChildren) {
+                flags |= SkCanvas::kClipToLayer_SaveFlag;
+            }
+            DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f, %d, 0x%x", indent, "SaveLayerAlpha",
+                    (float) 0, (float) 0, (float) mRight - mLeft, (float) mBottom - mTop,
+                    mMultipliedAlpha, flags);
+            renderer.saveLayerAlpha(0, 0, mRight - mLeft, mBottom - mTop,
+                    mMultipliedAlpha, flags);
+        }
         if (mClipChildren) {
             DISPLAY_LIST_LOGD("%s%s %.2f, %.2f, %.2f, %.2f", indent, "ClipRect", 0.0f, 0.0f,
                     (float) mRight - mLeft, (float) mBottom - mTop);
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b4cb1ab..f96a4df 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -2280,16 +2280,8 @@
                 mTextDriver = new TimedTextDriver(mListener);
             }
             // String values written in Parcel are UTF-16 values.
-            String16 uri16 = request.readString16();
-            const char *uri = NULL;
-            if (uri16 != NULL) {
-                uri = String8(uri16).string();
-            }
-            String16 mimeType16 = request.readString16();
-            const char *mimeType = NULL;
-            if (mimeType16 != NULL) {
-                mimeType = String8(mimeType16).string();
-            }
+            String8 uri(request.readString16());
+            String8 mimeType(request.readString16());
             return mTextDriver->addOutOfBandTextSource(uri, mimeType);
         }
         case INVOKE_ID_ADD_EXTERNAL_SOURCE_FD:
@@ -2301,12 +2293,7 @@
             int fd         = request.readFileDescriptor();
             off64_t offset = request.readInt64();
             size_t length  = request.readInt64();
-            String16 mimeType16 = request.readString16();
-            const char *mimeType = NULL;
-            if (mimeType16 != NULL) {
-                mimeType = String8(mimeType16).string();
-            }
-
+            String8 mimeType(request.readString16());
             return mTextDriver->addOutOfBandTextSource(
                     fd, offset, length, mimeType);
         }
diff --git a/media/libstagefright/timedtext/TimedTextDriver.cpp b/media/libstagefright/timedtext/TimedTextDriver.cpp
index ed83894..8ee15f8 100644
--- a/media/libstagefright/timedtext/TimedTextDriver.cpp
+++ b/media/libstagefright/timedtext/TimedTextDriver.cpp
@@ -175,7 +175,7 @@
     }
 
     sp<TimedTextSource> source;
-    if (strcasecmp(mimeType, MEDIA_MIMETYPE_TEXT_SUBRIP)) {
+    if (strcasecmp(mimeType, MEDIA_MIMETYPE_TEXT_SUBRIP) == 0) {
         source = TimedTextSource::CreateTimedTextSource(
                 dataSource, TimedTextSource::OUT_OF_BAND_FILE_SRT);
     }