Tweaking enter/scrim animations/styles.  Fixing issue with clipping not saving layers.

Change-Id: I476c68d7df4a8fc59ca3d9be3f99526089183ec2
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
index bac8cb6..305a82f 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_enter.xml
@@ -19,10 +19,10 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
-     android:zAdjustment="top">
+     android:zAdjustment="normal">
   <alpha android:fromAlpha="1.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/fast_out_slow_in"
-         android:duration="100"/>
+         android:interpolator="@android:interpolator/linear"
+         android:duration="200"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
index b0f8807..863591f 100644
--- a/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_from_launcher_exit.xml
@@ -19,10 +19,10 @@
 
 <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:shareInterpolator="false"
-     android:zAdjustment="normal">
+     android:zAdjustment="top">
   <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/fast_out_slow_in"
-         android:duration="100"/>
+         android:interpolator="@android:interpolator/linear_out_slow_in"
+         android:duration="200"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
index 2857c04..adcefe0 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_enter.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/fast_out_slow_in"
-         android:duration="150"/>
+         android:interpolator="@android:interpolator/fast_out_linear_in"
+         android:duration="200"/>
 </set>
diff --git a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
index 1139e72..863591f 100644
--- a/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
+++ b/packages/SystemUI/res/anim/recents_to_launcher_exit.xml
@@ -23,6 +23,6 @@
   <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
          android:fillEnabled="true"
          android:fillBefore="true" android:fillAfter="true"
-         android:interpolator="@android:interpolator/fast_out_slow_in"
-         android:duration="150"/>
+         android:interpolator="@android:interpolator/linear_out_slow_in"
+         android:duration="200"/>
 </set>
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index d66968b..dce8f57 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -117,7 +117,7 @@
                         // Otherwise, just finish the activity without launching any other activities
                         ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(context,
                                 null, mFinishRunnable, null);
-                        mRecentsView.startOnExitAnimation(
+                        mRecentsView.startExitToHomeAnimation(
                                 new ViewAnimation.TaskViewExitContext(exitTrigger));
                     }
                 }
@@ -129,7 +129,7 @@
                 }
             } else if (action.equals(RecentsService.ACTION_START_ENTER_ANIMATION)) {
                 // Try and start the enter animation (or restart it on configuration changed)
-                mRecentsView.startOnEnterAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenshotView));
+                mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenshotView));
                 // Call our callback
                 onEnterAnimationTriggered();
             }
@@ -162,6 +162,13 @@
 
     /** Updates the set of recent tasks */
     void updateRecentsTasks(Intent launchIntent) {
+        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
+        SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
+        ArrayList<TaskStack> stacks = root.getStacks();
+        if (!stacks.isEmpty()) {
+            mRecentsView.setBSP(root);
+        }
+
         // Update the configuration based on the launch intent
         mConfig.launchedFromHome = launchIntent.getBooleanExtra(
                 AlternateRecentsComponent.EXTRA_FROM_HOME, false);
@@ -171,13 +178,7 @@
                 AlternateRecentsComponent.EXTRA_FROM_APP_FULL_SCREENSHOT, false);
         mConfig.launchedWithAltTab = launchIntent.getBooleanExtra(
                 AlternateRecentsComponent.EXTRA_TRIGGERED_FROM_ALT_TAB, false);
-
-        RecentsTaskLoader loader = RecentsTaskLoader.getInstance();
-        SpaceNode root = loader.reload(this, Constants.Values.RecentsTaskLoader.PreloadFirstTasksCount);
-        ArrayList<TaskStack> stacks = root.getStacks();
-        if (!stacks.isEmpty()) {
-            mRecentsView.setBSP(root);
-        }
+        mConfig.launchedWithNoRecentTasks = !root.hasTasks();
 
         if (mConfig.shouldAnimateNavBarScrim()) {
             // Hide the scrim if we animate into Recents with window transitions
@@ -188,14 +189,12 @@
         }
 
         // Add the default no-recents layout
-        if (stacks.size() == 1 && stacks.get(0).getTaskCount() == 0) {
+        if (mConfig.launchedWithNoRecentTasks) {
             mEmptyView.setVisibility(View.VISIBLE);
+            mEmptyView.setBackgroundColor(0x80000000);
         } else {
             mEmptyView.setVisibility(View.GONE);
         }
-
-        // Dim the background
-        mRecentsView.setBackgroundColor(0x80000000);
     }
 
     /** Attempts to allocate and bind the search bar app widget */
@@ -284,7 +283,7 @@
                         // We really shouldn't hit this, but if we do, just animate out (aka. finish)
                         ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
                                 null, mFinishRunnable, null);
-                        mRecentsView.startOnExitAnimation(
+                        mRecentsView.startExitToHomeAnimation(
                                 new ViewAnimation.TaskViewExitContext(exitTrigger));
                     }
                 }
@@ -376,7 +375,7 @@
 
     void onConfigurationChange() {
         // Try and start the enter animation (or restart it on configuration changed)
-        mRecentsView.startOnEnterAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenshotView));
+        mRecentsView.startEnterRecentsAnimation(new ViewAnimation.TaskViewEnterContext(mFullScreenshotView));
         // Call our callback
         onEnterAnimationTriggered();
     }
@@ -547,7 +546,7 @@
                     // Just start the animation out of recents
                     ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
                             null, mFinishRunnable, null);
-                    mRecentsView.startOnExitAnimation(
+                    mRecentsView.startExitToHomeAnimation(
                             new ViewAnimation.TaskViewExitContext(exitTrigger));
                 } else {
                     // Otherwise, try and launch the first task
@@ -555,7 +554,7 @@
                         // If there are no tasks, then just finish recents
                         ReferenceCountedTrigger exitTrigger = new ReferenceCountedTrigger(this,
                                 null, mFinishRunnable, null);
-                        mRecentsView.startOnExitAnimation(
+                        mRecentsView.startExitToHomeAnimation(
                                 new ViewAnimation.TaskViewExitContext(exitTrigger));
                     }
                 }
@@ -567,12 +566,25 @@
         // Fade in the scrim
         if (mConfig.shouldAnimateNavBarScrim() && mConfig.hasNavBarScrim()) {
             mNavBarScrimView.setVisibility(View.VISIBLE);
-            mNavBarScrimView.setAlpha(0f);
-            mNavBarScrimView.animate().alpha(1f)
+            mNavBarScrimView.setTranslationY(mNavBarScrimView.getMeasuredHeight());
+            mNavBarScrimView.animate()
+                    .translationY(0)
                     .setStartDelay(mConfig.taskBarEnterAnimDelay)
                     .setDuration(mConfig.navBarScrimEnterDuration)
+                    .setInterpolator(mConfig.quintOutInterpolator)
+                    .start();
+        }
+    }
+
+    @Override
+    public void onExitAnimationTriggered() {
+        // Fade out the scrim
+        if (mConfig.shouldAnimateNavBarScrim() && mConfig.hasNavBarScrim()) {
+            mNavBarScrimView.animate()
+                    .translationY(mNavBarScrimView.getMeasuredHeight())
+                    .setStartDelay(0)
+                    .setDuration(mConfig.taskBarExitAnimDuration)
                     .setInterpolator(mConfig.fastOutSlowInInterpolator)
-                    .withLayer()
                     .start();
         }
     }
@@ -598,12 +610,7 @@
 
         // Fade out the scrim
         if (!isTaskInStackBounds && mConfig.hasNavBarScrim()) {
-            mNavBarScrimView.animate().alpha(0f)
-                    .setStartDelay(0)
-                    .setDuration(mConfig.taskBarExitAnimDuration)
-                    .setInterpolator(mConfig.fastOutSlowInInterpolator)
-                    .withLayer()
-                    .start();
+            onExitAnimationTriggered();
         }
 
         // Mark recents as no longer visible
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
index 3b8c6c9..c1a8ee6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsConfiguration.java
@@ -97,6 +97,7 @@
 
     /** Launch states */
     public boolean launchedWithAltTab;
+    public boolean launchedWithNoRecentTasks;
     public boolean launchedFromAppWithThumbnail;
     public boolean launchedFromAppWithScreenshot;
     public boolean launchedFromHome;
@@ -245,6 +246,7 @@
      * members. */
     public void updateOnConfigurationChange() {
         launchedWithAltTab = false;
+        launchedWithNoRecentTasks = false;
         launchedFromAppWithThumbnail = false;
         launchedFromAppWithScreenshot = false;
         launchedFromHome = false;
@@ -257,12 +259,14 @@
 
     /** Returns whether the nav bar scrim should be animated when shown for the first time. */
     public boolean shouldAnimateNavBarScrim() {
-        return !launchedFromHome && !launchedFromAppWithScreenshot;
+        return true;
     }
 
     /** Returns whether the nav bar scrim should be visible. */
     public boolean hasNavBarScrim() {
-        return !transposeRecentsLayoutWithOrientation || !isLandscape;
+        // Only show the scrim if we have recent tasks, and if the nav bar is not transposed
+        return !launchedWithNoRecentTasks &&
+                (!transposeRecentsLayoutWithOrientation || !isLandscape);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
index dbcdb94..a02e1a7b 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsTaskLoader.java
@@ -394,7 +394,7 @@
 
         SystemServicesProxy ssp = mSystemServicesProxy;
         List<ActivityManager.RecentTaskInfo> tasks =
-                ssp.getRecentTasks(25, UserHandle.CURRENT.getIdentifier());
+                ssp.getRecentTasks(100, UserHandle.CURRENT.getIdentifier());
         Collections.reverse(tasks);
         if (Console.Enabled) {
             Console.log(Constants.Log.App.TimeSystemCalls,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
index 1dd1be6..20be415 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/SpaceNode.java
@@ -56,6 +56,13 @@
         return mStack;
     }
 
+    /** Returns whether there are any tasks in any stacks below this node. */
+    public boolean hasTasks() {
+        return (mStack.getTaskCount() > 0) ||
+                (mStartNode != null && mStartNode.hasTasks()) ||
+                (mEndNode != null && mEndNode.hasTasks());
+    }
+
     /** Returns whether this is a leaf node */
     boolean isLeafNode() {
         return (mStartNode == null) && (mEndNode == null);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/FullScreenTransitionView.java b/packages/SystemUI/src/com/android/systemui/recents/views/FullScreenTransitionView.java
index ad2fa8d..c861d2c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/FullScreenTransitionView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/FullScreenTransitionView.java
@@ -99,12 +99,17 @@
 
     @Override
     public void draw(Canvas canvas) {
-        int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG);
+        int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
         canvas.clipRect(mClipRect);
         super.draw(canvas);
         canvas.restoreToCount(restoreCount);
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
     /** Prepares the screenshot view for the transition into Recents */
     public void prepareAnimateOnEnterRecents(Bitmap screenshot) {
         if (!mConfig.launchedFromAppWithScreenshot) return;
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 6f79683..3e6879d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -55,6 +55,7 @@
     /** The RecentsView callbacks */
     public interface RecentsViewCallbacks {
         public void onTaskLaunching(boolean isTaskInStackBounds);
+        public void onExitAnimationTriggered();
     }
 
     RecentsConfiguration mConfig;
@@ -160,19 +161,19 @@
     }
 
     /** Requests all task stacks to start their enter-recents animation */
-    public void startOnEnterAnimation(ViewAnimation.TaskViewEnterContext ctx) {
+    public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             View child = getChildAt(i);
             if (child instanceof TaskStackView) {
                 TaskStackView stackView = (TaskStackView) child;
-                stackView.startOnEnterAnimation(ctx);
+                stackView.startEnterRecentsAnimation(ctx);
             }
         }
     }
 
     /** Requests all task stacks to start their exit-recents animation */
-    public void startOnExitAnimation(ViewAnimation.TaskViewExitContext ctx) {
+    public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
         // Handle the case when there are no views by incrementing and decrementing after all
         // animations are started.
         ctx.postAnimationTrigger.increment();
@@ -183,7 +184,7 @@
                 View child = getChildAt(i);
                 if (child instanceof TaskStackView) {
                     TaskStackView stackView = (TaskStackView) child;
-                    stackView.startOnExitAnimation(ctx);
+                    stackView.startExitToHomeAnimation(ctx);
                 }
             }
         }
@@ -191,6 +192,9 @@
         // Handle the case when there are no views by incrementing and decrementing after all
         // animations are started.
         ctx.postAnimationTrigger.decrement();
+
+        // Notify of the exit animation
+        mCb.onExitAnimationTriggered();
     }
 
     /** Adds the search bar */
@@ -476,7 +480,7 @@
         if (tv == null) {
             post(launchRunnable);
         } else {
-            tv.animateOnLaunchingTask(launchRunnable);
+            stackView.animateOnLaunchingTask(tv, launchRunnable);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
index d4f381b..82d6220 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskBarView.java
@@ -124,6 +124,11 @@
         }
     }
 
+    @Override
+    public boolean hasOverlappingRendering() {
+        return false;
+    }
+
     /** Binds the bar view to the task */
     void rebindToTask(Task t, boolean animate) {
         mTask = t;
@@ -158,12 +163,12 @@
 
     /** Prepares this task view for the enter-recents animations.  This is called earlier in the
      * first layout because the actual animation into recents may take a long time. */
-    public void prepareAnimateEnterRecents() {
+    public void prepareEnterRecentsAnimation() {
         setVisibility(View.INVISIBLE);
     }
 
     /** Animates this task bar as it enters recents */
-    public void animateOnEnterRecents(int delay, Runnable postAnimRunnable) {
+    public void startEnterRecentsAnimation(int delay, Runnable postAnimRunnable) {
         // Animate the task bar of the first task view
         setVisibility(View.VISIBLE);
         setTranslationY(-getMeasuredHeight());
@@ -177,7 +182,7 @@
     }
 
     /** Animates this task bar as it exits recents */
-    public void animateOnLaunchingTask(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
+    public void startLaunchTaskAnimation(Runnable preAnimRunnable, final Runnable postAnimRunnable) {
         // Animate the task bar out of the first task view
         animate()
                 .translationY(-getMeasuredHeight())
@@ -194,8 +199,22 @@
                 .start();
     }
 
+    /** Animates this task bar dismiss button when launching a task. */
+    public void startLaunchTaskDismissAnimation() {
+        if (mDismissButton.getVisibility() == View.VISIBLE) {
+            mDismissButton.animate().cancel();
+            mDismissButton.animate()
+                    .alpha(0f)
+                    .setStartDelay(0)
+                    .setInterpolator(mConfig.fastOutSlowInInterpolator)
+                    .setDuration(mConfig.taskBarExitAnimDuration)
+                    .withLayer()
+                    .start();
+        }
+    }
+
     /** Animates this task bar if the user does not interact with the stack after a certain time. */
-    public void animateOnNoUserInteraction() {
+    public void startNoUserInteractionAnimation() {
         mDismissButton.setVisibility(View.VISIBLE);
         mDismissButton.setAlpha(0f);
         mDismissButton.animate()
@@ -208,7 +227,7 @@
     }
 
     /** Mark this task view that the user does has not interacted with the stack after a certain time. */
-    public void setOnNoUserInteraction() {
+    public void setNoUserInteractionState() {
         if (mDismissButton.getVisibility() != View.VISIBLE) {
             mDismissButton.animate().cancel();
             mDismissButton.setVisibility(View.VISIBLE);
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 79bfa5e..e0a12b7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -116,7 +116,7 @@
                 int childCount = getChildCount();
                 for (int i = 0; i < childCount; i++) {
                     TaskView tv = (TaskView) getChildAt(i);
-                    tv.animateOnNoUserInteraction();
+                    tv.startNoUserInteractionAnimation();
                 }
             }
         });
@@ -532,6 +532,20 @@
         }
     }
 
+    /** Animates a task view in this stack as it launches. */
+    public void animateOnLaunchingTask(TaskView tv, final Runnable r) {
+        // Hide each of the task bar dismiss buttons
+        int childCount = getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            TaskView t = (TaskView) getChildAt(i);
+            if (t == tv) {
+                t.startLaunchTaskAnimation(r, true);
+            } else {
+                t.startLaunchTaskAnimation(null, false);
+            }
+        }
+    }
+
     /** Focuses the task at the specified index in the stack */
     void focusTask(int taskIndex, boolean scrollToNewPosition) {
         if (Console.Enabled) {
@@ -818,14 +832,14 @@
             int offscreenY = mRect.bottom - (mTaskRect.top - mRect.top);
             for (int i = childCount - 1; i >= 0; i--) {
                 TaskView tv = (TaskView) getChildAt(i);
-                tv.prepareAnimateEnterRecents((i == (getChildCount() - 1)), offsetTopAlign,
+                tv.prepareEnterRecentsAnimation((i == (getChildCount() - 1)), offsetTopAlign,
                         offscreenY, mTaskRect);
             }
 
             // If the enter animation started already and we haven't completed a layout yet, do the
             // enter animation now
             if (mStartEnterAnimationRequestedAfterLayout) {
-                startOnEnterAnimation(mStartEnterAnimationContext);
+                startEnterRecentsAnimation(mStartEnterAnimationContext);
                 mStartEnterAnimationRequestedAfterLayout = false;
                 mStartEnterAnimationContext = null;
             }
@@ -838,7 +852,7 @@
     }
 
     /** Requests this task stacks to start it's enter-recents animation */
-    public void startOnEnterAnimation(ViewAnimation.TaskViewEnterContext ctx) {
+    public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
         // If we are still waiting to layout, then just defer until then
         if (mAwaitingFirstLayout) {
             mStartEnterAnimationRequestedAfterLayout = true;
@@ -858,18 +872,18 @@
             ctx.stackViewCount = childCount;
             ctx.isFrontMost = (i == (getChildCount() - 1));
             ctx.transform = transform;
-            tv.animateOnEnterRecents(ctx);
+            tv.startEnterRecentsAnimation(ctx);
         }
     }
 
     /** Requests this task stacks to start it's exit-recents animation. */
-    public void startOnExitAnimation(ViewAnimation.TaskViewExitContext ctx) {
+    public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
         // Animate all the task views into view
         ctx.offscreenTranslationY = mRect.bottom - (mTaskRect.top - mRect.top);
         int childCount = getChildCount();
         for (int i = 0; i < childCount; i++) {
             TaskView tv = (TaskView) getChildAt(i);
-            tv.animateOnExitRecents(ctx);
+            tv.startExitToHomeAnimation(ctx);
         }
     }
 
@@ -1179,7 +1193,7 @@
 
         // If the doze trigger has already fired, then update the state for this task view
         if (mDozeTrigger.hasTriggered()) {
-            tv.setOnNoUserInteraction();
+            tv.setNoUserInteractionState();
         }
 
         // Add/attach the view to the hierarchy
@@ -1275,7 +1289,7 @@
                 TaskView tv = getChildViewForTask(t);
                 if (tv != null) {
                     // For visible children, defer removing the task until after the animation
-                    tv.animateRemoval(new Runnable() {
+                    tv.startDeleteTaskAnimation(new Runnable() {
                         @Override
                         public void run() {
                             mStack.removeTask(t);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
index dc8a420..c2b2094 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskThumbnailView.java
@@ -54,10 +54,13 @@
     @Override
     public void draw(Canvas canvas) {
         if (mClipTaskBar && (mClipRect != null)) {
-            // Apply the clip rect
+            int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
             canvas.clipRect(mClipRect);
+            super.draw(canvas);
+            canvas.restoreToCount(restoreCount);
+        } else {
+            super.draw(canvas);
         }
-        super.draw(canvas);
     }
 
     /** Updates the clip rect based on the given task bar. */
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 b7e834b..09dc1c8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -259,15 +259,15 @@
 
     /** Prepares this task view for the enter-recents animations.  This is called earlier in the
      * first layout because the actual animation into recents may take a long time. */
-    public void prepareAnimateEnterRecents(boolean isTaskViewFrontMost, int offsetY, int offscreenY,
-                                           Rect taskRect) {
+    public void prepareEnterRecentsAnimation(boolean isTaskViewFrontMost, int offsetY, int offscreenY,
+                                             Rect taskRect) {
         if (mConfig.launchedFromAppWithScreenshot) {
             if (isTaskViewFrontMost) {
                 // Hide the task view as we are going to animate the full screenshot into view
                 // and then replace it with this view once we are done
                 setVisibility(View.INVISIBLE);
                 // Also hide the front most task bar view so we can animate it in
-                mBarView.prepareAnimateEnterRecents();
+                mBarView.prepareEnterRecentsAnimation();
             } else {
                 // Top align the task views
                 setTranslationY(offsetY);
@@ -278,7 +278,7 @@
         } else if (mConfig.launchedFromAppWithThumbnail) {
             if (isTaskViewFrontMost) {
                 // Hide the front most task bar view so we can animate it in
-                mBarView.prepareAnimateEnterRecents();
+                mBarView.prepareEnterRecentsAnimation();
                 // Set the dim to 0 so we can animate it in
                 setDim(0);
             }
@@ -286,13 +286,14 @@
         } else if (mConfig.launchedFromHome) {
             // Move the task view off screen (below) so we can animate it in
             setTranslationY(offscreenY);
+            setTranslationZ(0);
             setScaleX(1f);
             setScaleY(1f);
         }
     }
 
     /** Animates this task view as it enters recents */
-    public void animateOnEnterRecents(ViewAnimation.TaskViewEnterContext ctx) {
+    public void startEnterRecentsAnimation(ViewAnimation.TaskViewEnterContext ctx) {
         TaskViewTransform transform = ctx.transform;
 
         if (mConfig.launchedFromAppWithScreenshot) {
@@ -302,7 +303,7 @@
                     @Override
                     public void run() {
                         // Animate the task bar of the first task view
-                        mBarView.animateOnEnterRecents(0, mEnableThumbnailClip);
+                        mBarView.startEnterRecentsAnimation(0, mEnableThumbnailClip);
                         setVisibility(View.VISIBLE);
                     }
                 });
@@ -324,7 +325,7 @@
         } else if (mConfig.launchedFromAppWithThumbnail) {
             if (ctx.isFrontMost) {
                 // Animate the task bar of the first task view
-                mBarView.animateOnEnterRecents(mConfig.taskBarEnterAnimDelay, mEnableThumbnailClip);
+                mBarView.startEnterRecentsAnimation(mConfig.taskBarEnterAnimDelay, mEnableThumbnailClip);
 
                 // Animate the dim into view as well
                 ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", getDimOverlayFromScale());
@@ -345,6 +346,7 @@
                     .scaleX(transform.scale)
                     .scaleY(transform.scale)
                     .translationY(transform.translationY)
+                    .translationZ(transform.translationZ)
                     .setStartDelay(delay)
                     .setUpdateListener(null)
                     .setInterpolator(mConfig.quintOutInterpolator)
@@ -355,8 +357,8 @@
         }
     }
 
-    /** Animates this task view as it leaves recents */
-    public void animateOnExitRecents(ViewAnimation.TaskViewExitContext ctx) {
+    /** Animates this task view as it leaves recents by pressing home. */
+    public void startExitToHomeAnimation(ViewAnimation.TaskViewExitContext ctx) {
         animate()
                 .translationY(ctx.offscreenTranslationY)
                 .setStartDelay(0)
@@ -369,32 +371,27 @@
         ctx.postAnimationTrigger.increment();
     }
 
-    /** Animates this task view if the user does not interact with the stack after a certain time. */
-    public void animateOnNoUserInteraction() {
-        mBarView.animateOnNoUserInteraction();
-    }
-
-    /** Mark this task view that the user does has not interacted with the stack after a certain time. */
-    public void setOnNoUserInteraction() {
-        mBarView.setOnNoUserInteraction();
-    }
-
     /** Animates this task view as it exits recents */
-    public void animateOnLaunchingTask(final Runnable r) {
-        // Disable the thumbnail clip and animate the bar out
-        mBarView.animateOnLaunchingTask(mDisableThumbnailClip, r);
+    public void startLaunchTaskAnimation(final Runnable r, boolean isLaunchingTask) {
+        if (isLaunchingTask) {
+            // Disable the thumbnail clip and animate the bar out
+            mBarView.startLaunchTaskAnimation(mDisableThumbnailClip, r);
 
-        // Animate the dim
-        if (mDim > 0) {
-            ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
-            anim.setDuration(mConfig.taskBarExitAnimDuration);
-            anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
-            anim.start();
+            // Animate the dim
+            if (mDim > 0) {
+                ObjectAnimator anim = ObjectAnimator.ofInt(this, "dim", 0);
+                anim.setDuration(mConfig.taskBarExitAnimDuration);
+                anim.setInterpolator(mConfig.fastOutLinearInInterpolator);
+                anim.start();
+            }
+        } else {
+            // Hide the dismiss button
+            mBarView.startLaunchTaskDismissAnimation();
         }
     }
 
     /** Animates the deletion of this task view */
-    public void animateRemoval(final Runnable r) {
+    public void startDeleteTaskAnimation(final Runnable r) {
         // Disabling clipping with the stack while the view is animating away
         setClipViewInStack(false);
 
@@ -422,6 +419,16 @@
             .start();
     }
 
+    /** Animates this task view if the user does not interact with the stack after a certain time. */
+    public void startNoUserInteractionAnimation() {
+        mBarView.startNoUserInteractionAnimation();
+    }
+
+    /** Mark this task view that the user does has not interacted with the stack after a certain time. */
+    public void setNoUserInteractionState() {
+        mBarView.setNoUserInteractionState();
+    }
+
     /** Returns the rect we want to clip (it may not be the full rect) */
     Rect getClippingRect(Rect outRect) {
         getHitRect(outRect);
@@ -489,10 +496,11 @@
 
     @Override
     public void draw(Canvas canvas) {
+        int restoreCount = canvas.save(Canvas.CLIP_SAVE_FLAG | Canvas.CLIP_TO_LAYER_SAVE_FLAG);
         // Apply the rounded rect clip path on the whole view
         canvas.clipPath(mRoundedRectClipPath);
-
         super.draw(canvas);
+        canvas.restoreToCount(restoreCount);
 
         // Apply the dim if necessary
         if (mDim > 0) {
@@ -581,7 +589,7 @@
         } else if (v == mBarView.mDismissButton) {
             // Animate out the view and call the callback
             final TaskView tv = this;
-            animateRemoval(new Runnable() {
+            startDeleteTaskAnimation(new Runnable() {
                 @Override
                 public void run() {
                     mCb.onTaskDismissed(tv);