Merge changes Ie59ed72c,Ie763a2a6,I7f830e5c,Ife637438 into nyc-dev

* changes:
  Should not update initial state at all on resize.
  Adding logging to track down bitmap issues.
  Moving the background to the window.
  Adding clear-all button.
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 4b695b9..ea0fbda 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -209,6 +209,7 @@
     private Drawable mResizingBackgroundDrawable;
     private Drawable mCaptionBackgroundDrawable;
     private Drawable mUserCaptionBackgroundDrawable;
+    private Drawable mOriginalBackgroundDrawable;
 
     private float mAvailableWidth;
 
@@ -888,6 +889,11 @@
                 mBackgroundPadding.setEmpty();
             }
             drawableChanged();
+
+            // Make sure we don't reset to the old drawable when finishing resizing.
+            if (mResizeMode != RESIZE_MODE_INVALID) {
+                mOriginalBackgroundDrawable = null;
+            }
         }
     }
 
@@ -1950,6 +1956,9 @@
             updateElevation();
 
             updateColorViews(null /* insets */, false);
+
+            mOriginalBackgroundDrawable = getBackground();
+            setBackgroundDrawable(null);
         }
         mResizeMode = resizeMode;
         getViewRootImpl().requestInvalidateRootRenderNode();
@@ -1961,6 +1970,10 @@
         updateColorViews(null /* insets */, false);
         mResizeMode = RESIZE_MODE_INVALID;
         getViewRootImpl().requestInvalidateRootRenderNode();
+        if (mOriginalBackgroundDrawable != null) {
+            setBackgroundDrawable(mOriginalBackgroundDrawable);
+            mOriginalBackgroundDrawable = null;
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml
index 8783261..2b2ce4e 100644
--- a/packages/SystemUI/res/layout/recents_stack_action_button.xml
+++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml
@@ -27,8 +27,6 @@
     android:textSize="14sp"
     android:textColor="#FFFFFF"
     android:textAllCaps="true"
-    android:drawableStart="@drawable/ic_history"
-    android:drawablePadding="6dp"
     android:shadowColor="#99000000"
     android:shadowDx="0"
     android:shadowDy="2"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 622ae71..fd051b1 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -153,6 +153,9 @@
     <!-- The animation duration for animating the removal of a task view. -->
     <integer name="recents_animate_task_view_remove_duration">175</integer>
 
+    <!-- The base animation duration for animating the removal of all task views. -->
+    <integer name="recents_animate_task_views_remove_all_duration">300</integer>
+
     <!-- The animation duration for scrolling the stack to a particular item. -->
     <integer name="recents_animate_task_stack_scroll_duration">200</integer>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index d1faa4a..c094da9 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -574,10 +574,12 @@
     <dimen name="recents_layout_bottom_margin">16dp</dimen>
     <dimen name="recents_layout_side_margin_phone">16dp</dimen>
     <dimen name="recents_layout_side_margin_tablet">48dp</dimen>
+    <dimen name="recents_layout_side_margin_tablet_docked">16dp</dimen>
     <dimen name="recents_layout_side_margin_tablet_xlarge">64dp</dimen>
+    <dimen name="recents_layout_side_margin_tablet_xlarge_docked">16dp</dimen>
 
     <!-- The height between the top margin and the top of the focused task. -->
-    <dimen name="recents_layout_top_peek_size">56dp</dimen>
+    <dimen name="recents_layout_top_peek_size">48dp</dimen>
     <!-- The height between the bottom margin and the top of task in front of the focused task. -->
     <dimen name="recents_layout_bottom_peek_size">56dp</dimen>
 
diff --git a/packages/SystemUI/src/com/android/systemui/Interpolators.java b/packages/SystemUI/src/com/android/systemui/Interpolators.java
index 5e33a9f..17f4dab 100644
--- a/packages/SystemUI/src/com/android/systemui/Interpolators.java
+++ b/packages/SystemUI/src/com/android/systemui/Interpolators.java
@@ -17,6 +17,7 @@
 package com.android.systemui;
 
 import android.view.animation.AccelerateDecelerateInterpolator;
+import android.view.animation.AccelerateInterpolator;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 import android.view.animation.LinearInterpolator;
@@ -32,6 +33,7 @@
     public static final Interpolator ALPHA_IN = new PathInterpolator(0.4f, 0f, 1f, 1f);
     public static final Interpolator ALPHA_OUT = new PathInterpolator(0f, 0f, 0.8f, 1f);
     public static final Interpolator LINEAR = new LinearInterpolator();
+    public static final Interpolator ACCELERATE = new AccelerateInterpolator();
     public static final Interpolator ACCELERATE_DECELERATE = new AccelerateDecelerateInterpolator();
     public static final Interpolator DECELERATE_QUINT = new DecelerateInterpolator(2.5f);
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index b89c2f6..d7777d5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -90,6 +90,7 @@
 
     private RecentsPackageMonitor mPackageMonitor;
     private long mLastTabKeyEventTime;
+    private int mLastOrientation = Configuration.ORIENTATION_UNDEFINED;
     private boolean mFinishedOnStartup;
     private boolean mIgnoreAltTabRelease;
     private boolean mIsVisible;
@@ -266,6 +267,7 @@
         getWindow().getAttributes().privateFlags |=
                 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
 
+        mLastOrientation = getResources().getConfiguration().orientation;
         mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
         mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
             @Override
@@ -274,6 +276,9 @@
             }
         });
 
+        // Set the window background
+        getWindow().setBackgroundDrawable(mRecentsView.getBackgroundScrim());
+
         // Create the home intent runnable
         mHomeIntent = new Intent(Intent.ACTION_MAIN, null);
         mHomeIntent.addCategory(Intent.CATEGORY_HOME);
@@ -415,13 +420,18 @@
         // Update the nav bar for the current orientation
         updateNavBarScrim(false /* animateNavBarScrim */, AnimationProps.IMMEDIATE);
 
-        EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */));
+        // Notify of the config change
+        int newOrientation = getResources().getConfiguration().orientation;
+        EventBus.getDefault().send(new ConfigurationChangedEvent(false /* fromMultiWindow */,
+                (mLastOrientation != newOrientation)));
+        mLastOrientation = newOrientation;
     }
 
     @Override
     public void onMultiWindowChanged(boolean inMultiWindow) {
         super.onMultiWindowChanged(inMultiWindow);
-        EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */));
+        EventBus.getDefault().send(new ConfigurationChangedEvent(true /* fromMultiWindow */,
+                false /* fromOrientationChange */));
 
         if (mRecentsView != null) {
             // Reload the task stack completely
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
index 043510e..1715356 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsDebugFlags.java
@@ -36,7 +36,7 @@
         // Enables the task affiliations
         public static final boolean EnableAffiliatedTaskGroups = false;
         // TODO: To be repurposed
-        public static final boolean EnableStackActionButton = false;
+        public static final boolean EnableStackActionButton = true;
         // Overrides the Tuner flags and enables the timeout
         private static final boolean EnableFastToggleTimeout = false;
         // Overrides the Tuner flags and enables the paging via the Recents button
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index ffc037d..43d627d 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -663,13 +663,18 @@
             @Override
             public void run() {
                 final Bitmap transitionBitmap = drawThumbnailTransitionBitmap(toTask, toTransform);
-                mHandler.post(new Runnable() {
-                    @Override
-                    public void run() {
-                        mThumbnailTransitionBitmapCache = transitionBitmap;
-                        mThumbnailTransitionBitmapCacheKey = toTask;
-                    }
-                });
+                if (transitionBitmap != null) {
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            mThumbnailTransitionBitmapCache = transitionBitmap;
+                            mThumbnailTransitionBitmapCacheKey = toTask;
+                        }
+                    });
+                } else {
+                    Log.e(TAG, "Could not load thumbnail for task: " + toTask + " at transform: " +
+                            toTransform);
+                }
             }
         });
     }
@@ -774,7 +779,7 @@
         // Get the transform for the running task
         stackView.updateLayoutAlgorithm(true /* boundScroll */);
         stackView.updateToInitialState(true /* scrollToInitialState */);
-        mTmpTransform = stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
+        stackView.getStackAlgorithm().getStackTransformScreenCoordinates(launchTask,
                 stackView.getScroller().getStackScroll(), mTmpTransform, null);
         return mTmpTransform;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
index c234c34..8be9ca7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/activity/ConfigurationChangedEvent.java
@@ -24,8 +24,10 @@
 public class ConfigurationChangedEvent extends EventBus.AnimatedEvent {
 
     public final boolean fromMultiWindow;
+    public final boolean fromOrientationChange;
 
-    public ConfigurationChangedEvent(boolean fromMultiWindow) {
+    public ConfigurationChangedEvent(boolean fromMultiWindow, boolean fromOrientationChange) {
         this.fromMultiWindow = fromMultiWindow;
+        this.fromOrientationChange = fromOrientationChange;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
similarity index 78%
rename from packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
rename to packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
index 863f40b..f8b59c7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/ResetBackgroundScrimEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissAllTaskViewsEvent.java
@@ -17,10 +17,11 @@
 package com.android.systemui.recents.events.ui;
 
 import com.android.systemui.recents.events.EventBus;
+import com.android.systemui.recents.views.TaskView;
 
 /**
- * This is sent to reset the background scrim back to the initial state.
+ * This event is sent to request that all the {@link TaskView}s are dismissed.
  */
-public class ResetBackgroundScrimEvent extends EventBus.Event {
+public class DismissAllTaskViewsEvent extends EventBus.AnimatedEvent {
     // Simple event
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
index 1165f4e..1f8c644 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/events/ui/DismissTaskViewEvent.java
@@ -17,7 +17,6 @@
 package com.android.systemui.recents.events.ui;
 
 import com.android.systemui.recents.events.EventBus;
-import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.views.TaskView;
 
 /**
@@ -26,10 +25,8 @@
 public class DismissTaskViewEvent extends EventBus.AnimatedEvent {
 
     public final TaskView taskView;
-    public final Task task;
 
-    public DismissTaskViewEvent(TaskView taskView, Task task) {
+    public DismissTaskViewEvent(TaskView taskView) {
         this.taskView = taskView;
-        this.task = task;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java b/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
deleted file mode 100644
index fdd4c67..0000000
--- a/packages/SystemUI/src/com/android/systemui/recents/events/ui/UpdateBackgroundScrimEvent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * Copyright (C) 2016 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 com.android.systemui.recents.events.ui;
-
-import com.android.systemui.recents.events.EventBus;
-
-/**
- * This is sent to request an update to the background scrim.
- */
-public class UpdateBackgroundScrimEvent extends EventBus.Event {
-
-    public final float alpha;
-
-    public UpdateBackgroundScrimEvent(float alpha) {
-        this.alpha = alpha;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
index 5a2507d..df3f56c 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/model/TaskStack.java
@@ -222,6 +222,11 @@
             Task newFrontMostTask, AnimationProps animation, boolean fromDockGesture);
 
         /**
+         * Notifies when all tasks have been removed from the stack.
+         */
+        void onStackTasksRemoved(TaskStack stack);
+
+        /**
          * Notifies when tasks in the stack have been updated.
          */
         void onStackTasksUpdated(TaskStack stack);
@@ -510,6 +515,22 @@
     }
 
     /**
+     * Removes all tasks from the stack.
+     */
+    public void removeAllTasks() {
+        ArrayList<Task> tasks = mStackTaskList.getTasks();
+        for (int i = tasks.size() - 1; i >= 0; i--) {
+            Task t = tasks.get(i);
+            removeTaskImpl(mStackTaskList, t);
+            mRawTaskList.remove(t);
+        }
+        if (mCb != null) {
+            // Notify that all tasks have been removed
+            mCb.onStackTasksRemoved(this);
+        }
+    }
+
+    /**
      * Sets a few tasks in one go, without calling any callbacks.
      *
      * @param tasks the new set of tasks to replace the current set.
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
index 3d0e75a..5eb9fda 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskStackHorizontalGridView.java
@@ -158,6 +158,11 @@
     }
 
     @Override
+    public void onStackTasksRemoved(TaskStack stack) {
+        // Do nothing
+    }
+
+    @Override
     public void onStackTasksUpdated(TaskStack stack) {
         // Do nothing
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 9dc3fb1..9eec2ce 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -28,11 +28,13 @@
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
+import android.util.Log;
 import android.view.AppTransitionAnimationSpec;
 import android.view.IAppTransitionAnimationSpecsFuture;
 
@@ -252,12 +254,13 @@
     /**
      * Composes the transition spec when docking a task, which includes a full task bitmap.
      */
-    public List<AppTransitionAnimationSpec> composeDockAnimationSpec(
-            TaskView taskView, Rect transform) {
-        TaskViewTransform viewTransform = new TaskViewTransform();
-        viewTransform.fillIn(taskView);
-        return Collections.singletonList(new AppTransitionAnimationSpec(taskView.getTask().key.id,
-                RecentsTransitionHelper.composeTaskBitmap(taskView, viewTransform), transform));
+    public List<AppTransitionAnimationSpec> composeDockAnimationSpec(TaskView taskView,
+            Rect bounds) {
+        mTmpTransform.fillIn(taskView);
+        Task task = taskView.getTask();
+        Bitmap thumbnail = RecentsTransitionHelper.composeTaskBitmap(taskView, mTmpTransform);
+        return Collections.singletonList(new AppTransitionAnimationSpec(task.key.id, thumbnail,
+                bounds));
     }
 
     /**
@@ -336,18 +339,27 @@
         float scale = transform.scale;
         int fromWidth = (int) (transform.rect.width() * scale);
         int fromHeight = (int) (transform.rect.height() * scale);
-        Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight,
-                Bitmap.Config.ARGB_8888);
+        if (fromWidth == 0 || fromHeight == 0) {
+            Log.e(TAG, "Could not compose thumbnail for task: " + taskView.getTask() +
+                    " at transform: " + transform);
 
-        if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
-            b.eraseColor(0xFFff0000);
+            Bitmap b = Bitmap.createBitmap(1, 1, Bitmap.Config.ARGB_8888);
+            b.eraseColor(Color.TRANSPARENT);
+            return b;
         } else {
-            Canvas c = new Canvas(b);
-            c.scale(scale, scale);
-            taskView.draw(c);
-            c.setBitmap(null);
+            Bitmap b = Bitmap.createBitmap(fromWidth, fromHeight,
+                    Bitmap.Config.ARGB_8888);
+
+            if (RecentsDebugFlags.Static.EnableTransitionThumbnailDebugMode) {
+                b.eraseColor(0xFFff0000);
+            } else {
+                Canvas c = new Canvas(b);
+                c.scale(scale, scale);
+                taskView.draw(c);
+                c.setBitmap(null);
+            }
+            return b.createAshmemBitmap();
         }
-        return b.createAshmemBitmap();
     }
 
     private static Bitmap composeHeaderBitmap(TaskView taskView,
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 b23b01f..da2f721 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsView.java
@@ -58,10 +58,11 @@
 import com.android.systemui.recents.events.activity.HideStackActionButtonEvent;
 import com.android.systemui.recents.events.activity.LaunchTaskEvent;
 import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
+import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
+import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
+import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEndedEvent;
 import com.android.systemui.recents.events.ui.DraggingInRecentsEvent;
-import com.android.systemui.recents.events.ui.ResetBackgroundScrimEvent;
-import com.android.systemui.recents.events.ui.UpdateBackgroundScrimEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragDropTargetChangedEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragEndEvent;
 import com.android.systemui.recents.events.ui.dragndrop.DragStartEvent;
@@ -87,6 +88,9 @@
     private static final int DEFAULT_UPDATE_SCRIM_DURATION = 200;
     private static final float DEFAULT_SCRIM_ALPHA = 0.33f;
 
+    private static final int SHOW_STACK_ACTION_BUTTON_DURATION = 150;
+    private static final int HIDE_STACK_ACTION_BUTTON_DURATION = 100;
+
     private TaskStack mStack;
     private TaskStackView mTaskStackView;
     private TextView mStackActionButton;
@@ -99,7 +103,8 @@
     private Rect mSystemInsets = new Rect();
     private int mDividerSize;
 
-    private ColorDrawable mBackgroundScrim = new ColorDrawable(Color.BLACK);
+    private Drawable mBackgroundScrim = new ColorDrawable(
+            Color.argb((int) (DEFAULT_SCRIM_ALPHA * 255), 0, 0, 0)).mutate();
     private Animator mBackgroundScrimAnimator;
 
     private RecentsTransitionHelper mTransitionHelper;
@@ -135,10 +140,11 @@
                     R.dimen.recents_task_view_rounded_corners_radius);
             mStackActionButton = (TextView) inflater.inflate(R.layout.recents_stack_action_button,
                     this, false);
+            mStackActionButton.forceHasOverlappingRendering(false);
             mStackActionButton.setOnClickListener(new View.OnClickListener() {
                 @Override
                 public void onClick(View v) {
-                    // TODO: To be implemented
+                    EventBus.getDefault().send(new DismissAllTaskViewsEvent());
                 }
             });
             addView(mStackActionButton);
@@ -152,8 +158,6 @@
         }
         mEmptyView = (TextView) inflater.inflate(R.layout.recents_empty, this, false);
         addView(mEmptyView);
-
-        setBackground(mBackgroundScrim);
     }
 
     /**
@@ -179,14 +183,14 @@
 
         if (isResumingFromVisible) {
             // If we are already visible, then restore the background scrim
-            animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
+            animateBackgroundScrim(1f, DEFAULT_UPDATE_SCRIM_DURATION);
         } else {
             // If we are already occluded by the app, then set the final background scrim alpha now.
             // Otherwise, defer until the enter animation completes to animate the scrim alpha with
             // the tasks for the home animation.
             if (launchState.launchedViaDockGesture || launchState.launchedFromApp
                     || isTaskStackEmpty) {
-                mBackgroundScrim.setAlpha((int) (DEFAULT_SCRIM_ALPHA * 255));
+                mBackgroundScrim.setAlpha(255);
             } else {
                 mBackgroundScrim.setAlpha(0);
             }
@@ -215,6 +219,13 @@
         return mStack;
     }
 
+    /*
+     * Returns the window background scrim.
+     */
+    public Drawable getBackgroundScrim() {
+        return mBackgroundScrim;
+    }
+
     /**
      * Returns whether the last task launched was in the freeform stack or not.
      */
@@ -566,17 +577,21 @@
         RecentsActivityLaunchState launchState = Recents.getConfiguration().getLaunchState();
         if (!launchState.launchedViaDockGesture && !launchState.launchedFromApp
                 && mStack.getTaskCount() > 0) {
-            animateBackgroundScrim(DEFAULT_SCRIM_ALPHA,
+            animateBackgroundScrim(1f,
                     TaskStackAnimationHelper.ENTER_FROM_HOME_TRANSLATION_DURATION);
         }
     }
 
-    public final void onBusEvent(UpdateBackgroundScrimEvent event) {
-        animateBackgroundScrim(event.alpha, DEFAULT_UPDATE_SCRIM_DURATION);
+    public final void onBusEvent(AllTaskViewsDismissedEvent event) {
+        hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
     }
 
-    public final void onBusEvent(ResetBackgroundScrimEvent event) {
-        animateBackgroundScrim(DEFAULT_SCRIM_ALPHA, DEFAULT_UPDATE_SCRIM_DURATION);
+    public final void onBusEvent(DismissAllTaskViewsEvent event) {
+        SystemServicesProxy ssp = Recents.getSystemServices();
+        if (!ssp.hasDockedTask()) {
+            // Animate the background away only if we are dismissing Recents to home
+            animateBackgroundScrim(0f, DEFAULT_UPDATE_SCRIM_DURATION);
+        }
     }
 
     public final void onBusEvent(ShowStackActionButtonEvent event) {
@@ -584,7 +599,7 @@
             return;
         }
 
-        showStackActionButton(150, event.translate);
+        showStackActionButton(SHOW_STACK_ACTION_BUTTON_DURATION, event.translate);
     }
 
     public final void onBusEvent(HideStackActionButtonEvent event) {
@@ -592,7 +607,7 @@
             return;
         }
 
-        hideStackActionButton(100, true /* translate */);
+        hideStackActionButton(HIDE_STACK_ACTION_BUTTON_DURATION, true /* translate */);
     }
 
     /**
@@ -623,7 +638,6 @@
                             .alpha(1f)
                             .setDuration(duration)
                             .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
-                            .withLayer()
                             .start();
                 }
             });
@@ -669,7 +683,6 @@
                             postAnimationTrigger.decrement();
                         }
                     })
-                    .withLayer()
                     .start();
             postAnimationTrigger.increment();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
index 9c8189a..13ad9a5 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/SystemBarScrimViews.java
@@ -24,6 +24,7 @@
 import com.android.systemui.R;
 import com.android.systemui.recents.events.activity.DismissRecentsToHomeAnimationStarted;
 import com.android.systemui.recents.events.activity.EnterRecentsWindowAnimationCompletedEvent;
+import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
 
 /** Manages the scrims for the various system bars. */
 public class SystemBarScrimViews {
@@ -107,4 +108,14 @@
             animateNavBarScrimVisibility(false, animation);
         }
     }
+
+    public final void onBusEvent(DismissAllTaskViewsEvent event) {
+        if (mHasNavBarScrim) {
+            AnimationProps animation = new AnimationProps()
+                    .setDuration(AnimationProps.BOUNDS,
+                            TaskStackAnimationHelper.EXIT_TO_HOME_TRANSLATION_DURATION)
+                    .setInterpolator(AnimationProps.BOUNDS, Interpolators.FAST_OUT_SLOW_IN);
+            animateNavBarScrimVisibility(false, animation);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
index 8db81f7..1c433d8 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackAnimationHelper.java
@@ -31,6 +31,7 @@
 import com.android.systemui.recents.RecentsActivityLaunchState;
 import com.android.systemui.recents.RecentsConfiguration;
 import com.android.systemui.recents.misc.ReferenceCountedTrigger;
+import com.android.systemui.recents.misc.Utilities;
 import com.android.systemui.recents.model.Task;
 import com.android.systemui.recents.model.TaskStack;
 
@@ -277,7 +278,6 @@
     public void startExitToHomeAnimation(boolean animated,
             ReferenceCountedTrigger postAnimationTrigger) {
         TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
-        TaskStackViewScroller stackScroller = mStackView.getScroller();
         TaskStack stack = mStackView.getStack();
 
         // Break early if there are no tasks
@@ -313,8 +313,7 @@
                 taskAnimation = AnimationProps.IMMEDIATE;
             }
 
-            stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
-                    null);
+            mTmpTransform.fillIn(tv);
             mTmpTransform.alpha = 0f;
             mTmpTransform.rect.offset(0, offscreenYOffset);
             mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
@@ -328,8 +327,6 @@
     public void startLaunchTaskAnimation(TaskView launchingTaskView, boolean screenPinningRequested,
             final ReferenceCountedTrigger postAnimationTrigger) {
         Resources res = mStackView.getResources();
-        TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
-        TaskStackViewScroller stackScroller = mStackView.getScroller();
 
         int taskViewExitToAppDuration = res.getInteger(
                 R.integer.recents_task_exit_to_app_duration);
@@ -362,8 +359,7 @@
                         postAnimationTrigger.decrementOnAnimationEnd());
                 postAnimationTrigger.increment();
 
-                stackLayout.getStackTransform(task, stackScroller.getStackScroll(), mTmpTransform,
-                        null);
+                mTmpTransform.fillIn(tv);
                 mTmpTransform.alpha = 0f;
                 mTmpTransform.rect.offset(0, taskViewAffiliateGroupEnterOffset);
                 mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
@@ -374,16 +370,14 @@
     /**
      * Starts the delete animation for the specified {@link TaskView}.
      */
-    public void startDeleteTaskAnimation(Task deleteTask, final TaskView deleteTaskView,
+    public void startDeleteTaskAnimation(final TaskView deleteTaskView,
             final ReferenceCountedTrigger postAnimationTrigger) {
         Resources res = mStackView.getResources();
         TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
-        TaskStackViewScroller stackScroller = mStackView.getScroller();
 
         int taskViewRemoveAnimDuration = res.getInteger(
                 R.integer.recents_animate_task_view_remove_duration);
-        int taskViewRemoveAnimTranslationXPx = res.getDimensionPixelSize(
-                R.dimen.recents_task_view_remove_anim_translation_x);
+        int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left;
 
         // Disabling clipping with the stack while the view is animating away, this will get
         // restored when the task is next picked up from the view pool
@@ -399,14 +393,58 @@
         });
         postAnimationTrigger.increment();
 
-        stackLayout.getStackTransform(deleteTask, stackScroller.getStackScroll(), mTmpTransform,
-                null);
+        mTmpTransform.fillIn(deleteTaskView);
         mTmpTransform.alpha = 0f;
-        mTmpTransform.rect.offset(taskViewRemoveAnimTranslationXPx, 0);
+        mTmpTransform.rect.offset(offscreenXOffset, 0);
         mStackView.updateTaskViewToTransform(deleteTaskView, mTmpTransform, taskAnimation);
     }
 
     /**
+     * Starts the delete animation for all the {@link TaskView}s.
+     */
+    public void startDeleteAllTasksAnimation(final List<TaskView> taskViews,
+                                             final ReferenceCountedTrigger postAnimationTrigger) {
+        Resources res = mStackView.getResources();
+        TaskStackLayoutAlgorithm stackLayout = mStackView.getStackAlgorithm();
+
+        int taskViewRemoveAnimDuration = res.getInteger(
+                R.integer.recents_animate_task_views_remove_all_duration);
+        int offscreenXOffset = mStackView.getMeasuredWidth() - stackLayout.mTaskRect.left;
+
+        int taskViewCount = taskViews.size();
+        int startDelayMax = 125;
+
+        for (int i = taskViewCount - 1; i >= 0; i--) {
+            TaskView tv = taskViews.get(i);
+            int indexFromFront = taskViewCount - i - 1;
+            float x = Interpolators.ACCELERATE.getInterpolation((float) indexFromFront /
+                    taskViewCount);
+            int startDelay = (int) Utilities.mapRange(x, 0, startDelayMax);
+
+            // Disabling clipping with the stack while the view is animating away
+            tv.setClipViewInStack(false);
+
+            // Compose the new animation and transform and star the animation
+            AnimationProps taskAnimation = new AnimationProps(startDelay,
+                    taskViewRemoveAnimDuration, Interpolators.FAST_OUT_LINEAR_IN,
+                    new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    postAnimationTrigger.decrement();
+
+                    // Re-enable clipping with the stack (we will reuse this view)
+                    tv.setClipViewInStack(true);
+                }
+            });
+            postAnimationTrigger.increment();
+
+            mTmpTransform.fillIn(tv);
+            mTmpTransform.rect.offset(offscreenXOffset, 0);
+            mStackView.updateTaskViewToTransform(tv, mTmpTransform, taskAnimation);
+        }
+    }
+
+    /**
      * Starts the animation to focus the next {@link TaskView} when paging through recents.
      *
      * @return whether or not this will trigger a scroll in the stack
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index 4b1faf3..2508304 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -557,15 +557,17 @@
                 mInitialScrollP = Utilities.clamp(launchTaskIndex, mMinScrollP, mMaxScrollP);
                 mInitialNormX = null;
             } else {
-                float normX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
-                mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2)) -
-                        Math.max(0, mUnfocusedRange.getAbsoluteX(normX)));
+                // We are overriding the initial two task positions, so set the initial scroll
+                // position to match the second task (aka focused task) position
+                float initialTopNormX = getNormalizedXFromUnfocusedY(mInitialTopOffset, FROM_TOP);
+                mInitialScrollP = Math.max(mMinScrollP, Math.min(mMaxScrollP, (mNumStackTasks - 2))
+                        - Math.max(0, mUnfocusedRange.getAbsoluteX(initialTopNormX)));
 
                 // Set the initial scroll to the predefined state (which differs from the stack)
                 mInitialNormX = new float[] {
                         getNormalizedXFromUnfocusedY(mSystemInsets.bottom + mInitialBottomOffset,
                                 FROM_BOTTOM),
-                        normX
+                        initialTopNormX
                 };
             }
         }
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 04f153f..5416a48 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -72,6 +72,7 @@
 import com.android.systemui.recents.events.activity.ShowStackActionButtonEvent;
 import com.android.systemui.recents.events.ui.AllTaskViewsDismissedEvent;
 import com.android.systemui.recents.events.ui.DeleteTaskDataEvent;
+import com.android.systemui.recents.events.ui.DismissAllTaskViewsEvent;
 import com.android.systemui.recents.events.ui.DismissTaskViewEvent;
 import com.android.systemui.recents.events.ui.TaskViewDismissedEvent;
 import com.android.systemui.recents.events.ui.UpdateFreeformTaskViewVisibilityEvent;
@@ -1322,7 +1323,8 @@
         }
 
         // Update the stack action button visibility
-        if (mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) {
+        if (mStackScroller.getStackScroll() < SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
+                mStack.getTaskCount() > 0) {
             EventBus.getDefault().send(new ShowStackActionButtonEvent(false /* translate */));
         } else {
             EventBus.getDefault().send(new HideStackActionButtonEvent());
@@ -1447,6 +1449,26 @@
     }
 
     @Override
+    public void onStackTasksRemoved(TaskStack stack) {
+        // Reset the focused task
+        resetFocusedTask(getFocusedTask());
+
+        // Return all the views to the pool
+        List<TaskView> taskViews = new ArrayList<>();
+        taskViews.addAll(getTaskViews());
+        for (int i = taskViews.size() - 1; i >= 0; i--) {
+            mViewPool.returnViewToPool(taskViews.get(i));
+        }
+
+        // Remove all the ignore tasks
+        mIgnoreTasks.clear();
+
+        // If there are no remaining tasks, then just close recents
+        EventBus.getDefault().send(new AllTaskViewsDismissedEvent(
+                R.string.recents_empty_message_dismissed_all));
+    }
+
+    @Override
     public void onStackTasksUpdated(TaskStack stack) {
         // Update the layout and immediately layout
         updateLayoutAlgorithm(false /* boundScroll */);
@@ -1597,7 +1619,8 @@
 
         if (mEnterAnimationComplete) {
             if (prevScroll > SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
-                    curScroll <= SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) {
+                    curScroll <= SHOW_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
+                    mStack.getTaskCount() > 0) {
                 EventBus.getDefault().send(new ShowStackActionButtonEvent(true /* translate */));
             } else if (prevScroll < HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD &&
                     curScroll >= HIDE_STACK_ACTION_BUTTON_SCROLL_THRESHOLD) {
@@ -1705,14 +1728,42 @@
         }
     }
 
-    public final void onBusEvent(final DismissTaskViewEvent event) {
+    public final void onBusEvent(DismissTaskViewEvent event) {
         // For visible children, defer removing the task until after the animation
-        mAnimationHelper.startDeleteTaskAnimation(event.task, event.taskView,
-                event.getAnimationTrigger());
+        mAnimationHelper.startDeleteTaskAnimation(event.taskView, event.getAnimationTrigger());
+    }
+
+    public final void onBusEvent(final DismissAllTaskViewsEvent event) {
+        // Keep track of the tasks which will have their data removed
+        ArrayList<Task> tasks = new ArrayList<>(mStack.getStackTasks());
+        mAnimationHelper.startDeleteAllTasksAnimation(getTaskViews(), event.getAnimationTrigger());
+        event.addPostAnimationCallback(new Runnable() {
+            @Override
+            public void run() {
+                // Announce for accessibility
+                announceForAccessibility(getContext().getString(
+                        R.string.accessibility_recents_all_items_dismissed));
+
+                // Remove all tasks and delete the task data for all tasks
+                mStack.removeAllTasks();
+                for (int i = tasks.size() - 1; i >= 0; i--) {
+                    EventBus.getDefault().send(new DeleteTaskDataEvent(tasks.get(i)));
+                }
+
+                MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS_ALL);
+            }
+        });
+
     }
 
     public final void onBusEvent(TaskViewDismissedEvent event) {
-        removeTaskViewFromStack(event.taskView, event.task);
+        // Announce for accessibility
+        announceForAccessibility(getContext().getString(
+                R.string.accessibility_recents_item_dismissed, event.task.title));
+
+        // Remove the task from the stack
+        mStack.removeTask(event.task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
+                Interpolators.FAST_OUT_SLOW_IN), false /* fromDockGesture */);
         EventBus.getDefault().send(new DeleteTaskDataEvent(event.task));
 
         MetricsLogger.action(getContext(), MetricsEvent.OVERVIEW_DISMISS,
@@ -1948,28 +1999,16 @@
             }
         }
 
-        // Trigger a new layout and scroll to the initial state
-        mInitialState = event.fromMultiWindow
-                ? INITIAL_STATE_UPDATE_ALL
-                : INITIAL_STATE_UPDATE_LAYOUT_ONLY;
+        // Trigger a new layout and update to the initial state if necessary
+        if (event.fromMultiWindow) {
+            mInitialState = INITIAL_STATE_UPDATE_ALL;
+        } else if (event.fromOrientationChange) {
+            mInitialState = INITIAL_STATE_UPDATE_LAYOUT_ONLY;
+        }
         requestLayout();
     }
 
     /**
-     * Removes the task from the stack, and updates the focus to the next task in the stack if the
-     * removed TaskView was focused.
-     */
-    private void removeTaskViewFromStack(TaskView tv, Task task) {
-        // Announce for accessibility
-        tv.announceForAccessibility(getContext().getString(
-                R.string.accessibility_recents_item_dismissed, task.title));
-
-        // Remove the task from the stack
-        mStack.removeTask(task, new AnimationProps(DEFAULT_SYNC_STACK_DURATION,
-                Interpolators.FAST_OUT_SLOW_IN), false /* fromDockGesture */);
-    }
-
-    /**
      * Starts an alpha animation on the freeform workspace background.
      */
     private void animateFreeformWorkspaceBackgroundAlpha(int targetAlpha,
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index aed19c3..ee0de1a 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -356,6 +356,11 @@
             return;
         }
 
+        // Disallow tapping above and below the stack to dismiss recents
+        if (x > mSv.mLayoutAlgorithm.mStackRect.left && x < mSv.mLayoutAlgorithm.mStackRect.right) {
+            return;
+        }
+
         // If tapping on the freeform workspace background, just launch the first freeform task
         SystemServicesProxy ssp = Recents.getSystemServices();
         if (ssp.hasFreeformWorkspaceSupport()) {
@@ -507,13 +512,13 @@
         tv.setClipViewInStack(true);
         // Re-enable touch events from this task view
         tv.setTouchEnabled(true);
+        // Remove the task view from the stack
+        EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv));
         // Update the scroll to the final scroll position from onBeginDrag()
         mSv.getScroller().setStackScroll(mTargetStackScroll, null);
         // Update the focus state to the final focus state
         mSv.getStackAlgorithm().setFocusState(TaskStackLayoutAlgorithm.STATE_UNFOCUSED);
         mSv.getStackAlgorithm().clearUnfocusedTaskOverrides();
-        // Remove the task view from the stack
-        EventBus.getDefault().send(new TaskViewDismissedEvent(tv.getTask(), tv));
         // Stop tracking this deletion animation
         mSwipeHelperAnimations.remove(v);
         // Keep track of deletions by keyboard
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 c085d80..f8ed700 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -384,7 +384,7 @@
     void dismissTask() {
         // Animate out the view and call the callback
         final TaskView tv = this;
-        DismissTaskViewEvent dismissEvent = new DismissTaskViewEvent(tv, mTask);
+        DismissTaskViewEvent dismissEvent = new DismissTaskViewEvent(tv);
         dismissEvent.addPostAnimationCallback(new Runnable() {
             @Override
             public void run() {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
index dc76e61..b512393 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskViewTransform.java
@@ -226,4 +226,9 @@
         v.getViewBounds().setClipBottom(0);
         v.setLeftTopRightBottom(0, 0, 0, 0);
     }
+
+    @Override
+    public String toString() {
+        return "R: " + rect + " V: " + visible;
+    }
 }
diff --git a/proto/src/metrics_constants.proto b/proto/src/metrics_constants.proto
index d6f1499..a2cfae9 100644
--- a/proto/src/metrics_constants.proto
+++ b/proto/src/metrics_constants.proto
@@ -2017,6 +2017,9 @@
     // action pass package name of calling package.
     ACTION_SCOPED_DIRECTORY_ACCESS_DENIED_AND_PERSIST_BY_PACKAGE = 356;
 
+    // Logged when a user dismisses all task in overview
+    OVERVIEW_DISMISS_ALL = 357;
+
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
   }