Merge "Simplifying color extraction registration logic" into sc-v2-dev
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index 0e718ca..cc65cbf 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -14,12 +14,11 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<!-- NOTE! don't add dimensions for margins / gravity to root view in this file, they need to be
-     loaded at runtime. -->
 <com.android.quickstep.views.GoOverviewActionsView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_horizontal|bottom">
 
     <LinearLayout
         android:id="@+id/action_buttons"
diff --git a/quickstep/res/layout/overview_actions_container.xml b/quickstep/res/layout/overview_actions_container.xml
index 68680d3..0c2a28c 100644
--- a/quickstep/res/layout/overview_actions_container.xml
+++ b/quickstep/res/layout/overview_actions_container.xml
@@ -14,11 +14,10 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<!-- NOTE! don't add dimensions for margins / gravity to root view in this file, they need to be
-     loaded at runtime. -->
 <com.android.quickstep.views.OverviewActionsView xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="wrap_content">
+    android:layout_height="wrap_content"
+    android:layout_gravity="center_horizontal|bottom">
 
     <LinearLayout
         android:id="@+id/action_buttons"
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 5fc969d..4e97fbd 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -16,7 +16,6 @@
 
 <resources>
     <dimen name="task_thumbnail_icon_size">48dp</dimen>
-    <dimen name="task_thumbnail_icon_size_grid">40dp</dimen>
     <!-- For screens without rounded corners -->
     <dimen name="task_corner_radius_small">2dp</dimen>
     <!-- For Launchers that want to override the default dialog corner radius -->
@@ -31,18 +30,22 @@
 
     <dimen name="overview_minimum_next_prev_size">50dp</dimen>
     <dimen name="overview_task_margin">16dp</dimen>
+    <dimen name="overview_task_margin_grid">12dp</dimen>
 
     <!-- Overrideable in overlay that provides the Overview Actions. -->
     <dimen name="overview_actions_height">48dp</dimen>
-    <dimen name="overview_actions_bottom_margin_gesture">28dp</dimen>
-    <dimen name="overview_actions_bottom_margin_three_button">8dp</dimen>
+    <dimen name="overview_actions_margin_gesture">28dp</dimen>
+    <dimen name="overview_actions_top_margin_gesture_grid_portrait">19.37dp</dimen>
+    <dimen name="overview_actions_bottom_margin_gesture_grid_portrait">22dp</dimen>
+    <dimen name="overview_actions_top_margin_gesture_grid_landscape">19.1dp</dimen>
+    <dimen name="overview_actions_bottom_margin_gesture_grid_landscape">10dp</dimen>
+    <dimen name="overview_actions_margin_three_button">8dp</dimen>
     <dimen name="overview_actions_horizontal_margin">16dp</dimen>
 
-    <dimen name="overview_grid_top_margin">77dp</dimen>
-    <dimen name="overview_grid_bottom_margin">70dp</dimen>
-    <dimen name="overview_grid_side_margin">54dp</dimen>
-    <dimen name="overview_grid_row_spacing">42dp</dimen>
-    <dimen name="overview_grid_focus_vertical_margin">40dp</dimen>
+    <dimen name="overview_grid_side_margin">50dp</dimen>
+    <dimen name="overview_grid_row_spacing_portrait">37.13dp</dimen>
+    <dimen name="overview_grid_row_spacing_landscape">33.38dp</dimen>
+    <dimen name="overview_grid_focus_vertical_margin">0dp</dimen>
 
     <!-- These speeds are in dp/s -->
     <dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
@@ -51,6 +54,7 @@
     <dimen name="default_task_dismiss_drag_velocity_grid_focus_task">5dp</dimen>
 
     <dimen name="recents_page_spacing">16dp</dimen>
+    <dimen name="recents_page_spacing_grid">36dp</dimen>
     <dimen name="recents_clear_all_deadzone_vertical_margin">70dp</dimen>
 
     <!-- The speed in dp/s at which the user needs to be scrolling in recents such that we start
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 5250d18..e1d0574 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -210,6 +210,17 @@
         }
     }
 
+    /**
+     * {@code LauncherOverlayCallbacks} scroll amount.
+     * Indicates transition progress to -1 screen.
+     * @param progress From 0 to 1.
+     */
+    @Override
+    public void onScrollChanged(float progress) {
+        super.onScrollChanged(progress);
+        mDepthController.onOverlayScrollChanged(progress);
+    }
+
     @Override
     public void startIntentSenderForResult(IntentSender intent, int requestCode,
             Intent fillInIntent, int flagsMask, int flagsValues, int extraFlags, Bundle options) {
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 6cfbf62..aba16c2 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -117,6 +117,10 @@
     private WallpaperManagerCompat mWallpaperManager;
     private SurfaceControl mSurface;
     /**
+     * How visible the -1 overlay is, from 0 to 1.
+     */
+    private float mOverlayScrollProgress;
+    /**
      * Ratio from 0 to 1, where 0 is fully zoomed out, and 1 is zoomed in.
      * @see android.service.wallpaper.WallpaperService.Engine#onZoomChanged(float)
      */
@@ -255,12 +259,24 @@
         }
     }
 
+    public void onOverlayScrollChanged(float progress) {
+        // Round out the progress to dedupe frequent, non-perceptable updates
+        int progressI = (int) (progress * 256);
+        float progressF = progressI / 256f;
+        if (Float.compare(mOverlayScrollProgress, progressF) == 0) {
+            return;
+        }
+        mOverlayScrollProgress = progressF;
+        dispatchTransactionSurface(mDepth);
+    }
+
     private boolean dispatchTransactionSurface(float depth) {
         boolean supportsBlur = BlurUtils.supportsBlursOnWindows();
         if (supportsBlur && (mSurface == null || !mSurface.isValid())) {
             return false;
         }
         ensureDependencies();
+        depth = Math.max(depth, mOverlayScrollProgress);
         IBinder windowToken = mLauncher.getRootView().getWindowToken();
         if (windowToken != null) {
             mWallpaperManager.setWallpaperZoomOut(windowToken, depth);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 67ebc02..b89032e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -117,6 +117,24 @@
         dragLayerY += dragRect.top;
 
         DragOptions dragOptions = new DragOptions();
+        dragOptions.preDragCondition = new DragOptions.PreDragCondition() {
+            private DragView mDragView;
+
+            @Override
+            public boolean shouldStartDrag(double distanceDragged) {
+                return mDragView != null && mDragView.isAnimationFinished();
+            }
+
+            @Override
+            public void onPreDragStart(DropTarget.DragObject dragObject) {
+                mDragView = dragObject.dragView;
+            }
+
+            @Override
+            public void onPreDragEnd(DropTarget.DragObject dragObject, boolean dragStarted) {
+                mDragView = null;
+            }
+        };
         // TODO: open popup/pre-drag
         // PopupContainerWithArrow popupContainer = PopupContainerWithArrow.showForIcon(view);
         // if (popupContainer != null) {
@@ -155,6 +173,7 @@
 
         mDragObject = new DropTarget.DragObject(mActivity.getApplicationContext());
         mDragObject.originalView = originalView;
+        mDragObject.deferDragViewCleanupPostAnimation = false;
 
         mIsInPreDrag = mOptions.preDragCondition != null
                 && !mOptions.preDragCondition.shouldStartDrag(0);
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index c412ece..97f46a5 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1153,6 +1153,12 @@
                     mGestureState.getEndTarget(), duration,
                     mTaskAnimationManager.getCurrentCallbacks());
             if (mParallelRunningAnim != null) {
+                mParallelRunningAnim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mParallelRunningAnim = null;
+                    }
+                });
                 mParallelRunningAnim.start();
             }
         }
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index db56231..624ade2 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -210,14 +210,8 @@
             Rect gridRect = new Rect();
             calculateGridSize(context, dp, gridRect);
 
-            int verticalMargin = Math.max(
-                    res.getDimensionPixelSize(R.dimen.overview_grid_focus_vertical_margin),
-                    res.getDimensionPixelSize(R.dimen.overview_actions_height));
-            float taskHeight =
-                    gridRect.height() - verticalMargin * 2 - dp.overviewTaskThumbnailTopMarginPx;
-
             PointF taskDimension = getTaskDimension(context, dp);
-            float scale = taskHeight / taskDimension.y;
+            float scale = gridRect.height() / taskDimension.y;
             int outWidth = Math.round(scale * taskDimension.x);
             int outHeight = Math.round(scale * taskDimension.y);
 
@@ -225,19 +219,9 @@
             Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
         } else {
             int taskMargin = dp.overviewTaskMarginPx;
-            int proactiveRowAndMargin;
-            if (!TaskView.SHOW_PROACTIVE_ACTIONS || dp.isVerticalBarLayout()) {
-                // In Vertical Bar Layout the proactive row doesn't have its own space, it's inside
-                // the actions row.
-                proactiveRowAndMargin = 0;
-            } else {
-                proactiveRowAndMargin = res.getDimensionPixelSize(
-                        R.dimen.overview_proactive_row_height)
-                        + res.getDimensionPixelSize(R.dimen.overview_proactive_row_bottom_margin);
-            }
             calculateTaskSizeInternal(context, dp,
                     dp.overviewTaskThumbnailTopMarginPx,
-                    proactiveRowAndMargin + getOverviewActionsHeight(context, dp),
+                    getProactiveRowAndMargin(context, dp) + getOverviewActionsHeight(context, dp),
                     res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
                     outRect);
         }
@@ -299,13 +283,14 @@
      */
     public final void calculateGridSize(Context context, DeviceProfile dp, Rect outRect) {
         Resources res = context.getResources();
-        int topMargin = res.getDimensionPixelSize(R.dimen.overview_grid_top_margin);
-        int bottomMargin = res.getDimensionPixelSize(R.dimen.overview_grid_bottom_margin);
+        Rect insets = dp.getInsets();
+        int topMargin = dp.overviewTaskThumbnailTopMarginPx;
+        int bottomMargin =
+                getProactiveRowAndMargin(context, dp) + getOverviewActionsHeight(context, dp);
         int sideMargin = res.getDimensionPixelSize(R.dimen.overview_grid_side_margin);
 
-        Rect insets = dp.getInsets();
         outRect.set(0, 0, dp.widthPx, dp.heightPx);
-        outRect.inset(Math.max(insets.left, sideMargin), Math.max(insets.top, topMargin),
+        outRect.inset(Math.max(insets.left, sideMargin), insets.top + topMargin,
                 Math.max(insets.right, sideMargin), Math.max(insets.bottom, bottomMargin));
     }
 
@@ -318,8 +303,9 @@
         Rect gridRect = new Rect();
         calculateGridSize(context, dp, gridRect);
 
-        int rowSpacing = res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
-        float rowHeight = (gridRect.height() - rowSpacing) / 2f;
+        float rowHeight =
+                (gridRect.height() + dp.overviewTaskThumbnailTopMarginPx - dp.overviewRowSpacing)
+                        / 2f;
 
         PointF taskDimension = getTaskDimension(context, dp);
         float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / taskDimension.y;
@@ -328,7 +314,6 @@
 
         int gravity = Gravity.TOP;
         gravity |= orientedState.getRecentsRtlSetting(res) ? Gravity.RIGHT : Gravity.LEFT;
-        gridRect.inset(0, dp.overviewTaskThumbnailTopMarginPx, 0, 0);
         Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
     }
 
@@ -344,6 +329,21 @@
                 outRect);
     }
 
+    private int getProactiveRowAndMargin(Context context, DeviceProfile dp) {
+        Resources res = context.getResources();
+        int proactiveRowAndMargin;
+        if (!TaskView.SHOW_PROACTIVE_ACTIONS || dp.isVerticalBarLayout()) {
+            // In Vertical Bar Layout the proactive row doesn't have its own space, it's inside
+            // the actions row.
+            proactiveRowAndMargin = 0;
+        } else {
+            proactiveRowAndMargin = res.getDimensionPixelSize(
+                    R.dimen.overview_proactive_row_height)
+                    + res.getDimensionPixelSize(R.dimen.overview_proactive_row_bottom_margin);
+        }
+        return proactiveRowAndMargin;
+    }
+
     /** Gets the space that the overview actions will take, including bottom margin. */
     private int getOverviewActionsHeight(Context context, DeviceProfile dp) {
         Resources res = context.getResources();
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index 563bb53..a2d2179 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -16,7 +16,6 @@
 
 package com.android.quickstep.views;
 
-import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
 import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_SHARE;
 
 import android.content.Context;
@@ -33,7 +32,6 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.launcher3.util.MultiValueAlpha.AlphaProperty;
 import com.android.quickstep.SysUINavigationMode;
@@ -90,9 +88,6 @@
 
     protected T mCallbacks;
 
-    private float mModalness;
-    private float mModalTransformY;
-
     protected DeviceProfile mDp;
 
     public OverviewActionsView(Context context) {
@@ -225,29 +220,6 @@
         requestLayout();
     }
 
-    /**
-     * The current task is fully modal (modalness = 1) when it is shown on its own in a modal
-     * way. Modalness 0 means the task is shown in context with all the other tasks.
-     */
-    public void setTaskModalness(float modalness) {
-        mModalness = modalness;
-        applyTranslationY();
-    }
-
-    public void setModalTransformY(float modalTransformY) {
-        mModalTransformY = modalTransformY;
-        applyTranslationY();
-    }
-
-    private void applyTranslationY() {
-        setTranslationY(getModalTrans(mModalTransformY));
-    }
-
-    private float getModalTrans(float endTranslation) {
-        float progress = ACCEL_DEACCEL.getInterpolation(mModalness);
-        return Utilities.mapRange(progress, 0, endTranslation);
-    }
-
     /** Get the top margin associated with the action buttons in Overview. */
     public static int getOverviewActionsTopMarginPx(
             SysUINavigationMode.Mode mode, DeviceProfile dp) {
@@ -260,7 +232,7 @@
             return dp.overviewActionsMarginThreeButtonPx;
         }
 
-        return dp.overviewActionsMarginGesturePx;
+        return dp.overviewActionsTopMarginGesturePx;
     }
 
     /** Get the bottom margin associated with the action buttons in Overview. */
@@ -276,6 +248,6 @@
             return dp.overviewActionsMarginThreeButtonPx + inset;
         }
 
-        return dp.overviewActionsMarginGesturePx + inset;
+        return dp.overviewActionsBottomMarginGesturePx + inset;
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index b90389a..d00db2d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -83,7 +83,6 @@
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.SparseBooleanArray;
-import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -95,7 +94,6 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.view.animation.Interpolator;
-import android.widget.FrameLayout;
 import android.widget.ListView;
 import android.widget.OverScroller;
 
@@ -386,7 +384,6 @@
     protected final ACTIVITY_TYPE mActivity;
     private final float mFastFlingVelocity;
     private final RecentsModel mModel;
-    private final int mRowSpacing;
     private final int mGridSideMargin;
     private final ClearAllButton mClearAllButton;
     private final Rect mClearAllButtonDeadZoneRect = new Rect();
@@ -598,7 +595,6 @@
     public RecentsView(Context context, AttributeSet attrs, int defStyleAttr,
             BaseActivityInterface sizeStrategy) {
         super(context, attrs, defStyleAttr);
-        setPageSpacing(getResources().getDimensionPixelSize(R.dimen.recents_page_spacing));
         setEnableFreeScroll(true);
         mSizeStrategy = sizeStrategy;
         mActivity = BaseActivity.fromContext(context);
@@ -620,7 +616,6 @@
 
         mIsRtl = mOrientationHandler.getRecentsRtlSetting(getResources());
         setLayoutDirection(mIsRtl ? View.LAYOUT_DIRECTION_RTL : View.LAYOUT_DIRECTION_LTR);
-        mRowSpacing = getResources().getDimensionPixelSize(R.dimen.overview_grid_row_spacing);
         mGridSideMargin = getResources().getDimensionPixelSize(R.dimen.overview_grid_side_margin);
         mSquaredTouchSlop = squaredTouchSlop(context);
 
@@ -1351,6 +1346,7 @@
         DeviceProfile dp = mActivity.getDeviceProfile();
         setOverviewGridEnabled(
                 mActivity.getStateManager().getState().displayOverviewTasksAsGrid(dp));
+        setPageSpacing(dp.overviewPageSpacing);
 
         // Propagate DeviceProfile change event.
         mLiveTileTaskViewSimulator.setDp(dp);
@@ -1422,32 +1418,10 @@
         mTaskGridVerticalDiff = mLastComputedGridTaskSize.top - mLastComputedTaskSize.top;
         mTopBottomRowHeightDiff =
                 mLastComputedGridTaskSize.height() + dp.overviewTaskThumbnailTopMarginPx
-                        + mRowSpacing;
+                        + dp.overviewRowSpacing;
 
         // Force TaskView to update size from thumbnail
         updateTaskSize();
-
-        // Update ActionsView position
-        if (mActionsView != null) {
-            FrameLayout.LayoutParams layoutParams =
-                    (FrameLayout.LayoutParams) mActionsView.getLayoutParams();
-            if (dp.overviewShowAsGrid) {
-                layoutParams.gravity = Gravity.BOTTOM;
-                layoutParams.bottomMargin =
-                        dp.heightPx - mInsets.bottom - mLastComputedGridSize.bottom;
-                layoutParams.leftMargin = mLastComputedTaskSize.left;
-                layoutParams.rightMargin = dp.widthPx - mLastComputedTaskSize.right;
-                // When in modal state, remove bottom margin to avoid covering content.
-                mActionsView.setModalTransformY(layoutParams.bottomMargin);
-            } else {
-                layoutParams.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-                layoutParams.bottomMargin = 0;
-                layoutParams.leftMargin = 0;
-                layoutParams.rightMargin = 0;
-                mActionsView.setModalTransformY(0);
-            }
-            mActionsView.setLayoutParams(layoutParams);
-        }
     }
 
     /**
@@ -3947,7 +3921,6 @@
         boolean inPlaceLandscape = !mOrientationState.canRecentsActivityRotate()
                 && mOrientationState.getTouchRotation() != ROTATION_0;
         mActionsView.updateHiddenFlags(HIDDEN_NON_ZERO_ROTATION, modalness < 1 && inPlaceLandscape);
-        mActionsView.setTaskModalness(modalness);
     }
 
     @Nullable
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 3339bf1..010d15b 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -325,8 +325,17 @@
     <dimen name="task_thumbnail_icon_size">0dp</dimen>
     <dimen name="task_thumbnail_icon_size_grid">0dp</dimen>
     <dimen name="overview_task_margin">0dp</dimen>
-    <dimen name="overview_actions_bottom_margin_gesture">0dp</dimen>
-    <dimen name="overview_actions_bottom_margin_three_button">0dp</dimen>
+    <dimen name="overview_task_margin_grid">0dp</dimen>
+    <dimen name="overview_actions_margin_gesture">0dp</dimen>
+    <dimen name="overview_actions_top_margin_gesture_grid_portrait">0dp</dimen>
+    <dimen name="overview_actions_bottom_margin_gesture_grid_portrait">0dp</dimen>
+    <dimen name="overview_actions_top_margin_gesture_grid_landscape">0dp</dimen>
+    <dimen name="overview_actions_bottom_margin_gesture_grid_landscape">0dp</dimen>
+    <dimen name="overview_actions_margin_three_button">0dp</dimen>
+    <dimen name="overview_grid_row_spacing_portrait">0dp</dimen>
+    <dimen name="overview_grid_row_spacing_landscape">0dp</dimen>
+    <dimen name="recents_page_spacing">0dp</dimen>
+    <dimen name="recents_page_spacing_grid">0dp</dimen>
     <dimen name="split_placeholder_size">110dp</dimen>
 
 <!-- Workspace grid visualization parameters -->
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 256be27..740bf5a 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -184,7 +184,10 @@
     public int overviewTaskIconSizePx;
     public int overviewTaskThumbnailTopMarginPx;
     public final int overviewActionsMarginThreeButtonPx;
-    public final int overviewActionsMarginGesturePx;
+    public final int overviewActionsTopMarginGesturePx;
+    public final int overviewActionsBottomMarginGesturePx;
+    public int overviewPageSpacing;
+    public int overviewRowSpacing;
 
     // Widgets
     public final PointF appWidgetScale = new PointF(1.0f, 1.0f);
@@ -350,15 +353,36 @@
                 : 0;
 
         overviewShowAsGrid = isTablet && FeatureFlags.ENABLE_OVERVIEW_GRID.get();
-        overviewTaskMarginPx = res.getDimensionPixelSize(R.dimen.overview_task_margin);
-        overviewTaskIconSizePx = overviewShowAsGrid
-                ? res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_size_grid)
-                : res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
+        overviewTaskMarginPx = overviewShowAsGrid
+                ? res.getDimensionPixelSize(R.dimen.overview_task_margin_grid)
+                : res.getDimensionPixelSize(R.dimen.overview_task_margin);
+        overviewTaskIconSizePx = res.getDimensionPixelSize(R.dimen.task_thumbnail_icon_size);
         overviewTaskThumbnailTopMarginPx = overviewTaskIconSizePx + overviewTaskMarginPx * 2;
-        overviewActionsMarginGesturePx = res.getDimensionPixelSize(
-                R.dimen.overview_actions_bottom_margin_gesture);
+        if (overviewShowAsGrid) {
+            if (isLandscape) {
+                overviewActionsTopMarginGesturePx = res.getDimensionPixelSize(
+                        R.dimen.overview_actions_top_margin_gesture_grid_landscape);
+                overviewActionsBottomMarginGesturePx = res.getDimensionPixelSize(
+                        R.dimen.overview_actions_bottom_margin_gesture_grid_landscape);
+            } else {
+                overviewActionsTopMarginGesturePx = res.getDimensionPixelSize(
+                        R.dimen.overview_actions_top_margin_gesture_grid_portrait);
+                overviewActionsBottomMarginGesturePx = res.getDimensionPixelSize(
+                        R.dimen.overview_actions_bottom_margin_gesture_grid_portrait);
+            }
+        } else {
+            overviewActionsTopMarginGesturePx = res.getDimensionPixelSize(
+                    R.dimen.overview_actions_margin_gesture);
+            overviewActionsBottomMarginGesturePx = overviewActionsTopMarginGesturePx;
+        }
         overviewActionsMarginThreeButtonPx = res.getDimensionPixelSize(
-                R.dimen.overview_actions_bottom_margin_three_button);
+                R.dimen.overview_actions_margin_three_button);
+        overviewPageSpacing = overviewShowAsGrid
+                        ? res.getDimensionPixelSize(R.dimen.recents_page_spacing_grid)
+                        : res.getDimensionPixelSize(R.dimen.recents_page_spacing);
+        overviewRowSpacing = isLandscape
+                ? res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing_landscape)
+                : res.getDimensionPixelSize(R.dimen.overview_grid_row_spacing_portrait);
 
         // Calculate all of the remaining variables.
         extraSpace = updateAvailableDimensions(res);
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index e736022..07c2113 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -222,7 +222,8 @@
  * Default launcher application.
  */
 public class Launcher extends StatefulActivity<LauncherState> implements LauncherExterns,
-        Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin> {
+        Callbacks, InvariantDeviceProfile.OnIDPChangeListener, PluginListener<OverlayPlugin>,
+        LauncherOverlayCallbacks {
     public static final String TAG = "Launcher";
 
     public static final ActivityTracker<Launcher> ACTIVITY_TRACKER = new ActivityTracker<>();
@@ -622,7 +623,7 @@
     @Override
     public void setLauncherOverlay(LauncherOverlay overlay) {
         if (overlay != null) {
-            overlay.setOverlayCallbacks(new LauncherOverlayCallbacksImpl());
+            overlay.setOverlayCallbacks(this);
         }
         mWorkspace.setLauncherOverlay(overlay);
     }
@@ -1126,12 +1127,15 @@
         mAppWidgetHost.setActivityResumed(false);
     }
 
-    class LauncherOverlayCallbacksImpl implements LauncherOverlayCallbacks {
-
-        public void onScrollChanged(float progress) {
-            if (mWorkspace != null) {
-                mWorkspace.onOverlayScrollChanged(progress);
-            }
+    /**
+     * {@code LauncherOverlayCallbacks} scroll amount.
+     * Indicates transition progress to -1 screen.
+     * @param progress From 0 to 1.
+     */
+    @Override
+    public void onScrollChanged(float progress) {
+        if (mWorkspace != null) {
+            mWorkspace.onOverlayScrollChanged(progress);
         }
     }
 
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index d6704a6..57d6cc3 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -23,6 +23,8 @@
 import static com.android.launcher3.Utilities.getBadge;
 import static com.android.launcher3.util.Executors.MODEL_EXECUTOR;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
@@ -93,6 +95,8 @@
     private boolean mHasDrawn = false;
 
     final ValueAnimator mAnim;
+    // Whether mAnim has started. Unlike mAnim.isStarted(), this is true even after mAnim ends.
+    private boolean mAnimStarted;
 
     private int mLastTouchX;
     private int mLastTouchY;
@@ -170,6 +174,12 @@
                 animation.cancel();
             }
         });
+        mAnim.addListener(new AnimatorListenerAdapter() {
+            @Override
+            public void onAnimationStart(Animator animation) {
+                mAnimStarted = true;
+            }
+        });
 
         setDragRegion(new Rect(0, 0, width, height));
 
@@ -385,6 +395,10 @@
         }
     }
 
+    public boolean isAnimationFinished() {
+        return mAnimStarted && !mAnim.isRunning();
+    }
+
     /**
      * Move the window containing this view.
      *
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index e45b8f7..24d6fe5 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -142,7 +142,7 @@
         mSystemBackgroundColor = preloadColors[PRELOAD_BACKGROUND_COLOR_INDEX];
         mIsDarkMode = isDarkMode;
 
-        setInternalProgress(info.getProgressLevel());
+        setLevel(info.getProgressLevel());
         setIsStartable(info.isAppStartable());
     }