Merge "Add flag to allow fetching related users recent tasks."
diff --git a/api/current.txt b/api/current.txt
index 23229d4..5ebe2eb 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -346,7 +346,6 @@
     field public static final int canRetrieveWindowContent = 16843653; // 0x1010385
     field public static final int candidatesTextStyleSpans = 16843312; // 0x1010230
     field public static final deprecated int capitalize = 16843113; // 0x1010169
-    field public static final int castsShadow = 16843775; // 0x10103ff
     field public static final int category = 16843752; // 0x10103e8
     field public static final int centerBright = 16842956; // 0x10100cc
     field public static final int centerColor = 16843275; // 0x101020b
@@ -826,7 +825,7 @@
     field public static final int persistent = 16842765; // 0x101000d
     field public static final int persistentDrawingCache = 16842990; // 0x10100ee
     field public static final deprecated int phoneNumber = 16843111; // 0x1010167
-    field public static final int pinned = 16843777; // 0x1010401
+    field public static final int pinned = 16843776; // 0x1010400
     field public static final int pivotX = 16843189; // 0x10101b5
     field public static final int pivotY = 16843190; // 0x10101b6
     field public static final int popupAnimationStyle = 16843465; // 0x10102c9
@@ -890,7 +889,7 @@
     field public static final int required = 16843406; // 0x101028e
     field public static final int requiredAccountType = 16843734; // 0x10103d6
     field public static final int requiredForAllUsers = 16843728; // 0x10103d0
-    field public static final int requiredForProfile = 16843776; // 0x1010400
+    field public static final int requiredForProfile = 16843775; // 0x10103ff
     field public static final int requiresFadingEdge = 16843685; // 0x10103a5
     field public static final int requiresSmallestWidthDp = 16843620; // 0x1010364
     field public static final int resizeMode = 16843619; // 0x1010363
@@ -18617,6 +18616,7 @@
     field public static final int JELLY_BEAN_MR1 = 17; // 0x11
     field public static final int JELLY_BEAN_MR2 = 18; // 0x12
     field public static final int KITKAT = 19; // 0x13
+    field public static final int L = 10000; // 0x2710
   }
 
   public final class Bundle implements java.lang.Cloneable android.os.Parcelable {
@@ -29016,7 +29016,6 @@
     method protected float getBottomFadingEdgeStrength();
     method protected int getBottomPaddingOffset();
     method public float getCameraDistance();
-    method public final boolean getCastsShadow();
     method public android.graphics.Rect getClipBounds();
     method public final boolean getClipToOutline();
     method public java.lang.CharSequence getContentDescription();
@@ -29286,7 +29285,6 @@
     method public void setBackgroundResource(int);
     method public final void setBottom(int);
     method public void setCameraDistance(float);
-    method public void setCastsShadow(boolean);
     method public void setClickable(boolean);
     method public void setClipBounds(android.graphics.Rect);
     method public void setClipToOutline(boolean);
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 0351292..344c3b2 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -1479,13 +1479,13 @@
 
     private void validateServiceIntent(Intent service) {
         if (service.getComponent() == null && service.getPackage() == null) {
-            if (true || getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.KITKAT) {
+            if (getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.L) {
+                IllegalArgumentException ex = new IllegalArgumentException(
+                        "Service Intent must be explicit: " + service);
+                throw ex;
+            } else {
                 Log.w(TAG, "Implicit intents with startService are not safe: " + service
                         + " " + Debug.getCallers(2, 3));
-                //IllegalArgumentException ex = new IllegalArgumentException(
-                //        "Service Intent must be explicit: " + service);
-                //Log.e(TAG, "This will become an error", ex);
-                //throw ex;
             }
         }
     }
diff --git a/core/java/android/hardware/camera2/CameraManager.java b/core/java/android/hardware/camera2/CameraManager.java
index 78e7037..0fcd598 100644
--- a/core/java/android/hardware/camera2/CameraManager.java
+++ b/core/java/android/hardware/camera2/CameraManager.java
@@ -81,13 +81,8 @@
         mCameraService = CameraBinderDecorator.newInstance(cameraServiceRaw);
 
         try {
-            int err = CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor();
-            if (err == CameraBinderDecorator.EOPNOTSUPP) {
-                Log.w(TAG, "HAL version doesn't vendor tags.");
-            } else {
-                CameraBinderDecorator.throwOnError(CameraMetadataNative.
-                        nativeSetupGlobalVendorTagDescriptor());
-            }
+            CameraBinderDecorator.throwOnError(
+                    CameraMetadataNative.nativeSetupGlobalVendorTagDescriptor());
         } catch(CameraRuntimeException e) {
             throw new IllegalStateException("Failed to setup camera vendor tags",
                     e.asChecked());
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 22e1476..c8051aa 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -467,6 +467,19 @@
          * </ul>
          */
         public static final int KITKAT = 19;
+
+        /**
+         * L!
+         *
+         * <p>Applications targeting this or a later release will get these
+         * new changes in behavior:</p>
+         * <ul>
+         * <li> {@link android.content.Context#bindService Context.bindService} now
+         * requires an explicit Intent, and will throw an exception if given an explicit
+         * Intent.</li>
+         * </ul>
+         */
+        public static final int L = CUR_DEVELOPMENT;
     }
     
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/speech/SpeechRecognizer.java b/core/java/android/speech/SpeechRecognizer.java
index 94aedbd..91c3799 100644
--- a/core/java/android/speech/SpeechRecognizer.java
+++ b/core/java/android/speech/SpeechRecognizer.java
@@ -409,7 +409,7 @@
      * Internal wrapper of IRecognitionListener which will propagate the results to
      * RecognitionListener
      */
-    private class InternalListener extends IRecognitionListener.Stub {
+    private static class InternalListener extends IRecognitionListener.Stub {
         private RecognitionListener mInternalListener;
 
         private final static int MSG_BEGINNING_OF_SPEECH = 1;
diff --git a/core/java/android/view/RenderNode.java b/core/java/android/view/RenderNode.java
index 430bf5e..87ab20e 100644
--- a/core/java/android/view/RenderNode.java
+++ b/core/java/android/view/RenderNode.java
@@ -365,25 +365,6 @@
     }
 
     /**
-     * Set whether the DisplayList should cast a shadow.
-     *
-     * The shape of the shadow casting area is defined by the outline of the display list, if set
-     * and non-empty, otherwise it will be the bounds rect.
-     */
-    public void setCastsShadow(boolean castsShadow) {
-        nSetCastsShadow(mNativeDisplayList, castsShadow);
-    }
-
-    /**
-     * Sets whether the DisplayList should be drawn with perspective applied from the global camera.
-     *
-     * If set to true, camera distance will be ignored. Defaults to false.
-     */
-    public void setUsesGlobalCamera(boolean usesGlobalCamera) {
-        nSetUsesGlobalCamera(mNativeDisplayList, usesGlobalCamera);
-    }
-
-    /**
      * Set the static matrix on the display list. The specified matrix is combined with other
      * transforms (such as {@link #setScaleX(float)}, {@link #setRotation(float)}, etc.)
      *
@@ -877,8 +858,6 @@
     private static native void nSetIsolatedZVolume(long displayList, boolean isolateZVolume);
     private static native void nSetOutline(long displayList, long nativePath);
     private static native void nSetClipToOutline(long displayList, boolean clipToOutline);
-    private static native void nSetCastsShadow(long displayList, boolean castsShadow);
-    private static native void nSetUsesGlobalCamera(long displayList, boolean usesGlobalCamera);
     private static native void nSetAlpha(long displayList, float alpha);
     private static native void nSetHasOverlappingRendering(long displayList,
             boolean hasOverlappingRendering);
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index e693b9e..5a8d2c8 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -167,13 +167,6 @@
     public static final int FX_SURFACE_DIM = 0x00020000;
 
     /**
-     * Surface creation flag: Creates a video plane Surface.
-     * This surface is backed by a hardware video plane. It is an error to lock
-     * a video plane surface, since it doesn't have a backing store.
-     */
-    public static final int FX_SURFACE_VIDEO_PLANE = 0x00040000;
-
-    /**
      * Mask used for FX values above.
      *
      */
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index 1f211c2..23123dd 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -422,10 +422,7 @@
         mWindowType = type;
     }
 
-    /**
-     * @hide
-     */
-    protected void updateWindow(boolean force, boolean redrawNeeded) {
+    private void updateWindow(boolean force, boolean redrawNeeded) {
         if (!mHaveFrame) {
             return;
         }
diff --git a/core/java/android/view/VideoPlaneView.java b/core/java/android/view/VideoPlaneView.java
deleted file mode 100644
index 81dcf9d..0000000
--- a/core/java/android/view/VideoPlaneView.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package android.view;
-
-import android.content.Context;
-import android.util.AttributeSet;
-
-/**
- * Provides a dedicated surface embedded inside of a view hierarchy much like a
- * {@link SurfaceView}, but the surface is actually backed by a hardware video
- * plane.
- *
- * TODO: Eventually this should be separate from SurfaceView.
- *
- * @hide
- */
-public class VideoPlaneView extends SurfaceView {
-    public VideoPlaneView(Context context) {
-        super(context);
-    }
-
-    public VideoPlaneView(Context context, AttributeSet attrs) {
-        super(context, attrs);
-    }
-
-    public VideoPlaneView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
-    }
-
-    public VideoPlaneView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
-        super(context, attrs, defStyleAttr, defStyleRes);
-    }
-
-    @Override
-    protected void updateWindow(boolean force, boolean redrawNeeded) {
-        mLayout.privateFlags |= WindowManager.LayoutParams.PRIVATE_FLAG_VIDEO_PLANE;
-        super.updateWindow(force, redrawNeeded);
-    }
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index eff78d3..ecd73af 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2386,17 +2386,6 @@
      */
     static final int PFLAG3_FITTING_SYSTEM_WINDOWS = 0x80;
 
-    /**
-     * Flag indicating that an view will cast a shadow onto the Z=0 plane if elevated.
-     */
-    static final int PFLAG3_CASTS_SHADOW = 0x100;
-
-    /**
-     * Flag indicating that view will be transformed by the global camera if rotated in 3d, or given
-     * a non-0 Z translation.
-     */
-    static final int PFLAG3_USES_GLOBAL_CAMERA = 0x200;
-
     /* End of masks for mPrivateFlags3 */
 
     static final int DRAG_MASK = PFLAG2_DRAG_CAN_ACCEPT | PFLAG2_DRAG_HOVERED;
@@ -4039,11 +4028,6 @@
                 case R.styleable.View_layerType:
                     setLayerType(a.getInt(attr, LAYER_TYPE_NONE), null);
                     break;
-                case R.styleable.View_castsShadow:
-                    if (a.getBoolean(attr, false)) {
-                        mPrivateFlags3 |= PFLAG3_CASTS_SHADOW;
-                    }
-                    break;
                 case R.styleable.View_textDirection:
                     // Clear any text direction flag already set
                     mPrivateFlags2 &= ~PFLAG2_TEXT_DIRECTION_MASK;
@@ -10852,7 +10836,6 @@
      *
      * @param outline The new outline of the view. Must be non-null, and convex.
      *
-     * @see #setCastsShadow(boolean)
      * @see #getOutline(Path)
      * @see #getClipToOutline()
      * @see #setClipToOutline(boolean)
@@ -10916,95 +10899,6 @@
     }
 
     /**
-     * Returns whether the View will cast shadows when its
-     * {@link #setTranslationZ(float) z translation} is greater than 0, or it is
-     * rotated in 3D.
-     *
-     * @see #setTranslationZ(float)
-     * @see #setRotationX(float)
-     * @see #setRotationY(float)
-     * @see #setCastsShadow(boolean)
-     * @attr ref android.R.styleable#View_castsShadow
-     */
-    public final boolean getCastsShadow() {
-        return ((mPrivateFlags3 & PFLAG3_CASTS_SHADOW) != 0);
-    }
-
-    /**
-     * Set to true to enable this View to cast shadows.
-     * <p>
-     * If enabled, and the View has a z translation greater than 0, or is
-     * rotated in 3D, the shadow will be cast onto its parent at the z = 0
-     * plane.
-     * <p>
-     * The shape of the shadow being cast is defined by the
-     * {@link #setOutline(Path) outline} of the view, or the rectangular bounds
-     * of the view if the outline is not set or is empty.
-     *
-     * @see #setTranslationZ(float)
-     * @see #getCastsShadow()
-     * @attr ref android.R.styleable#View_castsShadow
-     */
-    public void setCastsShadow(boolean castsShadow) {
-        // TODO : Add a fast invalidation here.
-        if (getCastsShadow() != castsShadow) {
-            if (castsShadow) {
-                mPrivateFlags3 |= PFLAG3_CASTS_SHADOW;
-            } else {
-                mPrivateFlags3 &= ~PFLAG3_CASTS_SHADOW;
-            }
-            if (mDisplayList != null) {
-                mDisplayList.setCastsShadow(castsShadow);
-            }
-        }
-    }
-
-    /**
-     * Returns whether the View will be transformed by the global camera.
-     *
-     * @see #setUsesGlobalCamera(boolean)
-     *
-     * @hide
-     */
-    public final boolean getUsesGlobalCamera() {
-        return ((mPrivateFlags3 & PFLAG3_USES_GLOBAL_CAMERA) != 0);
-    }
-
-    /**
-     * Sets whether the View should be transformed by the global camera.
-     * <p>
-     * If the view has a Z translation or 3D rotation, perspective from the
-     * global camera will be applied. This enables an app to transform multiple
-     * views in 3D with coherent perspective projection among them all.
-     * <p>
-     * Setting this to true will cause {@link #setCameraDistance() camera distance}
-     * to be ignored, as the global camera's position will dictate perspective
-     * transform.
-     * <p>
-     * This should not be used in conjunction with {@link android.graphics.Camera}.
-     *
-     * @see #getUsesGlobalCamera()
-     * @see #setTranslationZ(float)
-     * @see #setRotationX(float)
-     * @see #setRotationY(float)
-     *
-     * @hide
-     */
-    public void setUsesGlobalCamera(boolean usesGlobalCamera) {
-        // TODO : Add a fast invalidation here.
-        if (getUsesGlobalCamera() != usesGlobalCamera) {
-            if (usesGlobalCamera) {
-                mPrivateFlags3 |= PFLAG3_USES_GLOBAL_CAMERA;
-            } else {
-                mPrivateFlags3 &= ~PFLAG3_USES_GLOBAL_CAMERA;
-            }
-            if (mDisplayList != null) {
-                mDisplayList.setUsesGlobalCamera(usesGlobalCamera);
-            }
-        }
-    }
-
-    /**
      * Hit rectangle in parent's coordinates
      *
      * @param outRect The hit rectangle of the view.
@@ -11567,7 +11461,7 @@
             }
 
             // Damage the entire IsolatedZVolume recieving this view's shadow.
-            if (getCastsShadow() && getTranslationZ() != 0) {
+            if (getTranslationZ() != 0) {
                 damageIsolatedZVolume();
             }
         }
@@ -11647,7 +11541,7 @@
         } else {
             damageInParent();
         }
-        if (invalidateParent && getCastsShadow() && getTranslationZ() != 0) {
+        if (invalidateParent && getTranslationZ() != 0) {
             damageIsolatedZVolume();
         }
     }
@@ -14685,8 +14579,6 @@
             }
             displayList.setOutline(mOutline);
             displayList.setClipToOutline(getClipToOutline());
-            displayList.setCastsShadow(getCastsShadow());
-            displayList.setUsesGlobalCamera(getUsesGlobalCamera());
             float alpha = 1;
             if (mParent instanceof ViewGroup && (((ViewGroup) mParent).mGroupFlags &
                     ViewGroup.FLAG_SUPPORT_STATIC_TRANSFORMATIONS) != 0) {
diff --git a/core/java/android/view/ViewConfiguration.java b/core/java/android/view/ViewConfiguration.java
index e67659c..5112b9a 100644
--- a/core/java/android/view/ViewConfiguration.java
+++ b/core/java/android/view/ViewConfiguration.java
@@ -80,7 +80,7 @@
      * is a tap or a scroll. If the user does not move within this interval, it is
      * considered to be a tap.
      */
-    private static final int TAP_TIMEOUT = 180;
+    private static final int TAP_TIMEOUT = 100;
 
     /**
      * Defines the duration in milliseconds we will wait to see if a touch event
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 55956bf..53a4c0d0 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -98,7 +98,7 @@
      * the given view hierarchy's {@link View#onDetachedFromWindow()
      * View.onDetachedFromWindow()} methods before returning.  This is not
      * for normal applications; using it correctly requires great care.
-     *
+     * 
      * @param view The view to be removed.
      */
     public void removeViewImmediate(View view);
@@ -112,7 +112,7 @@
          */
         @ViewDebug.ExportedProperty
         public int x;
-
+        
         /**
          * Y position for this window.  With the default gravity it is ignored.
          * When using {@link Gravity#TOP} or {@link Gravity#BOTTOM} it provides
@@ -161,7 +161,7 @@
          * be used by applications, and a special permission is required
          * to use them.
          * </ul>
-         *
+         * 
          * @see #TYPE_BASE_APPLICATION
          * @see #TYPE_APPLICATION
          * @see #TYPE_APPLICATION_STARTING
@@ -223,12 +223,12 @@
             @ViewDebug.IntToString(from = TYPE_PRIVATE_PRESENTATION, to = "TYPE_PRIVATE_PRESENTATION")
         })
         public int type;
-
+    
         /**
          * Start of window types that represent normal application windows.
          */
         public static final int FIRST_APPLICATION_WINDOW = 1;
-
+        
         /**
          * Window type: an application window that serves as the "base" window
          * of the overall application; all other application windows will
@@ -236,14 +236,14 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_BASE_APPLICATION   = 1;
-
+        
         /**
          * Window type: a normal application window.  The {@link #token} must be
          * an Activity token identifying who the window belongs to.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_APPLICATION        = 2;
-
+    
         /**
          * Window type: special application window that is displayed while the
          * application is starting.  Not for use by applications themselves;
@@ -252,12 +252,12 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_APPLICATION_STARTING = 3;
-
+    
         /**
          * End of types of application windows.
          */
         public static final int LAST_APPLICATION_WINDOW = 99;
-
+    
         /**
          * Start of types of sub-windows.  The {@link #token} of these windows
          * must be set to the window they are attached to.  These types of
@@ -265,19 +265,19 @@
          * coordinate space is relative to their attached window.
          */
         public static final int FIRST_SUB_WINDOW        = 1000;
-
+    
         /**
          * Window type: a panel on top of an application window.  These windows
          * appear on top of their attached window.
          */
         public static final int TYPE_APPLICATION_PANEL  = FIRST_SUB_WINDOW;
-
+    
         /**
          * Window type: window for showing media (such as video).  These windows
          * are displayed behind their attached window.
          */
         public static final int TYPE_APPLICATION_MEDIA  = FIRST_SUB_WINDOW+1;
-
+    
         /**
          * Window type: a sub-panel on top of an application window.  These
          * windows are displayed on top their attached window and any
@@ -290,7 +290,7 @@
          * as a child of its container.
          */
         public static final int TYPE_APPLICATION_ATTACHED_DIALOG = FIRST_SUB_WINDOW+3;
-
+        
         /**
          * Window type: window for showing overlays on top of media windows.
          * These windows are displayed between TYPE_APPLICATION_MEDIA and the
@@ -299,18 +299,18 @@
          * @hide
          */
         public static final int TYPE_APPLICATION_MEDIA_OVERLAY  = FIRST_SUB_WINDOW+4;
-
+    
         /**
          * End of types of sub-windows.
          */
         public static final int LAST_SUB_WINDOW         = 1999;
-
+        
         /**
          * Start of system-specific window types.  These are not normally
          * created by applications.
          */
         public static final int FIRST_SYSTEM_WINDOW     = 2000;
-
+    
         /**
          * Window type: the status bar.  There can be only one status bar
          * window; it is placed at the top of the screen, and all other
@@ -318,14 +318,14 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_STATUS_BAR         = FIRST_SYSTEM_WINDOW;
-
+    
         /**
          * Window type: the search bar.  There can be only one search bar
          * window; it is placed at the top of the screen.
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SEARCH_BAR         = FIRST_SYSTEM_WINDOW+1;
-
+    
         /**
          * Window type: phone.  These are non-application windows providing
          * user interaction with the phone (in particular incoming calls).
@@ -334,26 +334,26 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PHONE              = FIRST_SYSTEM_WINDOW+2;
-
+    
         /**
          * Window type: system window, such as low power alert. These windows
          * are always on top of application windows.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ALERT       = FIRST_SYSTEM_WINDOW+3;
-
+        
         /**
          * Window type: keyguard window.
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD           = FIRST_SYSTEM_WINDOW+4;
-
+        
         /**
          * Window type: transient notifications.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_TOAST              = FIRST_SYSTEM_WINDOW+5;
-
+        
         /**
          * Window type: system overlay windows, which need to be displayed
          * on top of everything else.  These windows must not take input
@@ -361,7 +361,7 @@
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_OVERLAY     = FIRST_SYSTEM_WINDOW+6;
-
+        
         /**
          * Window type: priority phone UI, which needs to be displayed even if
          * the keyguard is active.  These windows must not take input
@@ -369,26 +369,26 @@
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_PRIORITY_PHONE     = FIRST_SYSTEM_WINDOW+7;
-
+        
         /**
          * Window type: panel that slides out from the status bar
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_SYSTEM_DIALOG      = FIRST_SYSTEM_WINDOW+8;
-
+    
         /**
          * Window type: dialogs that the keyguard shows
          * In multiuser systems shows on all users' windows.
          */
         public static final int TYPE_KEYGUARD_DIALOG    = FIRST_SYSTEM_WINDOW+9;
-
+        
         /**
          * Window type: internal system error windows, appear on top of
          * everything they can.
          * In multiuser systems shows only on the owning user's window.
          */
         public static final int TYPE_SYSTEM_ERROR       = FIRST_SYSTEM_WINDOW+10;
-
+        
         /**
          * Window type: internal input methods windows, which appear above
          * the normal UI.  Application windows may be resized or panned to keep
@@ -559,16 +559,16 @@
         /** @deprecated this is ignored, this value is set automatically when needed. */
         @Deprecated
         public static final int MEMORY_TYPE_PUSH_BUFFERS = 3;
-
+        
         /**
          * @deprecated this is ignored
          */
         @Deprecated
         public int memoryType;
-
+        
         /** Window flag: as long as this window is visible to the user, allow
-         *  the lock screen to activate while the screen is on.
-         *  This can be used independently, or in combination with
+         *  the lock screen to activate while the screen is on. 
+         *  This can be used independently, or in combination with 
          *  {@link #FLAG_KEEP_SCREEN_ON} and/or {@link #FLAG_SHOW_WHEN_LOCKED} */
         public static final int FLAG_ALLOW_LOCK_WHILE_SCREEN_ON     = 0x00000001;
 
@@ -586,47 +586,47 @@
          * instead go to whatever focusable window is behind it.  This flag
          * will also enable {@link #FLAG_NOT_TOUCH_MODAL} whether or not that
          * is explicitly set.
-         *
+         * 
          * <p>Setting this flag also implies that the window will not need to
          * interact with
-         * a soft input method, so it will be Z-ordered and positioned
+         * a soft input method, so it will be Z-ordered and positioned 
          * independently of any active input method (typically this means it
          * gets Z-ordered on top of the input method, so it can use the full
          * screen for its content and cover the input method if needed.  You
          * can use {@link #FLAG_ALT_FOCUSABLE_IM} to modify this behavior. */
         public static final int FLAG_NOT_FOCUSABLE      = 0x00000008;
-
+        
         /** Window flag: this window can never receive touch events. */
         public static final int FLAG_NOT_TOUCHABLE      = 0x00000010;
-
+        
         /** Window flag: even when this window is focusable (its
          * {@link #FLAG_NOT_FOCUSABLE} is not set), allow any pointer events
          * outside of the window to be sent to the windows behind it.  Otherwise
          * it will consume all pointer events itself, regardless of whether they
          * are inside of the window. */
         public static final int FLAG_NOT_TOUCH_MODAL    = 0x00000020;
-
+        
         /** Window flag: when set, if the device is asleep when the touch
          * screen is pressed, you will receive this first touch event.  Usually
          * the first touch event is consumed by the system since the user can
          * not see what they are pressing on.
          */
         public static final int FLAG_TOUCHABLE_WHEN_WAKING = 0x00000040;
-
+        
         /** Window flag: as long as this window is visible to the user, keep
          *  the device's screen turned on and bright. */
         public static final int FLAG_KEEP_SCREEN_ON     = 0x00000080;
-
+        
         /** Window flag: place the window within the entire screen, ignoring
          *  decorations around the border (such as the status bar).  The
          *  window must correctly position its contents to take the screen
          *  decoration into account.  This flag is normally set for you
          *  by Window as described in {@link Window#setFlags}. */
         public static final int FLAG_LAYOUT_IN_SCREEN   = 0x00000100;
-
+        
         /** Window flag: allow window to extend outside of the screen. */
         public static final int FLAG_LAYOUT_NO_LIMITS   = 0x00000200;
-
+        
         /**
          * Window flag: hide all screen decorations (such as the status bar) while
          * this window is displayed.  This allows the window to use the entire
@@ -648,17 +648,17 @@
          * {@link android.R.style#Theme_DeviceDefault_Light_NoActionBar_Fullscreen}.</p>
          */
         public static final int FLAG_FULLSCREEN      = 0x00000400;
-
+        
         /** Window flag: override {@link #FLAG_FULLSCREEN} and force the
          *  screen decorations (such as the status bar) to be shown. */
         public static final int FLAG_FORCE_NOT_FULLSCREEN   = 0x00000800;
-
+        
         /** Window flag: turn on dithering when compositing this window to
          *  the screen.
          * @deprecated This flag is no longer used. */
         @Deprecated
         public static final int FLAG_DITHER             = 0x00001000;
-
+        
         /** Window flag: treat the content of the window as secure, preventing
          * it from appearing in screenshots or from being viewed on non-secure
          * displays.
@@ -667,21 +667,21 @@
          * secure surfaces and secure displays.
          */
         public static final int FLAG_SECURE             = 0x00002000;
-
+        
         /** Window flag: a special mode where the layout parameters are used
          * to perform scaling of the surface when it is composited to the
          * screen. */
         public static final int FLAG_SCALED             = 0x00004000;
-
+        
         /** Window flag: intended for windows that will often be used when the user is
          * holding the screen against their face, it will aggressively filter the event
          * stream to prevent unintended presses in this situation that may not be
-         * desired for a particular window, when such an event stream is detected, the
+         * desired for a particular window, when such an event stream is detected, the 
          * application will receive a CANCEL motion event to indicate this so applications
-         * can handle this accordingly by taking no action on the event
+         * can handle this accordingly by taking no action on the event 
          * until the finger is released. */
         public static final int FLAG_IGNORE_CHEEK_PRESSES    = 0x00008000;
-
+        
         /** Window flag: a special option only for use in combination with
          * {@link #FLAG_LAYOUT_IN_SCREEN}.  When requesting layout in the
          * screen your window may appear on top of or behind screen decorations
@@ -690,7 +690,7 @@
          * content is not covered by screen decorations.  This flag is normally
          * set for you by Window as described in {@link Window#setFlags}.*/
         public static final int FLAG_LAYOUT_INSET_DECOR = 0x00010000;
-
+        
         /** Window flag: invert the state of {@link #FLAG_NOT_FOCUSABLE} with
          * respect to how this window interacts with the current method.  That
          * is, if FLAG_NOT_FOCUSABLE is set and this flag is set, then the
@@ -701,7 +701,7 @@
          * to use more space and cover the input method.
          */
         public static final int FLAG_ALT_FOCUSABLE_IM = 0x00020000;
-
+        
         /** Window flag: if you have set {@link #FLAG_NOT_TOUCH_MODAL}, you
          * can set this flag to receive a single special MotionEvent with
          * the action
@@ -711,7 +711,7 @@
          * first down as an ACTION_OUTSIDE.
          */
         public static final int FLAG_WATCH_OUTSIDE_TOUCH = 0x00040000;
-
+        
         /** Window flag: special flag to let windows be shown when the screen
          * is locked. This will let application windows take precedence over
          * key guard or any other lock screens. Can be used with
@@ -741,13 +741,13 @@
          * {@link android.R.style#Theme_DeviceDefault_Wallpaper_NoTitleBar}.</p>
          */
         public static final int FLAG_SHOW_WALLPAPER = 0x00100000;
-
+        
         /** Window flag: when set as a window is being added or made
          * visible, once the window has been shown then the system will
          * poke the power manager's user activity (as if the user had woken
          * up the device) to turn the screen on. */
         public static final int FLAG_TURN_SCREEN_ON = 0x00200000;
-
+        
         /** Window flag: when set the window will cause the keyguard to
          * be dismissed, only if it is not a secure lock keyguard.  Because such
          * a keyguard is not needed for security, it will never re-appear if
@@ -761,7 +761,7 @@
          * also been set.
          */
         public static final int FLAG_DISMISS_KEYGUARD = 0x00400000;
-
+        
         /** Window flag: when set the window will accept for touch events
          * outside of its bounds to be sent to other windows that also
          * support split touch.  When this flag is not set, the first pointer
@@ -773,7 +773,7 @@
          * to be split across multiple windows.
          */
         public static final int FLAG_SPLIT_TOUCH = 0x00800000;
-
+        
         /**
          * <p>Indicates whether this window should be hardware accelerated.
          * Requesting hardware acceleration does not guarantee it will happen.</p>
@@ -916,7 +916,7 @@
 
         /**
          * Various behavioral options/flags.  Default is none.
-         *
+         * 
          * @see #FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
          * @see #FLAG_DIM_BEHIND
          * @see #FLAG_NOT_FOCUSABLE
@@ -1014,10 +1014,10 @@
          * as if it was.
          * Like {@link #FLAG_HARDWARE_ACCELERATED} except for trusted system windows
          * that need hardware acceleration (e.g. LockScreen), where hardware acceleration
-         * is generally disabled. This flag must be specified in addition to
+         * is generally disabled. This flag must be specified in addition to 
          * {@link #FLAG_HARDWARE_ACCELERATED} to enable hardware acceleration for system
          * windows.
-         *
+         * 
          * @hide
          */
         public static final int PRIVATE_FLAG_FAKE_HARDWARE_ACCELERATED = 0x00000001;
@@ -1028,7 +1028,7 @@
          * If certain parts of the UI that really do want to use hardware
          * acceleration, this flag can be set to force it.  This is basically
          * for the lock screen.  Anyone else using it, you are probably wrong.
-         *
+         * 
          * @hide
          */
         public static final int PRIVATE_FLAG_FORCE_HARDWARE_ACCELERATED = 0x00000002;
@@ -1086,11 +1086,6 @@
          * {@hide} */
         public static final int PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR = 0x00000200;
 
-        /** Window flag: the window is backed by a video plane, instead of a
-         * regular surface.
-         * {@hide} */
-        public static final int PRIVATE_FLAG_VIDEO_PLANE = 0x00000400;
-
         /**
          * Control flags that are private to the platform.
          * @hide
@@ -1105,9 +1100,9 @@
          * flags and returns true if the combination of the two corresponds
          * to a window that needs to be behind the input method so that the
          * user can type into it.
-         *
+         * 
          * @param flags The current window manager flags.
-         *
+         * 
          * @return Returns true if such a window should be behind/interact
          * with an input method, false if not.
          */
@@ -1119,63 +1114,63 @@
             }
             return false;
         }
-
+        
         /**
          * Mask for {@link #softInputMode} of the bits that determine the
          * desired visibility state of the soft input area for this window.
          */
         public static final int SOFT_INPUT_MASK_STATE = 0x0f;
-
+        
         /**
          * Visibility state for {@link #softInputMode}: no state has been specified.
          */
         public static final int SOFT_INPUT_STATE_UNSPECIFIED = 0;
-
+        
         /**
          * Visibility state for {@link #softInputMode}: please don't change the state of
          * the soft input area.
          */
         public static final int SOFT_INPUT_STATE_UNCHANGED = 1;
-
+        
         /**
          * Visibility state for {@link #softInputMode}: please hide any soft input
          * area when normally appropriate (when the user is navigating
          * forward to your window).
          */
         public static final int SOFT_INPUT_STATE_HIDDEN = 2;
-
+        
         /**
          * Visibility state for {@link #softInputMode}: please always hide any
          * soft input area when this window receives focus.
          */
         public static final int SOFT_INPUT_STATE_ALWAYS_HIDDEN = 3;
-
+        
         /**
          * Visibility state for {@link #softInputMode}: please show the soft
          * input area when normally appropriate (when the user is navigating
          * forward to your window).
          */
         public static final int SOFT_INPUT_STATE_VISIBLE = 4;
-
+        
         /**
          * Visibility state for {@link #softInputMode}: please always make the
          * soft input area visible when this window receives input focus.
          */
         public static final int SOFT_INPUT_STATE_ALWAYS_VISIBLE = 5;
-
+        
         /**
          * Mask for {@link #softInputMode} of the bits that determine the
          * way that the window should be adjusted to accommodate the soft
          * input window.
          */
         public static final int SOFT_INPUT_MASK_ADJUST = 0xf0;
-
+        
         /** Adjustment option for {@link #softInputMode}: nothing specified.
          * The system will try to pick one or
          * the other depending on the contents of the window.
          */
         public static final int SOFT_INPUT_ADJUST_UNSPECIFIED = 0x00;
-
+        
         /** Adjustment option for {@link #softInputMode}: set to allow the
          * window to be resized when an input
          * method is shown, so that its contents are not covered by the input
@@ -1188,7 +1183,7 @@
          * not resize, but will stay fullscreen.
          */
         public static final int SOFT_INPUT_ADJUST_RESIZE = 0x10;
-
+        
         /** Adjustment option for {@link #softInputMode}: set to have a window
          * pan when an input method is
          * shown, so it doesn't need to deal with resizing but just panned
@@ -1198,7 +1193,7 @@
          * the other depending on the contents of the window.
          */
         public static final int SOFT_INPUT_ADJUST_PAN = 0x20;
-
+        
         /** Adjustment option for {@link #softInputMode}: set to have a window
          * not adjust for a shown input method.  The window will not be resized,
          * and it will not be panned to make its focus visible.
@@ -1217,7 +1212,7 @@
         /**
          * Desired operating mode for any soft input area.  May be any combination
          * of:
-         *
+         * 
          * <ul>
          * <li> One of the visibility states
          * {@link #SOFT_INPUT_STATE_UNSPECIFIED}, {@link #SOFT_INPUT_STATE_UNCHANGED},
@@ -1234,7 +1229,7 @@
          * {@link android.R.attr#windowSoftInputMode} attribute.</p>
          */
         public int softInputMode;
-
+        
         /**
          * Placement of window within the screen as per {@link Gravity}.  Both
          * {@link Gravity#apply(int, int, int, android.graphics.Rect, int, int,
@@ -1251,7 +1246,7 @@
          * @see Gravity
          */
         public int gravity;
-
+    
         /**
          * The horizontal margin, as a percentage of the container's width,
          * between the container and the widget.  See
@@ -1260,7 +1255,7 @@
          * field is added with {@link #x} to supply the <var>xAdj</var> parameter.
          */
         public float horizontalMargin;
-
+    
         /**
          * The vertical margin, as a percentage of the container's height,
          * between the container and the widget.  See
@@ -1269,26 +1264,26 @@
          * field is added with {@link #y} to supply the <var>yAdj</var> parameter.
          */
         public float verticalMargin;
-
+    
         /**
          * The desired bitmap format.  May be one of the constants in
          * {@link android.graphics.PixelFormat}.  Default is OPAQUE.
          */
         public int format;
-
+    
         /**
          * A style resource defining the animations to use for this window.
          * This must be a system resource; it can not be an application resource
          * because the window manager does not have access to applications.
          */
         public int windowAnimations;
-
+    
         /**
          * An alpha value to apply to this entire window.
          * An alpha of 1.0 means fully opaque and 0.0 means fully transparent
          */
         public float alpha = 1.0f;
-
+    
         /**
          * When {@link #FLAG_DIM_BEHIND} is set, this is the amount of dimming
          * to apply.  Range is from 1.0 for completely opaque to 0.0 for no
@@ -1316,7 +1311,7 @@
          * to the hightest value when this window is in front.
          */
         public static final float BRIGHTNESS_OVERRIDE_FULL = 1.0f;
-
+    
         /**
          * This can be used to override the user's preferred brightness of
          * the screen.  A value of less than 0, the default, means to use the
@@ -1324,7 +1319,7 @@
          * dark to full bright.
          */
         public float screenBrightness = BRIGHTNESS_OVERRIDE_NONE;
-
+        
         /**
          * This can be used to override the standard behavior of the button and
          * keyboard backlights.  A value of less than 0, the default, means to
@@ -1358,7 +1353,7 @@
          * opaque windows have the #FLAG_FULLSCREEN bit set and are not covered
          * by other windows. All other situations default to the
          * {@link #ROTATION_ANIMATION_ROTATE} behavior.
-         *
+         * 
          * @see #ROTATION_ANIMATION_ROTATE
          * @see #ROTATION_ANIMATION_CROSSFADE
          * @see #ROTATION_ANIMATION_JUMPCUT
@@ -1370,18 +1365,18 @@
          * you.
          */
         public IBinder token = null;
-
+    
         /**
          * Name of the package owning this window.
          */
         public String packageName = null;
-
+        
         /**
          * Specific orientation value for a window.
          * May be any of the same values allowed
-         * for {@link android.content.pm.ActivityInfo#screenOrientation}.
-         * If not set, a default value of
-         * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED}
+         * for {@link android.content.pm.ActivityInfo#screenOrientation}. 
+         * If not set, a default value of 
+         * {@link android.content.pm.ActivityInfo#SCREEN_ORIENTATION_UNSPECIFIED} 
          * will be used.
          */
         public int screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
@@ -1403,7 +1398,7 @@
 
         /**
          * Get callbacks about the system ui visibility changing.
-         *
+         * 
          * TODO: Maybe there should be a bitfield of optional callbacks that we need.
          *
          * @hide
@@ -1469,34 +1464,34 @@
             type = TYPE_APPLICATION;
             format = PixelFormat.OPAQUE;
         }
-
+        
         public LayoutParams(int _type) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             format = PixelFormat.OPAQUE;
         }
-
+    
         public LayoutParams(int _type, int _flags) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             flags = _flags;
             format = PixelFormat.OPAQUE;
         }
-
+    
         public LayoutParams(int _type, int _flags, int _format) {
             super(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
             type = _type;
             flags = _flags;
             format = _format;
         }
-
+        
         public LayoutParams(int w, int h, int _type, int _flags, int _format) {
             super(w, h);
             type = _type;
             flags = _flags;
             format = _format;
         }
-
+        
         public LayoutParams(int w, int h, int xpos, int ypos, int _type,
                 int _flags, int _format) {
             super(w, h);
@@ -1506,18 +1501,18 @@
             flags = _flags;
             format = _format;
         }
-
+    
         public final void setTitle(CharSequence title) {
             if (null == title)
                 title = "";
-
+    
             mTitle = TextUtils.stringOrSpannedString(title);
         }
-
+    
         public final CharSequence getTitle() {
             return mTitle;
         }
-
+    
         public int describeContents() {
             return 0;
         }
@@ -1551,19 +1546,19 @@
             out.writeInt(inputFeatures);
             out.writeLong(userActivityTimeout);
         }
-
+        
         public static final Parcelable.Creator<LayoutParams> CREATOR
                     = new Parcelable.Creator<LayoutParams>() {
             public LayoutParams createFromParcel(Parcel in) {
                 return new LayoutParams(in);
             }
-
+    
             public LayoutParams[] newArray(int size) {
                 return new LayoutParams[size];
             }
         };
-
-
+    
+    
         public LayoutParams(Parcel in) {
             width = in.readInt();
             height = in.readInt();
@@ -1593,7 +1588,7 @@
             inputFeatures = in.readInt();
             userActivityTimeout = in.readLong();
         }
-
+    
         @SuppressWarnings({"PointlessBitwiseExpression"})
         public static final int LAYOUT_CHANGED = 1<<0;
         public static final int TYPE_CHANGED = 1<<1;
@@ -1627,10 +1622,10 @@
 
         // internal buffer to backup/restore parameters under compatibility mode.
         private int[] mCompatibilityParamsBackup = null;
-
+        
         public final int copyFrom(LayoutParams o) {
             int changes = 0;
-
+    
             if (width != o.width) {
                 width = o.width;
                 changes |= LAYOUT_CHANGED;
@@ -1729,7 +1724,7 @@
                 rotationAnimation = o.rotationAnimation;
                 changes |= ROTATION_ANIMATION_CHANGED;
             }
-
+    
             if (screenOrientation != o.screenOrientation) {
                 screenOrientation = o.screenOrientation;
                 changes |= SCREEN_ORIENTATION_CHANGED;
@@ -1759,7 +1754,7 @@
 
             return changes;
         }
-
+    
         @Override
         public String debug(String output) {
             output += "Contents of " + this + ":";
@@ -1770,7 +1765,7 @@
             Log.d("Debug", "WindowManager.LayoutParams={title=" + mTitle + "}");
             return "";
         }
-
+    
         @Override
         public String toString() {
             StringBuilder sb = new StringBuilder(256);
diff --git a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
index da8f083..2cb1015 100644
--- a/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
+++ b/core/jni/android/graphics/CreateJavaOutputStreamAdaptor.cpp
@@ -63,9 +63,14 @@
         size_t bytesRead = 0;
         // read the bytes
         do {
-            size_t requested = size;
-            if (requested > fCapacity)
+            jint requested = 0;
+            if (size > static_cast<size_t>(fCapacity)) {
                 requested = fCapacity;
+            } else {
+                // This is safe because requested is clamped to (jint)
+                // fCapacity.
+                requested = static_cast<jint>(size);
+            }
 
             jint n = env->CallIntMethod(fJavaInputStream,
                                         gInputStream_readMethodID, fJavaByteArray, 0, requested);
@@ -120,7 +125,7 @@
     JNIEnv*     fEnv;
     jobject     fJavaInputStream;   // the caller owns this object
     jbyteArray  fJavaByteArray;     // the caller owns this object
-    size_t      fCapacity;
+    jint        fCapacity;
     size_t      fBytesRead;
     bool        fIsAtEnd;
 };
@@ -174,14 +179,18 @@
         fCapacity = env->GetArrayLength(storage);
     }
 
-	virtual bool write(const void* buffer, size_t size) {
+    virtual bool write(const void* buffer, size_t size) {
         JNIEnv* env = fEnv;
         jbyteArray storage = fJavaByteArray;
 
         while (size > 0) {
-            size_t requested = size;
-            if (requested > fCapacity) {
+            jint requested = 0;
+            if (size > static_cast<size_t>(fCapacity)) {
                 requested = fCapacity;
+            } else {
+                // This is safe because requested is clamped to (jint)
+                // fCapacity.
+                requested = static_cast<jint>(size);
             }
 
             env->SetByteArrayRegion(storage, 0, requested,
@@ -216,7 +225,7 @@
     JNIEnv*     fEnv;
     jobject     fJavaOutputStream;  // the caller owns this object
     jbyteArray  fJavaByteArray;     // the caller owns this object
-    size_t      fCapacity;
+    jint        fCapacity;
 };
 
 SkWStream* CreateJavaOutputStreamAdaptor(JNIEnv* env, jobject stream,
diff --git a/core/jni/android/graphics/Paint.cpp b/core/jni/android/graphics/Paint.cpp
index 189fe47..51990d5 100644
--- a/core/jni/android/graphics/Paint.cpp
+++ b/core/jni/android/graphics/Paint.cpp
@@ -615,7 +615,7 @@
                 return 0;
             }
         }
-        jfloat advancesArray[count];
+        jfloat* advancesArray = new jfloat[count];
         jfloat totalAdvance = 0;
 
         TextLayout::getTextRunAdvances(paint, text, start, count, contextCount, flags,
@@ -624,6 +624,7 @@
         if (advances != NULL) {
             env->SetFloatArrayRegion(advances, advancesIndex, count, advancesArray);
         }
+        delete [] advancesArray;
         return totalAdvance;
     }
 
diff --git a/core/jni/android_hardware_camera2_CameraMetadata.cpp b/core/jni/android_hardware_camera2_CameraMetadata.cpp
index 8c15ac2..957f95c 100644
--- a/core/jni/android_hardware_camera2_CameraMetadata.cpp
+++ b/core/jni/android_hardware_camera2_CameraMetadata.cpp
@@ -579,9 +579,14 @@
     sp<VendorTagDescriptor> desc;
     err = cameraService->getCameraVendorTagDescriptor(/*out*/desc);
 
-    if (err != OK) {
-        ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)", __FUNCTION__,
-                strerror(-err), err);
+    if (err == -EOPNOTSUPP) {
+        ALOGW("%s: Camera HAL too old; does not support vendor tags", __FUNCTION__);
+        VendorTagDescriptor::clearGlobalVendorTagDescriptor();
+
+        return OK;
+    } else if (err != OK) {
+        ALOGE("%s: Failed to setup vendor tag descriptors, received error %s (%d)",
+                __FUNCTION__, strerror(-err), err);
         return err;
     }
 
diff --git a/core/jni/android_view_RenderNode.cpp b/core/jni/android_view_RenderNode.cpp
index 2f69b8b..823f8d7 100644
--- a/core/jni/android_view_RenderNode.cpp
+++ b/core/jni/android_view_RenderNode.cpp
@@ -128,18 +128,6 @@
     displayList->properties().setClipToOutline(clipToOutline);
 }
 
-static void android_view_RenderNode_setCastsShadow(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean castsShadow) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->properties().setCastsShadow(castsShadow);
-}
-
-static void android_view_RenderNode_setUsesGlobalCamera(JNIEnv* env,
-        jobject clazz, jlong displayListPtr, jboolean usesGlobalCamera) {
-    RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
-    displayList->properties().setUsesGlobalCamera(usesGlobalCamera);
-}
-
 static void android_view_RenderNode_setAlpha(JNIEnv* env,
         jobject clazz, jlong displayListPtr, float alpha) {
     RenderNode* displayList = reinterpret_cast<RenderNode*>(displayListPtr);
@@ -398,8 +386,6 @@
     { "nSetProjectionReceiver","(JZ)V",  (void*) android_view_RenderNode_setProjectionReceiver },
     { "nSetOutline",           "(JJ)V",  (void*) android_view_RenderNode_setOutline },
     { "nSetClipToOutline",     "(JZ)V",  (void*) android_view_RenderNode_setClipToOutline },
-    { "nSetCastsShadow",       "(JZ)V",  (void*) android_view_RenderNode_setCastsShadow },
-    { "nSetUsesGlobalCamera",  "(JZ)V",  (void*) android_view_RenderNode_setUsesGlobalCamera },
     { "nSetAlpha",             "(JF)V",  (void*) android_view_RenderNode_setAlpha },
     { "nSetHasOverlappingRendering", "(JZ)V",
             (void*) android_view_RenderNode_setHasOverlappingRendering },
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 2043960..8482fdb 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2132,10 +2132,6 @@
         <!-- scale of the view in the y direction. -->
         <attr name="scaleY" format="float" />
 
-        <!-- Defines whether the View casts a shadow when it has a 3D rotation or Z
-             translation.-->
-        <attr name="castsShadow" format="boolean" />
-
         <!-- Determines which side the vertical scroll bar should be placed on. -->
         <attr name="verticalScrollbarPosition">
             <!-- Place the scroll bar wherever the system default determines. -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 25c8baa..404b852 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -2111,7 +2111,6 @@
   <public type="attr" name="controlY2" />
   <public type="attr" name="sharedElementName" />
   <public type="attr" name="transitionGroup" />
-  <public type="attr" name="castsShadow" />
   <public type="attr" name="requiredForProfile"/>
   <public type="attr" name="pinned" />
 
diff --git a/docs/html/sdk/index.jd b/docs/html/sdk/index.jd
index bc793f1..7b3d120 100644
--- a/docs/html/sdk/index.jd
+++ b/docs/html/sdk/index.jd
@@ -5,43 +5,43 @@
 page.metaDescription=Download the official Android SDK to develop apps for Android-powered devices.
 
 
-sdk.linux32_bundle_download=adt-bundle-linux-x86-20131030.zip
-sdk.linux32_bundle_bytes=496876498
-sdk.linux32_bundle_checksum=d389139ad9f59a43bdd34c94bc850509
+sdk.linux32_bundle_download=adt-bundle-linux-x86-20140311.zip
+sdk.linux32_bundle_bytes=527970712
+sdk.linux32_bundle_checksum=ad97a54f7e0d84d7d7fe86b56307009f
 
-sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20131030.zip
-sdk.linux64_bundle_bytes=497171697
-sdk.linux64_bundle_checksum=99b51a4f0526434b083701a896550b72
+sdk.linux64_bundle_download=adt-bundle-linux-x86_64-20140311.zip
+sdk.linux64_bundle_bytes=528184435
+sdk.linux64_bundle_checksum=f60c023d574565fea7a52b42c69ae76b
 
-sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20131030.zip
-sdk.mac64_bundle_bytes=470386961
-sdk.mac64_bundle_checksum=3e80e7a92b549029d91bdcf2ae82657f
+sdk.mac64_bundle_download=adt-bundle-mac-x86_64-20140311.zip
+sdk.mac64_bundle_bytes=501954506
+sdk.mac64_bundle_checksum=9569251f3403c0f6c22b6caa1d672112
 
-sdk.win32_bundle_download=adt-bundle-windows-x86-20131030.zip
-sdk.win32_bundle_bytes=503599460
-sdk.win32_bundle_checksum=cd490a531ec24667354f6473e999b988
+sdk.win32_bundle_download=adt-bundle-windows-x86-20140311.zip
+sdk.win32_bundle_bytes=535083737
+sdk.win32_bundle_checksum=b2aabf536ddc4ea5cbb24e0752a832d8
 
-sdk.win64_bundle_download=adt-bundle-windows-x86_64-20131030.zip
-sdk.win64_bundle_bytes=503735416
-sdk.win64_bundle_checksum=ddddbb1b9028015779d68dde01f96b14
+sdk.win64_bundle_download=adt-bundle-windows-x86_64-20140311.zip
+sdk.win64_bundle_bytes=535284227
+sdk.win64_bundle_checksum=eee71e07dcfd538db57e9d76349efb98
 
 
 
-sdk.linux_download=android-sdk_r22.6-linux.tgz
-sdk.linux_bytes=100992666
-sdk.linux_checksum=dde27b72715e52693c1ebc908742fc40
+sdk.linux_download=android-sdk_r22.6.1-linux.tgz
+sdk.linux_bytes=101052129
+sdk.linux_checksum=d95b400600e9b68ed7719e0fd1792e0b
 
-sdk.mac_download=android-sdk_r22.6-macosx.zip
-sdk.mac_bytes=74547402
-sdk.mac_checksum=10c0e2ab65444c4911d69356ca2343f5
+sdk.mac_download=android-sdk_r22.6.1-macosx.zip
+sdk.mac_bytes=74639176
+sdk.mac_checksum=99abc850398ccc220e3a1d6d0ab73ccf
 
-sdk.win_download=android-sdk_r22.6-windows.zip
-sdk.win_bytes=108862292
-sdk.win_checksum=6faa487d328be352a456c53d9cbf0e3d
+sdk.win_download=android-sdk_r22.6.1-windows.zip
+sdk.win_bytes=108914728
+sdk.win_checksum=88471340a8c99822ffb5efbe3c28167c
 
-sdk.win_installer=installer_r22.6-windows.exe
-sdk.win_installer_bytes=88856450
-sdk.win_installer_checksum=6e5351b414bd554f3ac4c79f9dd4d213
+sdk.win_installer=installer_r22.6.1-windows.exe
+sdk.win_installer_bytes=88907175
+sdk.win_installer_checksum=fd664527ed1b1b1bfe2d4546cafc7ada
 
 
 
diff --git a/docs/html/sdk/installing/installing-adt.jd b/docs/html/sdk/installing/installing-adt.jd
index 42cb92c..2767d02 100644
--- a/docs/html/sdk/installing/installing-adt.jd
+++ b/docs/html/sdk/installing/installing-adt.jd
@@ -1,8 +1,8 @@
 page.title=Installing the Eclipse Plugin
-adt.zip.version=22.6.0
-adt.zip.download=ADT-22.6.0.zip
-adt.zip.bytes=14585211
-adt.zip.checksum=d95c6d8e678881f6c89f063b58d4162f
+adt.zip.version=22.6.1
+adt.zip.download=ADT-22.6.1.zip
+adt.zip.bytes=14586662
+adt.zip.checksum=c3cd19a1936ba0b850f74ef2b3a98b65
 
 @jd:body
 
diff --git a/docs/html/tools/sdk/eclipse-adt.jd b/docs/html/tools/sdk/eclipse-adt.jd
index d711e44..a821757 100644
--- a/docs/html/tools/sdk/eclipse-adt.jd
+++ b/docs/html/tools/sdk/eclipse-adt.jd
@@ -53,9 +53,59 @@
 <p>For a summary of all known issues in ADT, see <a
 href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
 
+
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>ADT 22.6.1</a> <em>(March 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+<dl>
+  <dt>Dependencies:</dt>
+
+  <dd>
+    <ul>
+      <li>Java 1.6 or higher is required.</li>
+      <li>Eclipse Indigo (Version 3.7.2) or higher is required.</li>
+      <li>This version of ADT is designed for use with
+        <a href="{@docRoot}tools/sdk/tools-notes.html">SDK Tools r22.6.1</a>.
+        If you haven't already installed SDK Tools r22.6.1 into your SDK, use the
+        Android SDK Manager to do so.</li>
+    </ul>
+  </dd>
+
+  <dt>General Notes:</dt>
+  <dd>
+    <ul>
+      <li>Fixed a problem where the Android Virtual Device Manager could not create new virtual
+          devices. (<a href="http://b.android.com/66661">Issue 66661</a>)</li>
+      <li><p>Fixed a problem with virtual devices created using ADT 22.3 or earlier.</p>
+          <p>If you created an Android Virtual Device using ADT 22.3 or earlier, the
+          AVD may be listed as <em>broken</em> in the AVD Manager in 22.6.1. To fix
+          this problem, select the virtual device on the AVD Manager and click
+          <strong>Repair</strong>.</p>
+      </li>
+      <li>Fixed a problem with the command line tools when creating virtual devices.
+          (<a href="http://b.android.com/66740">Issue 66740</a>)</li>
+      <li>Fixed a problem with the command line <code>lint</code> script.</li>
+    </ul>
+  </dd>
+
+  <dt>Known Issues:</dt>
+  <dd>
+    <p>When you create an Android virtual device using the Nexus 5 device definition,
+       you must enable the <em>Use Host GPU</em> option, otherwise the virtual device
+       will not start.</p>
+  </dd>
+</dl>
+</div>
+</div>
+
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 22.6.0</a> <em>(March 2014)</em>
   </p>
 
@@ -119,7 +169,7 @@
 
 <div class="toggle-content closed">
   <p><a href="#" onclick="return toggleContent(this)">
-    <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>ADT 22.3.0</a> <em>(October 2013)</em>
   </p>
 
diff --git a/docs/html/tools/sdk/tools-notes.jd b/docs/html/tools/sdk/tools-notes.jd
index 99f0b38..675cde3 100644
--- a/docs/html/tools/sdk/tools-notes.jd
+++ b/docs/html/tools/sdk/tools-notes.jd
@@ -25,10 +25,57 @@
 <p>For a summary of all known issues in SDK Tools, see <a
 href="http://tools.android.com/knownissues">http://tools.android.com/knownissues</a>.</p>
 
-
 <div class="toggle-content opened">
   <p><a href="#" onclick="return toggleContent(this)">
     <img src="{@docRoot}assets/images/triangle-opened.png" class="toggle-content-img"
+      alt=""/>SDK Tools, Revision 22.6.1</a> <em>(March 2014)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+
+    <dl>
+    <dt>Dependencies:</dt>
+
+    <dd>
+      <ul>
+        <li>Android SDK Platform-tools revision 18 or later.</li>
+        <li>If you are developing in Eclipse with ADT, note that this version of SDK Tools is
+          designed for use with ADT 22.6.1 and later. If you haven't already, update your
+        <a href="{@docRoot}tools/sdk/eclipse-adt.html">ADT Plugin</a> to 22.6.1.</li>
+        <li>If you are developing outside Eclipse, you must have
+          <a href="http://ant.apache.org/">Apache Ant</a> 1.8 or later.</li>
+      </ul>
+    </dd>
+
+    <dt>General Notes:</dt>
+    <dd>
+      <ul>
+        <li>Fixed a problem where the Android Virtual Device Manager could not create new virtual
+            devices. (<a href="http://b.android.com/66661">Issue 66661</a>)</li>
+        <li><p>Fixed a problem with virtual devices created using ADT 22.3 or earlier.</p>
+            <p>If you created an Android Virtual Device using ADT 22.3 or earlier, the
+            AVD may be listed as <em>broken</em> in the AVD Manager in 22.6.1. To fix
+            this problem, select the virtual device on the AVD Manager and click
+            <strong>Repair</strong>.</p>
+        </li>
+        <li>Fixed a problem with the command line tools when creating virtual devices.
+            (<a href="http://b.android.com/66740">Issue 66740</a>)</li>
+        <li>Fixed a problem with the command line <code>lint</code> script.</li>
+      </ul>
+    </dd>
+
+    <dt>Known Issues:</dt>
+    <dd>
+      <p>When you create an Android virtual device using the Nexus 5 device definition,
+         you must enable the <em>Use Host GPU</em> option, otherwise the virtual device
+         will not start.</p>
+    </dd>
+  </div>
+</div>
+
+<div class="toggle-content closed">
+  <p><a href="#" onclick="return toggleContent(this)">
+    <img src="{@docRoot}assets/images/triangle-closed.png" class="toggle-content-img"
       alt=""/>SDK Tools, Revision 22.6</a> <em>(March 2014)</em>
   </p>
 
diff --git a/graphics/java/android/graphics/Bitmap.java b/graphics/java/android/graphics/Bitmap.java
index 7676143..443e5dd 100644
--- a/graphics/java/android/graphics/Bitmap.java
+++ b/graphics/java/android/graphics/Bitmap.java
@@ -1052,7 +1052,7 @@
      * <p>This method will not affect the behavior of a bitmap without an alpha
      * channel, or if {@link #hasAlpha()} returns false.</p>
      *
-     * <p>Calling createBitmap() or createScaledBitmap() with a source
+     * <p>Calling {@link #createBitmap} or {@link #createScaledBitmap} with a source
      * Bitmap whose colors are not pre-multiplied may result in a RuntimeException,
      * since those functions require drawing the source, which is not supported for
      * un-pre-multiplied Bitmaps.</p>
diff --git a/libs/hwui/AmbientShadow.cpp b/libs/hwui/AmbientShadow.cpp
index 8327ef7..c0b5402 100644
--- a/libs/hwui/AmbientShadow.cpp
+++ b/libs/hwui/AmbientShadow.cpp
@@ -31,6 +31,7 @@
  * Calculate the shadows as a triangle strips while alpha value as the
  * shadow values.
  *
+ * @param isCasterOpaque Whether the caster is opaque.
  * @param vertices The shadow caster's polygon, which is represented in a Vector3
  *                  array.
  * @param vertexCount The length of caster's polygon in terms of number of
@@ -43,17 +44,18 @@
  * @param shadowVertexBuffer Return an floating point array of (x, y, a)
  *               triangle strips mode.
  */
-void AmbientShadow::createAmbientShadow(const Vector3* vertices, int vertexCount,
-        const Vector3& centroid3d, float heightFactor, float geomFactor,
-        VertexBuffer& shadowVertexBuffer) {
+VertexBufferMode AmbientShadow::createAmbientShadow(bool isCasterOpaque,
+        const Vector3* vertices, int vertexCount, const Vector3& centroid3d,
+        float heightFactor, float geomFactor, VertexBuffer& shadowVertexBuffer) {
     const int rays = SHADOW_RAY_COUNT;
+    VertexBufferMode mode = kVertexBufferMode_OnePolyRingShadow;
     // Validate the inputs.
     if (vertexCount < 3 || heightFactor <= 0 || rays <= 0
         || geomFactor <= 0) {
 #if DEBUG_SHADOW
-        ALOGE("Invalid input for createAmbientShadow(), early return!");
+        ALOGW("Invalid input for createAmbientShadow(), early return!");
 #endif
-        return;
+        return mode; // vertex buffer is empty, so any mode doesn't matter.
     }
 
     Vector<Vector2> dir; // TODO: use C++11 unique_ptr
@@ -75,7 +77,7 @@
         rayDist[i] = rayDistance;
         if (edgeIndex < 0 || edgeIndex >= vertexCount) {
 #if DEBUG_SHADOW
-            ALOGE("Invalid edgeIndex!");
+            ALOGW("Invalid edgeIndex!");
 #endif
             edgeIndex = 0;
         }
@@ -86,7 +88,8 @@
 
     // The output buffer length basically is roughly rays * layers, but since we
     // need triangle strips, so we need to duplicate vertices to accomplish that.
-    AlphaVertex* shadowVertices = shadowVertexBuffer.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
+    AlphaVertex* shadowVertices =
+            shadowVertexBuffer.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
 
     // Calculate the vertex of the shadows.
     //
@@ -95,6 +98,7 @@
     // calculate the normal N, which should be perpendicular to the edge of the
     // polygon (represented by the neighbor intersection points) .
     // Shadow's vertices will be generated as : P + N * scale.
+    const Vector2 centroid2d = Vector2(centroid3d.x, centroid3d.y);
     for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
         Vector2 normal(1.0f, 0.0f);
         calculateNormal(rays, rayIndex, dir.array(), rayDist, normal);
@@ -102,7 +106,7 @@
         // The vertex should be start from rayDist[i] then scale the
         // normalizeNormal!
         Vector2 intersection = dir[rayIndex] * rayDist[rayIndex] +
-                Vector2(centroid3d.x, centroid3d.y);
+                centroid2d;
 
         // outer ring of points, expanded based upon height of each ray intersection
         float expansionDist = rayHeight[rayIndex] * heightFactor *
@@ -114,25 +118,31 @@
 
         // inner ring of points
         float opacity = 1.0 / (1 + rayHeight[rayIndex] * heightFactor);
-        AlphaVertex::set(&shadowVertices[rayIndex + rays],
+        AlphaVertex::set(&shadowVertices[rays + rayIndex],
                 intersection.x,
                 intersection.y,
                 opacity);
     }
-    float centroidAlpha = 1.0 / (1 + centroid3d.z * heightFactor);
-    AlphaVertex::set(&shadowVertices[SHADOW_VERTEX_COUNT - 1],
-            centroid3d.x, centroid3d.y, centroidAlpha);
+
+    // If caster isn't opaque, we need to to fill the umbra by storing the umbra's
+    // centroid in the innermost ring of vertices.
+    if (!isCasterOpaque) {
+        mode = kVertexBufferMode_TwoPolyRingShadow;
+        float centroidAlpha = 1.0 / (1 + centroid3d.z * heightFactor);
+        AlphaVertex centroidXYA;
+        AlphaVertex::set(&centroidXYA, centroid2d.x, centroid2d.y, centroidAlpha);
+        for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
+            shadowVertices[2 * rays + rayIndex] = centroidXYA;
+        }
+    }
 
 #if DEBUG_SHADOW
-    if (currentVertexIndex != SHADOW_VERTEX_COUNT) {
-        ALOGE("number of vertex generated for ambient shadow is wrong! "
-              "current: %d , expected: %d", currentVertexIndex, SHADOW_VERTEX_COUNT);
-    }
     for (int i = 0; i < SHADOW_VERTEX_COUNT; i++) {
         ALOGD("ambient shadow value: i %d, (x:%f, y:%f, a:%f)", i, shadowVertices[i].x,
                 shadowVertices[i].y, shadowVertices[i].alpha);
     }
 #endif
+    return mode;
 }
 
 /**
diff --git a/libs/hwui/AmbientShadow.h b/libs/hwui/AmbientShadow.h
index 20d1384..45b8bef 100644
--- a/libs/hwui/AmbientShadow.h
+++ b/libs/hwui/AmbientShadow.h
@@ -19,6 +19,7 @@
 #define ANDROID_HWUI_AMBIENT_SHADOW_H
 
 #include "Debug.h"
+#include "OpenGLRenderer.h"
 #include "Vector.h"
 #include "VertexBuffer.h"
 
@@ -34,9 +35,9 @@
  */
 class AmbientShadow {
 public:
-    static void createAmbientShadow(const Vector3* poly, int polyLength,
-            const Vector3& centroid3d, float heightFactor, float geomFactor,
-            VertexBuffer& shadowVertexBuffer);
+    static VertexBufferMode createAmbientShadow(bool isCasterOpaque, const Vector3* poly,
+            int polyLength, const Vector3& centroid3d, float heightFactor,
+            float geomFactor, VertexBuffer& shadowVertexBuffer);
 
 private:
     static void calculateRayDirections(int rays, Vector2* dir);
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 2dfc873..477d691 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -445,11 +445,11 @@
 
 bool Caches::bindShadowIndicesBuffer() {
     if (!mShadowStripsIndices) {
-        uint16_t* shadowIndices = new uint16_t[SHADOW_INDEX_COUNT];
+        uint16_t* shadowIndices = new uint16_t[MAX_SHADOW_INDEX_COUNT];
         ShadowTessellator::generateShadowIndices(shadowIndices);
         glGenBuffers(1, &mShadowStripsIndices);
         bool force = bindIndicesBufferInternal(mShadowStripsIndices);
-        glBufferData(GL_ELEMENT_ARRAY_BUFFER, SHADOW_INDEX_COUNT * sizeof(uint16_t),
+        glBufferData(GL_ELEMENT_ARRAY_BUFFER, MAX_SHADOW_INDEX_COUNT * sizeof(uint16_t),
             shadowIndices, GL_STATIC_DRAW);
 
         delete[] shadowIndices;
diff --git a/libs/hwui/DisplayList.cpp b/libs/hwui/DisplayList.cpp
index 346fbce..f4de8ec 100644
--- a/libs/hwui/DisplayList.cpp
+++ b/libs/hwui/DisplayList.cpp
@@ -432,7 +432,7 @@
             // OR if its caster's Z value is similar to the previous potential caster
             if (shadowIndex == drawIndex || casterZ - lastCasterZ < SHADOW_DELTA) {
 
-                if (caster->properties().mCastsShadow && caster->properties().mAlpha > 0.0f) {
+                if (caster->properties().mAlpha > 0.0f) {
                     mat4 shadowMatrixXY(casterOp->mTransformFromParent);
                     caster->applyViewPropertyTransforms(shadowMatrixXY);
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 1475953..cb8155b 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -2414,9 +2414,12 @@
     if (mode == kVertexBufferMode_Standard) {
         mCaches.unbindIndicesBuffer();
         glDrawArrays(GL_TRIANGLE_STRIP, 0, vertexBuffer.getVertexCount());
-    } else {
+    } else if (mode == kVertexBufferMode_OnePolyRingShadow) {
         mCaches.bindShadowIndicesBuffer();
-        glDrawElements(GL_TRIANGLE_STRIP, SHADOW_INDEX_COUNT, GL_UNSIGNED_SHORT, 0);
+        glDrawElements(GL_TRIANGLE_STRIP, ONE_POLY_RING_SHADOW_INDEX_COUNT, GL_UNSIGNED_SHORT, 0);
+    } else if (mode == kVertexBufferMode_TwoPolyRingShadow) {
+        mCaches.bindShadowIndicesBuffer();
+        glDrawElements(GL_TRIANGLE_STRIP, TWO_POLY_RING_SHADOW_INDEX_COUNT, GL_UNSIGNED_SHORT, 0);
     }
 
     if (isAA) {
@@ -3245,14 +3248,15 @@
         }
         centroid3d.z += casterLift;
     }
-
+    bool isCasterOpaque = (casterAlpha == 1.0f);
     // draw caster's shadows
     if (mCaches.propertyAmbientShadowStrength > 0) {
         paint.setARGB(casterAlpha * mCaches.propertyAmbientShadowStrength, 0, 0, 0);
         VertexBuffer ambientShadowVertexBuffer;
-        ShadowTessellator::tessellateAmbientShadow(casterPolygon, casterVertexCount,
-                centroid3d, ambientShadowVertexBuffer);
-        drawVertexBuffer(kVertexBufferMode_Shadow, ambientShadowVertexBuffer, &paint);
+        VertexBufferMode vertexBufferMode = ShadowTessellator::tessellateAmbientShadow(
+                isCasterOpaque, casterPolygon, casterVertexCount, centroid3d,
+                ambientShadowVertexBuffer);
+        drawVertexBuffer(vertexBufferMode, ambientShadowVertexBuffer, &paint);
     }
 
     if (mCaches.propertySpotShadowStrength > 0) {
@@ -3260,10 +3264,10 @@
         VertexBuffer spotShadowVertexBuffer;
         Vector3 lightPosScale(mCaches.propertyLightPosXScale,
                 mCaches.propertyLightPosYScale, mCaches.propertyLightPosZScale);
-        ShadowTessellator::tessellateSpotShadow(casterPolygon, casterVertexCount,
-                lightPosScale, *currentTransform(), getWidth(), getHeight(),
-                spotShadowVertexBuffer);
-        drawVertexBuffer(kVertexBufferMode_Shadow, spotShadowVertexBuffer, &paint);
+        VertexBufferMode vertexBufferMode = ShadowTessellator::tessellateSpotShadow(
+                isCasterOpaque, casterPolygon, casterVertexCount, lightPosScale,
+                *currentTransform(), getWidth(), getHeight(), spotShadowVertexBuffer);
+        drawVertexBuffer(vertexBufferMode, spotShadowVertexBuffer, &paint);
     }
 
     return DrawGlInfo::kStatusDrew;
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 94abfa7..059c64f 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -119,7 +119,8 @@
 
 enum VertexBufferMode {
     kVertexBufferMode_Standard = 0,
-    kVertexBufferMode_Shadow = 1
+    kVertexBufferMode_OnePolyRingShadow = 1,
+    kVertexBufferMode_TwoPolyRingShadow = 2
 };
 
 ///////////////////////////////////////////////////////////////////////////////
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 714fd1b..233aace 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -27,8 +27,6 @@
         , mProjectBackwards(false)
         , mProjectionReceiver(false)
         , mClipToOutline(false)
-        , mCastsShadow(false)
-        , mUsesGlobalCamera(false) // TODO: respect value when rendering
         , mAlpha(1)
         , mHasOverlappingRendering(true)
         , mTranslationX(0), mTranslationY(0), mTranslationZ(0)
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index a5ce4a6..6e3b8ae 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -52,14 +52,6 @@
         mClipToBounds = clipToBounds;
     }
 
-    void setCastsShadow(bool castsShadow) {
-        mCastsShadow = castsShadow;
-    }
-
-    void setUsesGlobalCamera(bool usesGlobalCamera) {
-        mUsesGlobalCamera = usesGlobalCamera;
-    }
-
     void setProjectBackwards(bool shouldProject) {
         mProjectBackwards = shouldProject;
     }
@@ -409,8 +401,6 @@
     bool mProjectionReceiver;
     SkPath mOutline;
     bool mClipToOutline;
-    bool mCastsShadow;
-    bool mUsesGlobalCamera; // TODO: respect value when rendering
     float mAlpha;
     bool mHasOverlappingRendering;
     float mTranslationX, mTranslationY, mTranslationZ;
diff --git a/libs/hwui/ShadowTessellator.cpp b/libs/hwui/ShadowTessellator.cpp
index f138222..771904a 100644
--- a/libs/hwui/ShadowTessellator.cpp
+++ b/libs/hwui/ShadowTessellator.cpp
@@ -33,9 +33,9 @@
     return a > b ? a : b;
 }
 
-void ShadowTessellator::tessellateAmbientShadow(const Vector3* casterPolygon,
-        int casterVertexCount, const Vector3& centroid3d,
-        VertexBuffer& shadowVertexBuffer) {
+VertexBufferMode ShadowTessellator::tessellateAmbientShadow(bool isCasterOpaque,
+        const Vector3* casterPolygon, int casterVertexCount,
+        const Vector3& centroid3d, VertexBuffer& shadowVertexBuffer) {
     ATRACE_CALL();
 
     // A bunch of parameters to tweak the shadow.
@@ -43,12 +43,14 @@
     const float heightFactor = 1.0f / 128;
     const float geomFactor = 64;
 
-    AmbientShadow::createAmbientShadow(casterPolygon, casterVertexCount,
-            centroid3d, heightFactor, geomFactor, shadowVertexBuffer);
+    return AmbientShadow::createAmbientShadow(isCasterOpaque, casterPolygon,
+            casterVertexCount, centroid3d, heightFactor, geomFactor,
+            shadowVertexBuffer);
 
 }
 
-void ShadowTessellator::tessellateSpotShadow(const Vector3* casterPolygon, int casterVertexCount,
+VertexBufferMode ShadowTessellator::tessellateSpotShadow(bool isCasterOpaque,
+        const Vector3* casterPolygon, int casterVertexCount,
         const Vector3& lightPosScale, const mat4& receiverTransform,
         int screenWidth, int screenHeight, VertexBuffer& shadowVertexBuffer) {
     ATRACE_CALL();
@@ -71,37 +73,40 @@
     const float lightSize = maximal / 4;
     const int lightVertexCount = 8;
 
-    SpotShadow::createSpotShadow(casterPolygon, casterVertexCount, lightCenter,
-            lightSize, lightVertexCount, shadowVertexBuffer);
+    VertexBufferMode mode = SpotShadow::createSpotShadow(isCasterOpaque,
+            casterPolygon, casterVertexCount, lightCenter, lightSize,
+            lightVertexCount, shadowVertexBuffer);
 
+#if DEBUG_SHADOW
+     if(shadowVertexBuffer.getVertexCount() <= 0) {
+        ALOGD("Spot shadow generation failed %d", shadowVertexBuffer.getVertexCount());
+     }
+#endif
+     return mode;
 }
 
 void ShadowTessellator::generateShadowIndices(uint16_t* shadowIndices) {
     int currentIndex = 0;
     const int rays = SHADOW_RAY_COUNT;
     // For the penumbra area.
-    for (int i = 0; i < rays; i++) {
-        shadowIndices[currentIndex++] = i;
-        shadowIndices[currentIndex++] = rays + i;
+    for (int layer = 0; layer < 2; layer ++) {
+        int baseIndex = layer * rays;
+        for (int i = 0; i < rays; i++) {
+            shadowIndices[currentIndex++] = i + baseIndex;
+            shadowIndices[currentIndex++] = rays + i + baseIndex;
+        }
+        // To close the loop, back to the ray 0.
+        shadowIndices[currentIndex++] = 0 + baseIndex;
+         // Note this is the same as the first index of next layer loop.
+        shadowIndices[currentIndex++] = rays + baseIndex;
     }
-    // To close the loop, back to the ray 0.
-    shadowIndices[currentIndex++] = 0;
-    shadowIndices[currentIndex++] = rays;
-
-    uint16_t centroidIndex = 2 * rays;
-    // For the umbra area, using strips to simulate the fans.
-    for (int i = 0; i < rays; i++) {
-        shadowIndices[currentIndex++] = rays + i;
-        shadowIndices[currentIndex++] = centroidIndex;
-    }
-    shadowIndices[currentIndex++] = rays;
 
 #if DEBUG_SHADOW
-    if (currentIndex != SHADOW_INDEX_COUNT) {
-        ALOGE("vertex index count is wrong. current %d, expected %d",
-                currentIndex, SHADOW_INDEX_COUNT);
+    if (currentIndex != MAX_SHADOW_INDEX_COUNT) {
+        ALOGW("vertex index count is wrong. current %d, expected %d",
+                currentIndex, MAX_SHADOW_INDEX_COUNT);
     }
-    for (int i = 0; i < SHADOW_INDEX_COUNT; i++) {
+    for (int i = 0; i < MAX_SHADOW_INDEX_COUNT; i++) {
         ALOGD("vertex index is (%d, %d)", i, shadowIndices[i]);
     }
 #endif
@@ -135,7 +140,7 @@
     if (area != 0) {
         centroid = Vector2(sumx / (3 * area), sumy / (3 * area));
     } else {
-        ALOGE("Area is 0 while computing centroid!");
+        ALOGW("Area is 0 while computing centroid!");
     }
     return centroid;
 }
diff --git a/libs/hwui/ShadowTessellator.h b/libs/hwui/ShadowTessellator.h
index c558460..ab039fa 100644
--- a/libs/hwui/ShadowTessellator.h
+++ b/libs/hwui/ShadowTessellator.h
@@ -20,6 +20,7 @@
 
 #include "Debug.h"
 #include "Matrix.h"
+#include "OpenGLRenderer.h"
 #include "VertexBuffer.h"
 
 namespace android {
@@ -30,15 +31,14 @@
 // Assuming we use 6 rays and only 1 layer, Then we will have 2 hexagons, which
 // are 0 to 5 and 6 to 11. The area between them will be the penumbra area, and
 // the area inside the 2nd hexagon is the umbra.
-// Also, we need to add the centroid "12" to draw the umbra area as triangle fans.
-//
+// Ambient shadow is using only 1 layer for opaque caster, otherwise, spot
+// shadow and ambient shadow are using 2 layers.
 // Triange strip indices for penumbra area: (0, 6, 1, 7, 2, 8, 3, 9, 4, 10, 5, 11, 0, 6)
-// Triange strip indices for numbra area: (6, 12, 7, 12, 8, 12, 9, 12, 10, 12, 11, 12, 6)
 //                 0
 //
 //      5          6         1
 //           11         7
-//                12
+//
 //           10         8
 //      4          9         2
 //
@@ -49,20 +49,27 @@
 #define SHADOW_RAY_COUNT 128
 
 // The total number of all the vertices representing the shadow.
-#define SHADOW_VERTEX_COUNT (2 * SHADOW_RAY_COUNT + 1)
+// For the case we only have 1 layer, then we will just fill only 2/3 of it.
+#define SHADOW_VERTEX_COUNT (3 * SHADOW_RAY_COUNT)
 
 // The total number of indices used for drawing the shadow geometry as triangle strips.
-#define SHADOW_INDEX_COUNT (2 * SHADOW_RAY_COUNT + 1 + 2 * (SHADOW_RAY_COUNT + 1))
+// Depending on the mode we are drawing, we can have 1 layer or 2 layers.
+// Therefore, we only build the longer index buffer.
+#define TWO_POLY_RING_SHADOW_INDEX_COUNT (4 * (SHADOW_RAY_COUNT + 1))
+#define ONE_POLY_RING_SHADOW_INDEX_COUNT (2 * (SHADOW_RAY_COUNT + 1))
+
+#define MAX_SHADOW_INDEX_COUNT TWO_POLY_RING_SHADOW_INDEX_COUNT
 
 #define SHADOW_MIN_CASTER_Z 0.001f
 
 class ShadowTessellator {
 public:
-    static void tessellateAmbientShadow(const Vector3* casterPolygon,
-            int casterVertexCount, const Vector3& centroid3d,
-            VertexBuffer& shadowVertexBuffer);
+    static VertexBufferMode tessellateAmbientShadow(bool isCasterOpaque,
+            const Vector3* casterPolygon, int casterVertexCount,
+            const Vector3& centroid3d, VertexBuffer& shadowVertexBuffer);
 
-    static void tessellateSpotShadow(const Vector3* casterPolygon, int casterVertexCount,
+    static VertexBufferMode tessellateSpotShadow(bool isCasterOpaque,
+            const Vector3* casterPolygon, int casterVertexCount,
             const Vector3& lightPosScale, const mat4& receiverTransform,
             int screenWidth, int screenHeight, VertexBuffer& shadowVertexBuffer);
 
diff --git a/libs/hwui/SpotShadow.cpp b/libs/hwui/SpotShadow.cpp
index 8538b29..f81cd12 100644
--- a/libs/hwui/SpotShadow.cpp
+++ b/libs/hwui/SpotShadow.cpp
@@ -62,7 +62,9 @@
 
 #if DEBUG_SHADOW
     double interpVal = (dx * (p1.y - rayOrigin.y) + dy * rayOrigin.x - dy * p1.x) / divisor;
-    if (interpVal < 0 || interpVal > 1) return -1.0f; // error, doesn't intersect between points
+    if (interpVal < 0 || interpVal > 1) {
+        ALOGW("rayIntersectPoints is hitting outside the segment %f", interpVal);
+    }
 #endif
 
     double distance = (p1.x * (rayOrigin.y - p2.y) + p2.x * (p1.y - rayOrigin.y) +
@@ -161,7 +163,7 @@
 
 /**
  * Calculates the intersection of poly1 with poly2 and put in poly2.
- *
+ * Note that both poly1 and poly2 must be in CW order already!
  *
  * @param poly1 The 1st polygon, as a Vector2 array.
  * @param poly1Length The number of vertices of 1st polygon.
@@ -169,11 +171,16 @@
  * @param poly2Length The number of vertices of 2nd polygon.
  * @return number of vertices in output polygon as poly2.
  */
-int SpotShadow::intersection(Vector2* poly1, int poly1Length,
+int SpotShadow::intersection(const Vector2* poly1, int poly1Length,
         Vector2* poly2, int poly2Length) {
-    makeClockwise(poly1, poly1Length);
-    makeClockwise(poly2, poly2Length);
-
+#if DEBUG_SHADOW
+    if (!isClockwise(poly1, poly1Length)) {
+        ALOGW("Poly1 is not clockwise! Intersection is wrong!");
+    }
+    if (!isClockwise(poly2, poly2Length)) {
+        ALOGW("Poly2 is not clockwise! Intersection is wrong!");
+    }
+#endif
     Vector2 poly[poly1Length * poly2Length + 2];
     int count = 0;
     int pcount = 0;
@@ -411,7 +418,7 @@
  * @param polygon the polygon as a Vector2 array
  * @param len the number of points of the polygon
  */
-bool SpotShadow::isClockwise(Vector2* polygon, int len) {
+bool SpotShadow::isClockwise(const Vector2* polygon, int len) {
     double sum = 0;
     double p1x = polygon[len - 1].x;
     double p1y = polygon[len - 1].y;
@@ -514,13 +521,14 @@
 *                            empty strip if error.
 *
 */
-void SpotShadow::createSpotShadow(const Vector3* poly, int polyLength,
-        const Vector3& lightCenter, float lightSize, int lightVertexCount,
-        VertexBuffer& retStrips) {
+VertexBufferMode SpotShadow::createSpotShadow(bool isCasterOpaque, const Vector3* poly,
+        int polyLength, const Vector3& lightCenter, float lightSize,
+        int lightVertexCount, VertexBuffer& retStrips) {
     Vector3 light[lightVertexCount * 3];
     computeLightPolygon(lightVertexCount, lightCenter, lightSize, light);
-    computeSpotShadow(light, lightVertexCount, lightCenter, poly, polyLength,
-            retStrips);
+    computeSpotShadow(isCasterOpaque, light, lightVertexCount, lightCenter, poly,
+            polyLength, retStrips);
+    return kVertexBufferMode_TwoPolyRingShadow;
 }
 
 /**
@@ -533,9 +541,9 @@
  * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
  *                            empty strip if error.
  */
-void SpotShadow::computeSpotShadow(const Vector3* lightPoly, int lightPolyLength,
-        const Vector3& lightCenter, const Vector3* poly, int polyLength,
-        VertexBuffer& shadowTriangleStrip) {
+void SpotShadow::computeSpotShadow(bool isCasterOpaque, const Vector3* lightPoly,
+        int lightPolyLength, const Vector3& lightCenter, const Vector3* poly,
+        int polyLength, VertexBuffer& shadowTriangleStrip) {
     // Point clouds for all the shadowed vertices
     Vector2 shadowRegion[lightPolyLength * polyLength];
     // Shadow polygon from one point light.
@@ -565,13 +573,13 @@
     for (int j = 0; j < lightPolyLength; j++) {
         int m = 0;
         for (int i = 0; i < polyLength; i++) {
-            float t = lightPoly[j].z - poly[i].z;
-            if (t == 0) {
+            float deltaZ = lightPoly[j].z - poly[i].z;
+            if (deltaZ == 0) {
                 return;
             }
-            t = lightPoly[j].z / t;
-            float x = lightPoly[j].x - t * (lightPoly[j].x - poly[i].x);
-            float y = lightPoly[j].y - t * (lightPoly[j].y - poly[i].y);
+            float ratioZ = lightPoly[j].z / deltaZ;
+            float x = lightPoly[j].x - ratioZ * (lightPoly[j].x - poly[i].x);
+            float y = lightPoly[j].y - ratioZ * (lightPoly[j].y - poly[i].y);
 
             Vector2 newPoint = Vector2(x, y);
             shadowRegion[k] = newPoint;
@@ -606,13 +614,13 @@
     if (umbraLength < 3) {
         // If there is no real umbra, make a fake one.
         for (int i = 0; i < polyLength; i++) {
-            float t = lightCenter.z - poly[i].z;
-            if (t == 0) {
+            float deltaZ = lightCenter.z - poly[i].z;
+            if (deltaZ == 0) {
                 return;
             }
-            t = lightCenter.z / t;
-            float x = lightCenter.x - t * (lightCenter.x - poly[i].x);
-            float y = lightCenter.y - t * (lightCenter.y - poly[i].y);
+            float ratioZ = lightCenter.z / deltaZ;
+            float x = lightCenter.x - ratioZ * (lightCenter.x - poly[i].x);
+            float y = lightCenter.y - ratioZ * (lightCenter.y - poly[i].y);
 
             fakeUmbra[i].x = x;
             fakeUmbra[i].y = y;
@@ -635,8 +643,8 @@
         umbraLength = polyLength;
     }
 
-    generateTriangleStrip(penumbra, penumbraLength, umbra, umbraLength,
-            shadowTriangleStrip);
+    generateTriangleStrip(isCasterOpaque, penumbra, penumbraLength, umbra,
+            umbraLength, poly, polyLength, shadowTriangleStrip);
 }
 
 /**
@@ -684,7 +692,12 @@
                     cos(rayIndex * step),
                     sin(rayIndex * step),
                     *lastVertex, poly[polyIndex]);
-            if (distanceToIntersect < 0) return false; // error case, abort
+            if (distanceToIntersect < 0) {
+#if DEBUG_SHADOW
+                ALOGW("ERROR: convertPolyToRayDist failed");
+#endif
+                return false; // error case, abort
+            }
 
             rayDist[rayIndex] = distanceToIntersect;
 
@@ -696,6 +709,22 @@
    return true;
 }
 
+int SpotShadow::calculateOccludedUmbra(const Vector2* umbra, int umbraLength,
+        const Vector3* poly, int polyLength, Vector2* occludedUmbra) {
+    // Occluded umbra area is computed as the intersection of the projected 2D
+    // poly and umbra.
+    for (int i = 0; i < polyLength; i++) {
+        occludedUmbra[i].x = poly[i].x;
+        occludedUmbra[i].y = poly[i].y;
+    }
+
+    // Both umbra and incoming polygon are guaranteed to be CW, so we can call
+    // intersection() directly.
+    return intersection(umbra, umbraLength,
+            occludedUmbra, polyLength);
+}
+
+#define OCLLUDED_UMBRA_SHRINK_FACTOR 0.95f
 /**
  * Generate a triangle strip given two convex polygons
  *
@@ -706,10 +735,10 @@
  * @param shadowTriangleStrip return an (x,y,alpha) triangle strip representing the shadow. Return
  *                            empty strip if error.
 **/
-void SpotShadow::generateTriangleStrip(const Vector2* penumbra, int penumbraLength,
-        const Vector2* umbra, int umbraLength, VertexBuffer& shadowTriangleStrip) {
+void SpotShadow::generateTriangleStrip(bool isCasterOpaque, const Vector2* penumbra,
+        int penumbraLength, const Vector2* umbra, int umbraLength,
+        const Vector3* poly, int polyLength, VertexBuffer& shadowTriangleStrip) {
     const int rays = SHADOW_RAY_COUNT;
-
     const int size = 2 * rays;
     const float step = M_PI * 2 / rays;
     // Centroid of the umbra.
@@ -721,37 +750,66 @@
     float penumbraDistPerRay[rays];
     // Intersection to the umbra.
     float umbraDistPerRay[rays];
+    // Intersection to the occluded umbra area.
+    float occludedUmbraDistPerRay[rays];
 
     // convert CW polygons to ray distance encoding, aborting on conversion failure
     if (!convertPolyToRayDist(umbra, umbraLength, centroid, umbraDistPerRay)) return;
     if (!convertPolyToRayDist(penumbra, penumbraLength, centroid, penumbraDistPerRay)) return;
 
-    AlphaVertex* shadowVertices = shadowTriangleStrip.alloc<AlphaVertex>(getStripSize(rays));
+    bool hasOccludedUmbraArea = false;
+    if (isCasterOpaque) {
+        Vector2 occludedUmbra[polyLength + umbraLength];
+        int occludedUmbraLength = calculateOccludedUmbra(umbra, umbraLength, poly, polyLength,
+                occludedUmbra);
+        // Make sure the centroid is inside the umbra, otherwise, fall back to the
+        // approach as if there is no occluded umbra area.
+        if (testPointInsidePolygon(centroid, occludedUmbra, occludedUmbraLength)) {
+            hasOccludedUmbraArea = true;
+            // Shrink the occluded umbra area to avoid pixel level artifacts.
+            for (int i = 0; i < occludedUmbraLength; i ++) {
+                occludedUmbra[i] = centroid + (occludedUmbra[i] - centroid) *
+                        OCLLUDED_UMBRA_SHRINK_FACTOR;
+            }
+            if (!convertPolyToRayDist(occludedUmbra, occludedUmbraLength, centroid,
+                    occludedUmbraDistPerRay)) {
+                return;
+            }
+        }
+    }
+
+    AlphaVertex* shadowVertices =
+            shadowTriangleStrip.alloc<AlphaVertex>(SHADOW_VERTEX_COUNT);
 
     // Calculate the vertices (x, y, alpha) in the shadow area.
+    AlphaVertex centroidXYA;
+    AlphaVertex::set(&centroidXYA, centroid.x, centroid.y, 1.0f);
     for (int rayIndex = 0; rayIndex < rays; rayIndex++) {
         float dx = cosf(step * rayIndex);
         float dy = sinf(step * rayIndex);
 
-        // outer ring
-        float currentDist = penumbraDistPerRay[rayIndex];
+        // penumbra ring
+        float penumbraDistance = penumbraDistPerRay[rayIndex];
         AlphaVertex::set(&shadowVertices[rayIndex],
-                dx * currentDist + centroid.x, dy * currentDist + centroid.y, 0.0f);
+                dx * penumbraDistance + centroid.x,
+                dy * penumbraDistance + centroid.y, 0.0f);
 
-        // inner ring
-        float deltaDist = umbraDistPerRay[rayIndex] - penumbraDistPerRay[rayIndex];
-        currentDist += deltaDist;
+        // umbra ring
+        float umbraDistance = umbraDistPerRay[rayIndex];
         AlphaVertex::set(&shadowVertices[rays + rayIndex],
-                dx * currentDist + centroid.x, dy * currentDist + centroid.y, 1.0f);
+                dx * umbraDistance + centroid.x, dy * umbraDistance + centroid.y, 1.0f);
+
+        // occluded umbra ring
+        if (hasOccludedUmbraArea) {
+            float occludedUmbraDistance = occludedUmbraDistPerRay[rayIndex];
+            AlphaVertex::set(&shadowVertices[2 * rays + rayIndex],
+                    dx * occludedUmbraDistance + centroid.x,
+                    dy * occludedUmbraDistance + centroid.y, 1.0f);
+        } else {
+            // Put all vertices of the occluded umbra ring at the centroid.
+            shadowVertices[2 * rays + rayIndex] = centroidXYA;
+        }
     }
-    // The centroid is in the umbra area, so the opacity is considered as 1.0.
-    AlphaVertex::set(&shadowVertices[SHADOW_VERTEX_COUNT - 1], centroid.x, centroid.y, 1.0f);
-#if DEBUG_SHADOW
-    for (int i = 0; i < currentIndex; i++) {
-        ALOGD("spot shadow value: i %d, (x:%f, y:%f, a:%f)", i, shadowVertices[i].x,
-                shadowVertices[i].y, shadowVertices[i].alpha);
-    }
-#endif
 }
 
 /**
@@ -775,17 +833,6 @@
     }
 }
 
-/**
- * Calculate the number of vertex we will create given a number of rays and layers
- *
- * @param rays number of points around the polygons you want
- * @param layers number of layers of triangle strips you need
- * @return number of vertex (multiply by 3 for number of floats)
- */
-int SpotShadow::getStripSize(int rays) {
-    return  (2 + rays + (2 * (rays + 1)));
-}
-
 #if DEBUG_SHADOW
 
 #define TEST_POINT_NUMBER 128
@@ -837,7 +884,7 @@
         bool isCCWOrCoLinear = (delta >= EPSILON);
 
         if (isCCWOrCoLinear) {
-            ALOGE("(Error Type 2): polygon (%s) is not a convex b/c start (x %f, y %f),"
+            ALOGW("(Error Type 2): polygon (%s) is not a convex b/c start (x %f, y %f),"
                     "middle (x %f, y %f) and end (x %f, y %f) , delta is %f !!!",
                     name, start.x, start.y, middle.x, middle.y, end.x, end.y, delta);
             isConvex = false;
@@ -879,14 +926,14 @@
         if (testPointInsidePolygon(testPoint, intersection, intersectionLength)) {
             if (!testPointInsidePolygon(testPoint, poly1, poly1Length)) {
                 dumpPoly = true;
-                ALOGE("(Error Type 1): one point (%f, %f) in the intersection is"
+                ALOGW("(Error Type 1): one point (%f, %f) in the intersection is"
                       " not in the poly1",
                         testPoint.x, testPoint.y);
             }
 
             if (!testPointInsidePolygon(testPoint, poly2, poly2Length)) {
                 dumpPoly = true;
-                ALOGE("(Error Type 1): one point (%f, %f) in the intersection is"
+                ALOGW("(Error Type 1): one point (%f, %f) in the intersection is"
                       " not in the poly2",
                         testPoint.x, testPoint.y);
             }
diff --git a/libs/hwui/SpotShadow.h b/libs/hwui/SpotShadow.h
index 7839dc3..599d37e 100644
--- a/libs/hwui/SpotShadow.h
+++ b/libs/hwui/SpotShadow.h
@@ -26,19 +26,20 @@
 
 class SpotShadow {
 public:
-    static void createSpotShadow(const Vector3* poly, int polyLength,
-            const Vector3& lightCenter, float lightSize, int lightVertexCount,
-            VertexBuffer& retStrips);
+    static VertexBufferMode createSpotShadow(bool isCasterOpaque, const Vector3* poly,
+            int polyLength, const Vector3& lightCenter, float lightSize,
+            int lightVertexCount, VertexBuffer& retStrips);
 
 private:
-    static void computeSpotShadow(const Vector3* lightPoly, int lightPolyLength,
-            const Vector3& lightCenter, const Vector3* poly, int polyLength,
-            VertexBuffer& retstrips);
+    static int calculateOccludedUmbra(const Vector2* umbra, int umbraLength,
+            const Vector3* poly, int polyLength, Vector2* occludedUmbra);
+    static void computeSpotShadow(bool isCasterOpaque, const Vector3* lightPoly,
+            int lightPolyLength, const Vector3& lightCenter, const Vector3* poly,
+            int polyLength, VertexBuffer& retstrips);
 
     static void computeLightPolygon(int points, const Vector3& lightCenter,
             float size, Vector3* ret);
 
-    static int  getStripSize(int rays);
     static void smoothPolygon(int level, int rays, float* rayDist);
     static float rayIntersectPoly(const Vector2* poly, int polyLength,
             const Vector2& point, float dx, float dy);
@@ -46,7 +47,7 @@
     static void xsort(Vector2* points, int pointsLength);
     static int hull(Vector2* points, int pointsLength, Vector2* retPoly);
     static bool ccw(double ax, double ay, double bx, double by, double cx, double cy);
-    static int intersection(Vector2* poly1, int poly1length, Vector2* poly2, int poly2length);
+    static int intersection(const Vector2* poly1, int poly1length, Vector2* poly2, int poly2length);
     static void sort(Vector2* poly, int polyLength, const Vector2& center);
 
     static void swap(Vector2* points, int i, int j);
@@ -55,13 +56,14 @@
 
     static bool testPointInsidePolygon(const Vector2 testPoint, const Vector2* poly, int len);
     static void makeClockwise(Vector2* polygon, int len);
-    static bool isClockwise(Vector2* polygon, int len);
+    static bool isClockwise(const Vector2* polygon, int len);
     static void reverse(Vector2* polygon, int len);
     static inline bool lineIntersection(double x1, double y1, double x2, double y2,
             double x3, double y3, double x4, double y4, Vector2& ret);
 
-    static void generateTriangleStrip(const Vector2* penumbra, int penumbraLength,
-            const Vector2* umbra, int umbraLength, VertexBuffer& retstrips);
+    static void generateTriangleStrip(bool isCasterOpaque, const Vector2* penumbra,
+            int penumbraLength, const Vector2* umbra, int umbraLength,
+            const Vector3* poly, int polyLength, VertexBuffer& retstrips);
 
 #if DEBUG_SHADOW
     // Verification utility function.
diff --git a/media/jni/android_media_ImageReader.cpp b/media/jni/android_media_ImageReader.cpp
index d475eee..fcd425e 100644
--- a/media/jni/android_media_ImageReader.cpp
+++ b/media/jni/android_media_ImageReader.cpp
@@ -86,8 +86,8 @@
     void setCpuConsumer(const sp<CpuConsumer>& consumer) { mConsumer = consumer; }
     CpuConsumer* getCpuConsumer() { return mConsumer.get(); }
 
-    void setBufferQueue(const sp<BufferQueue>& bq) { mBufferQueue = bq; }
-    BufferQueue* getBufferQueue() { return mBufferQueue.get(); }
+    void setProducer(const sp<IGraphicBufferProducer>& producer) { mProducer = producer; }
+    IGraphicBufferProducer* getProducer() { return mProducer.get(); }
 
     void setBufferFormat(int format) { mFormat = format; }
     int getBufferFormat() { return mFormat; }
@@ -104,7 +104,7 @@
 
     List<CpuConsumer::LockedBuffer*> mBuffers;
     sp<CpuConsumer> mConsumer;
-    sp<BufferQueue> mBufferQueue;
+    sp<IGraphicBufferProducer> mProducer;
     jobject mWeakThiz;
     jclass mClazz;
     int mFormat;
@@ -222,7 +222,7 @@
     return ctx->getCpuConsumer();
 }
 
-static BufferQueue* ImageReader_getBufferQueue(JNIEnv* env, jobject thiz)
+static IGraphicBufferProducer* ImageReader_getProducer(JNIEnv* env, jobject thiz)
 {
     ALOGV("%s:", __FUNCTION__);
     JNIImageReaderContext* const ctx = ImageReader_getContext(env, thiz);
@@ -230,7 +230,7 @@
         jniThrowRuntimeException(env, "ImageReaderContext is not initialized");
         return NULL;
     }
-    return ctx->getBufferQueue();
+    return ctx->getProducer();
 }
 
 static void ImageReader_setNativeContext(JNIEnv* env,
@@ -613,8 +613,10 @@
 
     nativeFormat = Image_getPixelFormat(env, format);
 
-    sp<BufferQueue> bq = new BufferQueue();
-    sp<CpuConsumer> consumer = new CpuConsumer(bq, maxImages,
+    sp<IGraphicBufferProducer> gbProducer;
+    sp<IGraphicBufferConsumer> gbConsumer;
+    BufferQueue::createBufferQueue(&gbProducer, &gbConsumer);
+    sp<CpuConsumer> consumer = new CpuConsumer(gbConsumer, maxImages,
                                                /*controlledByApp*/true);
     // TODO: throw dvm exOutOfMemoryError?
     if (consumer == NULL) {
@@ -629,7 +631,7 @@
     }
     sp<JNIImageReaderContext> ctx(new JNIImageReaderContext(env, weakThiz, clazz, maxImages));
     ctx->setCpuConsumer(consumer);
-    ctx->setBufferQueue(bq);
+    ctx->setProducer(gbProducer);
     consumer->setFrameAvailableListener(ctx);
     ImageReader_setNativeContext(env, thiz, ctx);
     ctx->setBufferFormat(nativeFormat);
@@ -794,14 +796,14 @@
 {
     ALOGV("%s: ", __FUNCTION__);
 
-    BufferQueue* bq = ImageReader_getBufferQueue(env, thiz);
-    if (bq == NULL) {
+    IGraphicBufferProducer* gbp = ImageReader_getProducer(env, thiz);
+    if (gbp == NULL) {
         jniThrowRuntimeException(env, "CpuConsumer is uninitialized");
         return NULL;
     }
 
     // Wrap the IGBP in a Java-language Surface.
-    return android_view_Surface_createFromIGraphicBufferProducer(env, bq);
+    return android_view_Surface_createFromIGraphicBufferProducer(env, gbp);
 }
 
 static jobject Image_createSurfacePlane(JNIEnv* env, jobject thiz, int idx)
diff --git a/media/mca/filterfw/native/core/gl_env.cpp b/media/mca/filterfw/native/core/gl_env.cpp
index 84dad8c..f092af8 100644
--- a/media/mca/filterfw/native/core/gl_env.cpp
+++ b/media/mca/filterfw/native/core/gl_env.cpp
@@ -162,9 +162,11 @@
   }
 
   // Create dummy surface using a GLConsumer
-  sp<BufferQueue> bq = new BufferQueue();
-  surfaceTexture_ = new GLConsumer(bq, 0);
-  window_ = new Surface(static_cast<sp<IGraphicBufferProducer> >(bq));
+  sp<IGraphicBufferProducer> producer;
+  sp<IGraphicBufferConsumer> consumer;
+  BufferQueue::createBufferQueue(&producer, &consumer);
+  surfaceTexture_ = new GLConsumer(consumer, 0);
+  window_ = new Surface(producer);
 
   surfaces_[0] = SurfaceWindowPair(eglCreateWindowSurface(display(), config, window_.get(), NULL), NULL);
   if (CheckEGLError("eglCreateWindowSurface")) return false;
diff --git a/packages/SystemUI/src/com/android/systemui/recent/Recents.java b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
index c7d2f04..56acf04 100644
--- a/packages/SystemUI/src/com/android/systemui/recent/Recents.java
+++ b/packages/SystemUI/src/com/android/systemui/recent/Recents.java
@@ -107,8 +107,10 @@
     final static int MSG_UPDATE_TASK_THUMBNAIL = 1;
     final static int MSG_PRELOAD_TASKS = 2;
     final static int MSG_CANCEL_PRELOAD_TASKS = 3;
+    final static int MSG_CLOSE_RECENTS = 4;
+    final static int MSG_TOGGLE_RECENTS = 5;
 
-    final static String sToggleRecentsAction = "com.android.systemui.recents.TOGGLE_RECENTS";
+    final static String sToggleRecentsAction = "com.android.systemui.recents.SHOW_RECENTS";
     final static String sRecentsPackage = "com.android.systemui";
     final static String sRecentsActivity = "com.android.systemui.recents.RecentsActivity";
     final static String sRecentsService = "com.android.systemui.recents.RecentsService";
@@ -421,6 +423,33 @@
 
     /** Starts the recents activity */
     void startAlternateRecentsActivity() {
+        // If Recents is the front most activity, then we should just communicate with it directly
+        // to launch the first task or dismiss itself
+        ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
+        List<ActivityManager.RunningTaskInfo> tasks = am.getRunningTasks(1);
+        if (!tasks.isEmpty()) {
+            ComponentName topActivity = tasks.get(0).topActivity;
+            Log.d(TAG, "[RecentsComponent|topActivity] " + topActivity);
+
+            // Check if the front most activity is recents
+            if (topActivity.getPackageName().equals(sRecentsPackage) &&
+                    topActivity.getClassName().equals(sRecentsActivity)) {
+                // Notify Recents to toggle itself
+                try {
+                    Bundle data = new Bundle();
+                    Message msg = Message.obtain(null, MSG_TOGGLE_RECENTS, 0, 0);
+                    msg.setData(data);
+                    mService.send(msg);
+                } catch (RemoteException re) {
+                    re.printStackTrace();
+                }
+                return;
+            }
+        }
+
+        // XXX: If window transitions are currently happening, then we should eat up the event here
+
+        // Otherwise, Recents is not the front-most activity and we should animate into it
         Rect taskRect = mFirstTaskRect;
         if (taskRect != null && taskRect.width() > 0 && taskRect.height() > 0 && hasFirstTask()) {
             // Loading from thumbnail
@@ -513,6 +542,17 @@
     public void closeRecents() {
         if (mUseAlternateRecents) {
             Log.d(TAG, "[RecentsComponent|closeRecents]");
+            if (mServiceIsBound) {
+                // Try and update the recents configuration
+                try {
+                    Bundle data = new Bundle();
+                    Message msg = Message.obtain(null, MSG_CLOSE_RECENTS, 0, 0);
+                    msg.setData(data);
+                    mService.send(msg);
+                } catch (RemoteException re) {
+                    re.printStackTrace();
+                }
+            }
         } else {
             Intent intent = new Intent(RecentsActivity.CLOSE_RECENTS_INTENT);
             intent.setPackage("com.android.systemui");
diff --git a/packages/SystemUI/src/com/android/systemui/recents/Constants.java b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
index 62da17e..ede4ea8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/Constants.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/Constants.java
@@ -28,6 +28,7 @@
         public static class App {
             public static final boolean EnableTaskFiltering = false;
             public static final boolean EnableTaskStackClipping = false;
+            public static final boolean EnableToggleNewRecentsActivity = false;
             // This disables the bitmap and icon caches to
             public static final boolean DisableBackgroundCache = false;
 
@@ -76,6 +77,8 @@
                 public static final int SnapScrollBackDuration = 650;
             }
 
+            public static final int TaskStackOverscrollRange = 150;
+
             // The padding will be applied to the smallest dimension, and then applied to all sides
             public static final float StackPaddingPct = 0.15f;
             // The overlap height relative to the task height
@@ -91,12 +94,13 @@
         public static class TaskView {
             public static class Animation {
                 public static final int TaskDataUpdatedFadeDuration = 250;
-                public static final int TaskIconCircularClipInDuration = 225;
-                public static final int TaskIconCircularClipOutDuration = 85;
+                public static final int TaskIconOnEnterDuration = 175;
+                public static final int TaskIconOnLeavingDuration = 75;
             }
 
             public static final boolean AnimateFrontTaskIconOnEnterRecents = true;
             public static final boolean AnimateFrontTaskIconOnLeavingRecents = true;
+            public static final boolean AnimateFrontTaskIconOnEnterUseClip = false;
             public static final boolean AnimateFrontTaskIconOnLeavingUseClip = false;
             public static final boolean DrawColoredTaskBars = false;
             public static final boolean UseRoundedCorners = true;
@@ -106,9 +110,4 @@
             public static final float TaskIconSizeDps = 60;
         }
     }
-
-    // UNMIGRATED CONSTANTS:
-
-    /** Determines whether to layout the stack vertically in landscape mode */
-    public static final boolean LANDSCAPE_LAYOUT_VERTICAL_STACK = true;
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index e3908ff..8408684 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -17,27 +17,48 @@
 package com.android.systemui.recents;
 
 import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.os.Bundle;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
-import com.android.systemui.recent.RecentTasksLoader;
+import com.android.systemui.R;
 import com.android.systemui.recents.model.SpaceNode;
 import com.android.systemui.recents.model.TaskStack;
 import com.android.systemui.recents.views.RecentsView;
-import com.android.systemui.R;
 
 import java.util.ArrayList;
 
 
 /* Activity */
-public class RecentsActivity extends Activity {
+public class RecentsActivity extends Activity implements RecentsView.RecentsViewCallbacks {
     FrameLayout mContainerView;
     RecentsView mRecentsView;
     View mEmptyView;
+
     boolean mVisible;
+    boolean mTaskLaunched;
+
+    BroadcastReceiver mServiceBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                    "[RecentsActivity|serviceBroadcast]", action, Console.AnsiRed);
+            if (action.equals(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY)) {
+                if (Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
+                    finish();
+                }
+            } else if (action.equals(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY)) {
+                // Dismiss recents and launch the first task if possible
+                dismissRecentsIfVisible();
+            }
+        }
+    };
 
     /** Updates the set of recent tasks */
     void updateRecentsTasks() {
@@ -63,14 +84,12 @@
     }
 
     /** Dismisses recents if we are already visible and the intent is to toggle the recents view */
-    boolean dismissRecentsIfVisible(Intent intent) {
-        if ("com.android.systemui.recents.TOGGLE_RECENTS".equals(intent.getAction())) {
-            if (mVisible) {
-                if (!mRecentsView.launchFirstTask()) {
-                    finish();
-                }
-                return true;
+    boolean dismissRecentsIfVisible() {
+        if (mVisible) {
+            if (!mRecentsView.launchFirstTask()) {
+                finish();
             }
+            return true;
         }
         return false;
     }
@@ -87,9 +106,6 @@
         RecentsTaskLoader.initialize(this);
         RecentsConfiguration.reinitialize(this);
 
-        // Dismiss recents if it is visible and we are toggling
-        if (dismissRecentsIfVisible(getIntent())) return;
-
         // Set the background dim
         WindowManager.LayoutParams wlp = getWindow().getAttributes();
         wlp.dimAmount = Constants.Values.Window.BackgroundDim;
@@ -98,6 +114,7 @@
 
         // Create the view hierarchy
         mRecentsView = new RecentsView(this);
+        mRecentsView.setCallbacks(this);
         mRecentsView.setLayoutParams(new FrameLayout.LayoutParams(
                 FrameLayout.LayoutParams.MATCH_PARENT,
                 FrameLayout.LayoutParams.MATCH_PARENT));
@@ -118,13 +135,14 @@
     @Override
     protected void onNewIntent(Intent intent) {
         super.onNewIntent(intent);
+
+        // Reset the task launched flag if we encounter an onNewIntent() before onStop()
+        mTaskLaunched = false;
+
         Console.logDivider(Constants.DebugFlags.App.SystemUIHandshake);
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onNewIntent]",
                 intent.getAction() + " visible: " + mVisible, Console.AnsiRed);
 
-        // Dismiss recents if it is visible and we are toggling
-        if (dismissRecentsIfVisible(intent)) return;
-
         // Initialize the loader and the configuration
         RecentsTaskLoader.initialize(this);
         RecentsConfiguration.reinitialize(this);
@@ -146,6 +164,12 @@
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onResume]", "",
                 Console.AnsiRed);
         super.onResume();
+
+        // Register the broadcast receiver to handle messages from our service
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
+        filter.addAction(RecentsService.ACTION_FINISH_RECENTS_ACTIVITY);
+        registerReceiver(mServiceBroadcastReceiver, filter);
     }
 
     @Override
@@ -154,9 +178,8 @@
                 Console.AnsiRed);
         super.onPause();
 
-        // Stop the loader immediately when we leave Recents
-        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
-        loader.stopLoader();
+        // Unregister any broadcast receivers we have registered
+        unregisterReceiver(mServiceBroadcastReceiver);
     }
 
     @Override
@@ -164,7 +187,21 @@
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onStop]", "",
                 Console.AnsiRed);
         super.onStop();
+
+        // Finish the current recents activity after we have launched a task
+        if (mTaskLaunched && Constants.DebugFlags.App.EnableToggleNewRecentsActivity) {
+            finish();
+        }
+
         mVisible = false;
+        mTaskLaunched = false;
+    }
+
+    @Override
+    protected void onDestroy() {
+        Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsActivity|onDestroy]", "",
+                Console.AnsiRed);
+        super.onDestroy();
     }
 
     @Override
@@ -181,4 +218,9 @@
             super.onBackPressed();
         }
     }
+
+    @Override
+    public void onTaskLaunching() {
+        mTaskLaunched = true;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
index 46ff841..485b136 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsService.java
@@ -33,57 +33,72 @@
 import java.lang.ref.WeakReference;
 
 
-/* Service */
-public class RecentsService extends Service {
-    // XXX: This should be getting the message from recents definition
-    final static int MSG_UPDATE_RECENTS_FOR_CONFIGURATION = 0;
+/** The message handler to process Recents SysUI messages */
+class SystemUIMessageHandler extends Handler {
+    WeakReference<Context> mContext;
 
-    /** This Handler should be static to prevent holding onto a reference to the service. */
-    static class MessageHandler extends Handler {
-        WeakReference<Context> mContext;
-
-        MessageHandler(Context context) {
-            // Keep a weak ref to the context instead of a strong ref
-            mContext = new WeakReference<Context>(context);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            Console.log(Constants.DebugFlags.App.SystemUIHandshake,
-                    "[RecentsService|handleMessage]", msg);
-            if (msg.what == MSG_UPDATE_RECENTS_FOR_CONFIGURATION) {
-                Context context = mContext.get();
-                if (context == null) return;
-
-                RecentsTaskLoader.initialize(context);
-                RecentsConfiguration.reinitialize(context);
-
-                try {
-                    Bundle data = msg.getData();
-                    Rect windowRect = (Rect) data.getParcelable("windowRect");
-                    Rect systemInsets = (Rect) data.getParcelable("systemInsets");
-                    RecentsConfiguration.getInstance().updateSystemInsets(systemInsets);
-
-                    // Create a dummy task stack & compute the rect for the thumbnail to animate to
-                    TaskStack stack = new TaskStack(context);
-                    TaskStackView tsv = new TaskStackView(context, stack);
-                    tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top);
-                    tsv.boundScroll();
-                    TaskViewTransform transform = tsv.getStackTransform(0);
-                    Rect taskRect = new Rect(transform.rect);
-
-                    data.putParcelable("taskRect", taskRect);
-                    Message reply = Message.obtain(null, MSG_UPDATE_RECENTS_FOR_CONFIGURATION, 0, 0);
-                    reply.setData(data);
-                    msg.replyTo.send(reply);
-                } catch (RemoteException re) {
-                    re.printStackTrace();
-                }
-            }
-        }
+    SystemUIMessageHandler(Context context) {
+        // Keep a weak ref to the context instead of a strong ref
+        mContext = new WeakReference<Context>(context);
     }
 
-    Messenger mMessenger = new Messenger(new MessageHandler(this));
+    @Override
+    public void handleMessage(Message msg) {
+        Console.log(Constants.DebugFlags.App.SystemUIHandshake,
+                "[RecentsService|handleMessage]", msg);
+
+        Context context = mContext.get();
+        if (context == null) return;
+
+        if (msg.what == RecentsService.MSG_UPDATE_RECENTS_FOR_CONFIGURATION) {
+            RecentsTaskLoader.initialize(context);
+            RecentsConfiguration.reinitialize(context);
+
+            try {
+                Bundle data = msg.getData();
+                Rect windowRect = (Rect) data.getParcelable("windowRect");
+                Rect systemInsets = (Rect) data.getParcelable("systemInsets");
+
+                // Create a dummy task stack & compute the rect for the thumbnail to animate to
+                TaskStack stack = new TaskStack(context);
+                TaskStackView tsv = new TaskStackView(context, stack);
+                // Since the nav bar height is already accounted for in the windowRect, don't pass
+                // in a bottom inset
+                tsv.computeRects(windowRect.width(), windowRect.height() - systemInsets.top, 0);
+                tsv.boundScroll();
+                TaskViewTransform transform = tsv.getStackTransform(0);
+                Rect taskRect = new Rect(transform.rect);
+
+                data.putParcelable("taskRect", taskRect);
+                Message reply = Message.obtain(null,
+                        RecentsService.MSG_UPDATE_RECENTS_FOR_CONFIGURATION, 0, 0);
+                reply.setData(data);
+                msg.replyTo.send(reply);
+            } catch (RemoteException re) {
+                re.printStackTrace();
+            }
+        } else if (msg.what == RecentsService.MSG_CLOSE_RECENTS) {
+            // Do nothing
+        } else if (msg.what == RecentsService.MSG_TOGGLE_RECENTS) {
+            // Send a broadcast to toggle recents
+            Intent intent = new Intent(RecentsService.ACTION_TOGGLE_RECENTS_ACTIVITY);
+            intent.setPackage(context.getPackageName());
+            context.sendBroadcast(intent);
+        }
+    }
+}
+
+/* Service */
+public class RecentsService extends Service {
+    final static String ACTION_FINISH_RECENTS_ACTIVITY = "action_finish_recents_activity";
+    final static String ACTION_TOGGLE_RECENTS_ACTIVITY = "action_toggle_recents_activity";
+
+    // XXX: This should be getting the message from recents definition
+    final static int MSG_UPDATE_RECENTS_FOR_CONFIGURATION = 0;
+    final static int MSG_CLOSE_RECENTS = 4;
+    final static int MSG_TOGGLE_RECENTS = 5;
+
+    Messenger mSystemUIMessenger = new Messenger(new SystemUIMessageHandler(this));
 
     @Override
     public void onCreate() {
@@ -94,7 +109,7 @@
     @Override
     public IBinder onBind(Intent intent) {
         Console.log(Constants.DebugFlags.App.SystemUIHandshake, "[RecentsService|onBind]");
-        return mMessenger.getBinder();
+        return mSystemUIMessenger.getBinder();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index 253b8e3..5f9162d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -511,7 +511,8 @@
 
         switch (level) {
             case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN:
-                // Do nothing
+                // Stop the loader immediately when the UI is no longer visible
+                stopLoader();
                 break;
             case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE:
             case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND:
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
index c85c14b..9133f7d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -40,14 +40,27 @@
  * to their SpaceNode bounds.
  */
 public class RecentsView extends FrameLayout implements TaskStackView.TaskStackViewCallbacks {
+
+    /** The RecentsView callbacks */
+    public interface RecentsViewCallbacks {
+        public void onTaskLaunching();
+    }
+
     // The space partitioning root of this container
     SpaceNode mBSP;
+    // Recents view callbacks
+    RecentsViewCallbacks mCb;
 
     public RecentsView(Context context) {
         super(context);
         setWillNotDraw(false);
     }
 
+    /** Sets the callbacks */
+    public void setCallbacks(RecentsViewCallbacks cb) {
+        mCb = cb;
+    }
+
     /** Set/get the bsp root node */
     public void setBSP(SpaceNode n) {
         mBSP = n;
@@ -64,14 +77,19 @@
 
     /** Launches the first task from the first stack if possible */
     public boolean launchFirstTask() {
+        // Get the first stack view
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             TaskStackView stackView = (TaskStackView) getChildAt(i);
             TaskStack stack = stackView.mStack;
             ArrayList<Task> tasks = stack.getTasks();
+
+            // Get the first task in the stack
             if (!tasks.isEmpty()) {
                 Task task = tasks.get(tasks.size() - 1);
                 TaskView tv = null;
+
+                // Try and use the first child task view as the source of the launch animation
                 if (stackView.getChildCount() > 0) {
                     TaskView stv = (TaskView) stackView.getChildAt(stackView.getChildCount() - 1);
                     if (stv.getTask() == task) {
@@ -133,13 +151,15 @@
 
     @Override
     protected void dispatchDraw(Canvas canvas) {
-        Console.log(Constants.DebugFlags.UI.Draw, "[RecentsView|dispatchDraw]", "", Console.AnsiPurple);
+        Console.log(Constants.DebugFlags.UI.Draw, "[RecentsView|dispatchDraw]", "",
+                Console.AnsiPurple);
         super.dispatchDraw(canvas);
     }
 
     @Override
     protected boolean fitSystemWindows(Rect insets) {
-        Console.log(Constants.DebugFlags.UI.MeasureAndLayout, "[RecentsView|fitSystemWindows]", "insets: " + insets, Console.AnsiGreen);
+        Console.log(Constants.DebugFlags.UI.MeasureAndLayout,
+                "[RecentsView|fitSystemWindows]", "insets: " + insets, Console.AnsiGreen);
 
         // Update the configuration with the latest system insets and trigger a relayout
         RecentsConfiguration config = RecentsConfiguration.getInstance();
@@ -166,11 +186,16 @@
         return false;
     }
 
-    /**** View.OnClickListener Implementation ****/
+    /**** TaskStackView.TaskStackCallbacks Implementation ****/
 
     @Override
     public void onTaskLaunched(final TaskStackView stackView, final TaskView tv,
                                final TaskStack stack, final Task task) {
+        // Notify any callbacks of the launching of a new task
+        if (mCb != null) {
+            mCb.onTaskLaunching();
+        }
+
         final Runnable launchRunnable = new Runnable() {
             @Override
             public void run() {
@@ -221,7 +246,7 @@
 
         // Launch the app right away if there is no task view, otherwise, animate the icon out first
         if (tv == null || !Constants.Values.TaskView.AnimateFrontTaskIconOnLeavingRecents) {
-            launchRunnable.run();
+            post(launchRunnable);
         } else {
             tv.animateOnLeavingRecents(launchRunnable);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 17660d8..62cf394 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -428,16 +428,15 @@
     }
 
     /** Computes the stack and task rects */
-    public void computeRects(int width, int height) {
+    public void computeRects(int width, int height, int insetBottom) {
         // Note: We let the stack view be the full height because we want the cards to go under the
         //       navigation bar if possible.  However, the stack rects which we use to calculate
         //       max scroll, etc. need to take the nav bar into account
 
         // Compute the stack rects
-        RecentsConfiguration config = RecentsConfiguration.getInstance();
         mRect.set(0, 0, width, height);
         mStackRect.set(mRect);
-        mStackRect.bottom -= config.systemInsets.bottom;
+        mStackRect.bottom -= insetBottom;
 
         int smallestDimension = Math.min(width, height);
         int padding = (int) (Constants.Values.TaskStackView.StackPaddingPct * smallestDimension / 2f);
@@ -466,7 +465,8 @@
                 " awaitingFirstLayout: " + mAwaitingFirstLayout, Console.AnsiGreen);
 
         // Compute our stack/task rects
-        computeRects(width, height);
+        RecentsConfiguration config = RecentsConfiguration.getInstance();
+        computeRects(width, height, config.systemInsets.bottom);
 
         // Debug logging
         if (Constants.DebugFlags.UI.MeasureAndLayout) {
@@ -920,18 +920,25 @@
                 int velocity = (int) velocityTracker.getYVelocity(mActivePointerId);
 
                 if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
-                    Console.log(Constants.DebugFlags.UI.TouchEvents,
-                        "[TaskStackViewTouchHandler|fling]",
-                        "scroll: " + mSv.getStackScroll() + " velocity: " + velocity,
-                            Console.AnsiGreen);
                     // Enable HW layers on the stack
                     mSv.addHwLayersRefCount("flingScroll");
+                    int overscrollRange = (int) (Math.min(1f,
+                            Math.abs((float) velocity / mMaximumVelocity)) *
+                            Constants.Values.TaskStackView.TaskStackOverscrollRange);
+
+                    Console.log(Constants.DebugFlags.UI.TouchEvents,
+                            "[TaskStackViewTouchHandler|fling]",
+                            "scroll: " + mSv.getStackScroll() + " velocity: " + velocity +
+                                    " maxVelocity: " + mMaximumVelocity +
+                                    " overscrollRange: " + overscrollRange,
+                            Console.AnsiGreen);
+
                     // Fling scroll
                     mSv.mScroller.fling(0, mSv.getStackScroll(),
                             0, -velocity,
                             0, 0,
                             mSv.mMinScroll, mSv.mMaxScroll,
-                            0, 0);
+                            0, overscrollRange);
                     // Invalidate to kick off computeScroll
                     mSv.invalidate();
                 } else if (mSv.isScrollOutOfBounds()) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index ace2428..9d4f92d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -290,17 +290,36 @@
 
     /** Animates this task view as it enters recents */
     public void animateOnEnterRecents() {
-        mIconView.setCircularClipRadius(0f);
-        mIconView.animateCircularClip(true, 1f,
-            Constants.Values.TaskView.Animation.TaskIconCircularClipInDuration,
-            300, new AccelerateInterpolator(), null);
+        if (Constants.Values.TaskView.AnimateFrontTaskIconOnEnterUseClip) {
+            mIconView.setCircularClipRadius(0f);
+            mIconView.animateCircularClip(true, 1f,
+                Constants.Values.TaskView.Animation.TaskIconOnEnterDuration,
+                300, new AccelerateInterpolator(), null);
+        } else {
+            RecentsConfiguration config = RecentsConfiguration.getInstance();
+            int translate = config.pxFromDp(10);
+            mIconView.setScaleX(1.25f);
+            mIconView.setScaleY(1.25f);
+            mIconView.setAlpha(0f);
+            mIconView.setTranslationX(translate / 2);
+            mIconView.setTranslationY(-translate);
+            mIconView.animate()
+                    .alpha(1f)
+                    .scaleX(1f)
+                    .scaleY(1f)
+                    .translationX(0)
+                    .translationY(0)
+                    .setStartDelay(235)
+                    .setDuration(Constants.Values.TaskView.Animation.TaskIconOnEnterDuration)
+                    .start();
+        }
     }
 
     /** Animates this task view as it exits recents */
     public void animateOnLeavingRecents(final Runnable r) {
         if (Constants.Values.TaskView.AnimateFrontTaskIconOnLeavingUseClip) {
             mIconView.animateCircularClip(false, 0f,
-                Constants.Values.TaskView.Animation.TaskIconCircularClipOutDuration, 0,
+                Constants.Values.TaskView.Animation.TaskIconOnLeavingDuration, 0,
                 new DecelerateInterpolator(),
                 new AnimatorListenerAdapter() {
                     @Override
@@ -311,7 +330,7 @@
         } else {
             mIconView.animate()
                 .alpha(0f)
-                .setDuration(Constants.Values.TaskView.Animation.TaskIconCircularClipOutDuration)
+                .setDuration(Constants.Values.TaskView.Animation.TaskIconOnLeavingDuration)
                 .setInterpolator(new DecelerateInterpolator())
                 .setListener(
                     new AnimatorListenerAdapter() {
diff --git a/services/Android.mk b/services/Android.mk
index 5260540..165f456 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -8,6 +8,10 @@
 
 LOCAL_SRC_FILES := $(call all-java-files-under,java)
 
+# EventLogTags files.
+LOCAL_SRC_FILES += \
+        core/java/com/android/server/EventLogTags.logtags
+
 # Uncomment to enable output of certain warnings (deprecated, unchecked)
 # LOCAL_JAVACFLAGS := -Xlint
 
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index fc98c4e..7f55464 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -234,9 +234,7 @@
     }
 
     void systemReady() {
-        final Context context = ActivityThread.systemMain().getSystemContext();
-        mUserPackageMonitor.register(context,
-                null, UserHandle.ALL, false);
+        mUserPackageMonitor.register(mContext, null, UserHandle.ALL, false);
         userForeground(UserHandle.USER_OWNER);
     }
 
@@ -457,7 +455,7 @@
 
     /**
      * Enforces that only the system UID or root's UID or apps that have the
-     * {@link android.Manifest.permission.MANAGE_USERS MANAGE_USERS}
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}
      * permission can make certain calls to the UserManager.
      *
      * @param message used as message if SecurityException is thrown
@@ -1046,7 +1044,7 @@
     /**
      * Removes a user and all data directories created for that user. This method should be called
      * after the user's processes have been terminated.
-     * @param id the user's id
+     * @param userHandle the user's id
      */
     public boolean removeUser(int userHandle) {
         checkManageUsersPermission("Only the system can remove users");
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index 0b19b5c..93f6d22 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -669,15 +669,10 @@
 
             int flags = SurfaceControl.HIDDEN;
             final WindowManager.LayoutParams attrs = mWin.mAttrs;
-            final boolean isVideoPlane =
-                    (attrs.privateFlags & WindowManager.LayoutParams.PRIVATE_FLAG_VIDEO_PLANE) != 0;
 
             if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
                 flags |= SurfaceControl.SECURE;
             }
-            if (isVideoPlane) {
-                flags |= SurfaceControl.FX_SURFACE_VIDEO_PLANE;
-            }
             if (DEBUG_VISIBILITY) Slog.v(
                 TAG, "Creating surface in session "
                 + mSession.mSurfaceSession + " window " + this
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 91d77fb..b4c099d 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -51,6 +51,7 @@
 import com.android.internal.R;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
+import com.android.server.accessibility.AccessibilityManagerService;
 import com.android.server.accounts.AccountManagerService;
 import com.android.server.am.ActivityManagerService;
 import com.android.server.am.BatteryStatsService;
@@ -482,8 +483,8 @@
 
                 try {
                     Slog.i(TAG, "Accessibility Manager");
-                    ServiceManager.addService(Context.ACCESSIBILITY_SERVICE, (IBinder)
-                            getClass().getClassLoader().loadClass("com.android.server.accessibility.AccessibilityManagerService").getConstructor(Context.class).newInstance(context));
+                    ServiceManager.addService(Context.ACCESSIBILITY_SERVICE,
+                            new AccessibilityManagerService(context));
                 } catch (Throwable e) {
                     reportWtf("starting Accessibility Manager", e);
                 }