Merge changes I675dbe99,Ia6daa741 into sc-v2-dev

* changes:
  [Hotseat] Fix hotseat edu flicker
  [Hotseat] Show edu tip within screen bounds
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index d24d752..fcbea77 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -353,6 +353,7 @@
 
         mAppTransitionManager = new QuickstepTransitionManager(this);
         mAppTransitionManager.registerRemoteAnimations();
+        mAppTransitionManager.registerRemoteTransitions();
 
         internalBindToTIS();
     }
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 6298bb8..9fa0f1a 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -536,9 +536,4 @@
             pa.addFloat(recentsView, FULLSCREEN_PROGRESS, 1, 0, LINEAR);
         }
     }
-
-    /** Called when OverviewService is bound to this process */
-    void onOverviewServiceBound() {
-        // Do nothing
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
index ae6ea79..b0bd747 100644
--- a/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/LauncherActivityInterface.java
@@ -309,13 +309,6 @@
     }
 
     @Override
-    void onOverviewServiceBound() {
-        final BaseQuickstepLauncher activity = getCreatedActivity();
-        if (activity == null) return;
-        activity.getAppTransitionManager().registerRemoteTransitions();
-    }
-
-    @Override
     public @Nullable Animator getParallelAnimationToLauncher(GestureEndTarget endTarget,
             long duration, RecentsAnimationCallbacks callbacks) {
         LauncherTaskbarUIController uiController = getTaskbarController();
diff --git a/quickstep/src/com/android/quickstep/SystemUiProxy.java b/quickstep/src/com/android/quickstep/SystemUiProxy.java
index aea2d4c..61540d1 100644
--- a/quickstep/src/com/android/quickstep/SystemUiProxy.java
+++ b/quickstep/src/com/android/quickstep/SystemUiProxy.java
@@ -17,7 +17,6 @@
 
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 
-import android.app.ActivityManager;
 import android.app.PendingIntent;
 import android.app.PictureInPictureParams;
 import android.content.ComponentName;
@@ -54,6 +53,8 @@
 import com.android.wm.shell.startingsurface.IStartingWindowListener;
 import com.android.wm.shell.transition.IShellTransitions;
 
+import java.util.ArrayList;
+
 /**
  * Holds the reference to SystemUI.
  */
@@ -81,6 +82,7 @@
     private ISplitScreenListener mPendingSplitScreenListener;
     private IStartingWindowListener mPendingStartingWindowListener;
     private ISmartspaceCallback mPendingSmartspaceCallback;
+    private final ArrayList<RemoteTransitionCompat> mPendingRemoteTransitions = new ArrayList<>();
 
     // Used to dedupe calls to SystemUI
     private int mLastShelfHeight;
@@ -161,6 +163,10 @@
             setSmartspaceCallback(mPendingSmartspaceCallback);
             mPendingSmartspaceCallback = null;
         }
+        for (int i = mPendingRemoteTransitions.size() - 1; i >= 0; --i) {
+            registerRemoteTransition(mPendingRemoteTransitions.get(i));
+        }
+        mPendingRemoteTransitions.clear();
 
         if (mPendingSetNavButtonAlpha != null) {
             mPendingSetNavButtonAlpha.run();
@@ -688,6 +694,8 @@
             } catch (RemoteException e) {
                 Log.w(TAG, "Failed call registerRemoteTransition");
             }
+        } else {
+            mPendingRemoteTransitions.add(remoteTransition);
         }
     }
 
@@ -699,6 +707,7 @@
                 Log.w(TAG, "Failed call registerRemoteTransition");
             }
         }
+        mPendingRemoteTransitions.remove(remoteTransition);
     }
 
     //
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 3ce12c5..bb8473b 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -179,12 +179,6 @@
                         smartspaceTransitionController);
                 TouchInteractionService.this.initInputMonitor();
                 preloadOverview(true /* fromInit */);
-                mDeviceState.runOnUserUnlocked(() -> {
-                    final BaseActivityInterface ai =
-                            mOverviewComponentObserver.getActivityInterface();
-                    if (ai == null) return;
-                    ai.onOverviewServiceBound();
-                });
             });
             sIsInitialized = true;
         }
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 5fc0480..bc232a6 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -57,6 +57,7 @@
     <dimen name="widget_handle_margin">13dp</dimen>
     <dimen name="resize_frame_background_padding">24dp</dimen>
     <dimen name="resize_frame_margin">22dp</dimen>
+    <dimen name="resize_frame_invalid_drag_across_two_panel_opacity_margin">24dp</dimen>
 
     <!-- App widget reconfigure button -->
     <dimen name="widget_reconfigure_button_corner_radius">14dp</dimen>
diff --git a/src/com/android/launcher3/AppWidgetResizeFrame.java b/src/com/android/launcher3/AppWidgetResizeFrame.java
index ee71146..fef3f8f 100644
--- a/src/com/android/launcher3/AppWidgetResizeFrame.java
+++ b/src/com/android/launcher3/AppWidgetResizeFrame.java
@@ -2,6 +2,7 @@
 
 import static android.appwidget.AppWidgetHostView.getDefaultPaddingForWidget;
 
+import static com.android.launcher3.CellLayout.SPRING_LOADED_PROGRESS;
 import static com.android.launcher3.LauncherAnimUtils.LAYOUT_HEIGHT;
 import static com.android.launcher3.LauncherAnimUtils.LAYOUT_WIDTH;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_WIDGET_RESIZE_COMPLETED;
@@ -9,6 +10,8 @@
 import static com.android.launcher3.views.BaseDragLayer.LAYOUT_X;
 import static com.android.launcher3.views.BaseDragLayer.LAYOUT_Y;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
@@ -29,6 +32,7 @@
 
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
 import com.android.launcher3.dragndrop.DragLayer;
+import com.android.launcher3.keyboard.ViewGroupFocusHelper;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.InstanceIdSequence;
 import com.android.launcher3.model.data.ItemInfo;
@@ -49,12 +53,14 @@
     private static final String KEY_RECONFIGURABLE_WIDGET_EDUCATION_TIP_SEEN =
             "launcher.reconfigurable_widget_education_tip_seen";
     private static final Rect sTmpRect = new Rect();
+    private static final Rect sTmpRect2 = new Rect();
 
     private static final int HANDLE_COUNT = 4;
     private static final int INDEX_LEFT = 0;
     private static final int INDEX_TOP = 1;
     private static final int INDEX_RIGHT = 2;
     private static final int INDEX_BOTTOM = 3;
+    private static final float MIN_OPACITY_FOR_CELL_LAYOUT_DURING_INVALID_RESIZE = 0.5f;
 
     private final Launcher mLauncher;
     private final DragViewStateAnnouncer mStateAnnouncer;
@@ -103,6 +109,16 @@
 
     private final InstanceId logInstanceId = new InstanceIdSequence().newInstanceId();
 
+    private final ViewGroupFocusHelper mDragLayerRelativeCoordinateHelper;
+
+    /**
+     * In the two panel UI, it is not possible to resize a widget to cross its host
+     * {@link CellLayout}'s sibling. When this happens, we gradually reduce the opacity of the
+     * sibling {@link CellLayout} from 1f to
+     * {@link #MIN_OPACITY_FOR_CELL_LAYOUT_DURING_INVALID_RESIZE}.
+     */
+    private final float mDragAcrossTwoPanelOpacityMargin;
+
     private boolean mLeftBorderActive;
     private boolean mRightBorderActive;
     private boolean mTopBorderActive;
@@ -149,6 +165,10 @@
         for (int i = 0; i < HANDLE_COUNT; i++) {
             mSystemGestureExclusionRects.add(new Rect());
         }
+
+        mDragAcrossTwoPanelOpacityMargin = mLauncher.getResources().getDimensionPixelSize(
+                R.dimen.resize_frame_invalid_drag_across_two_panel_opacity_margin);
+        mDragLayerRelativeCoordinateHelper = new ViewGroupFocusHelper(mLauncher.getDragLayer());
     }
 
     @Override
@@ -359,6 +379,37 @@
             lp.y = sTmpRect.top;
         }
 
+        // Handle invalid resize across CellLayouts in the two panel UI.
+        if (mCellLayout.getParent() instanceof Workspace) {
+            Workspace workspace = (Workspace) mCellLayout.getParent();
+            CellLayout pairedCellLayout = workspace.getScreenPair(mCellLayout);
+            if (pairedCellLayout != null) {
+                Rect focusedCellLayoutBound = sTmpRect;
+                mDragLayerRelativeCoordinateHelper.viewToRect(mCellLayout, focusedCellLayoutBound);
+                Rect resizeFrameBound = sTmpRect2;
+                findViewById(R.id.widget_resize_frame).getGlobalVisibleRect(resizeFrameBound);
+                float progress = 1f;
+                if (workspace.indexOfChild(pairedCellLayout) < workspace.indexOfChild(mCellLayout)
+                        && mDeltaX < 0
+                        && resizeFrameBound.left < focusedCellLayoutBound.left) {
+                    // Resize from right to left.
+                    progress = (mDragAcrossTwoPanelOpacityMargin + mDeltaX)
+                            / mDragAcrossTwoPanelOpacityMargin;
+                } else if (workspace.indexOfChild(pairedCellLayout)
+                                > workspace.indexOfChild(mCellLayout)
+                        && mDeltaX > 0
+                        && resizeFrameBound.right > focusedCellLayoutBound.right) {
+                    // Resize from left to right.
+                    progress = (mDragAcrossTwoPanelOpacityMargin - mDeltaX)
+                            / mDragAcrossTwoPanelOpacityMargin;
+                }
+                float alpha = Math.max(MIN_OPACITY_FOR_CELL_LAYOUT_DURING_INVALID_RESIZE, progress);
+                float springLoadedProgress = Math.min(1f, 1f - progress);
+                updateInvalidResizeEffect(mCellLayout, pairedCellLayout, alpha,
+                        springLoadedProgress);
+            }
+        }
+
         requestLayout();
     }
 
@@ -515,13 +566,24 @@
         }
 
         final DragLayer.LayoutParams lp = (DragLayer.LayoutParams) getLayoutParams();
+        final CellLayout pairedCellLayout;
+        if (mCellLayout.getParent() instanceof Workspace) {
+            Workspace workspace = (Workspace) mCellLayout.getParent();
+            pairedCellLayout = workspace.getScreenPair(mCellLayout);
+        } else {
+            pairedCellLayout = null;
+        }
         if (!animate) {
             lp.width = newWidth;
             lp.height = newHeight;
             lp.x = newX;
             lp.y = newY;
             for (int i = 0; i < HANDLE_COUNT; i++) {
-                mDragHandles[i].setAlpha(1.0f);
+                mDragHandles[i].setAlpha(1f);
+            }
+            if (pairedCellLayout != null) {
+                updateInvalidResizeEffect(mCellLayout, pairedCellLayout, /* alpha= */ 1f,
+                        /* springLoadedProgress= */ 0f);
             }
             requestLayout();
         } else {
@@ -538,6 +600,10 @@
                 set.play(mFirstFrameAnimatorHelper.addTo(
                         ObjectAnimator.ofFloat(mDragHandles[i], ALPHA, 1f)));
             }
+            if (pairedCellLayout != null) {
+                updateInvalidResizeEffect(mCellLayout, pairedCellLayout, /* alpha= */ 1f,
+                        /* springLoadedProgress= */ 0f, /* animatorSet= */ set);
+            }
             set.setDuration(SNAP_DURATION);
             set.start();
         }
@@ -624,6 +690,52 @@
         }
     }
 
+    private void updateInvalidResizeEffect(CellLayout cellLayout, CellLayout pairedCellLayout,
+            float alpha, float springLoadedProgress) {
+        updateInvalidResizeEffect(cellLayout, pairedCellLayout, alpha,
+                springLoadedProgress, /* animatorSet= */ null);
+    }
+
+    private void updateInvalidResizeEffect(CellLayout cellLayout, CellLayout pairedCellLayout,
+            float alpha, float springLoadedProgress, @Nullable AnimatorSet animatorSet) {
+        int childCount = pairedCellLayout.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            View child = pairedCellLayout.getChildAt(i);
+            if (animatorSet != null) {
+                animatorSet.play(
+                        mFirstFrameAnimatorHelper.addTo(
+                                ObjectAnimator.ofFloat(child, ALPHA, alpha)));
+            } else {
+                child.setAlpha(alpha);
+            }
+        }
+        if (animatorSet != null) {
+            animatorSet.play(mFirstFrameAnimatorHelper.addTo(
+                    ObjectAnimator.ofFloat(cellLayout, SPRING_LOADED_PROGRESS,
+                            springLoadedProgress)));
+            animatorSet.play(mFirstFrameAnimatorHelper.addTo(
+                    ObjectAnimator.ofFloat(pairedCellLayout, SPRING_LOADED_PROGRESS,
+                            springLoadedProgress)));
+        } else {
+            cellLayout.setSpringLoadedProgress(springLoadedProgress);
+            pairedCellLayout.setSpringLoadedProgress(springLoadedProgress);
+        }
+
+        boolean shouldShowCellLayoutBorder = springLoadedProgress > 0f;
+        if (animatorSet != null) {
+            animatorSet.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animator) {
+                    cellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
+                    pairedCellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
+                }
+            });
+        } else {
+            cellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
+            pairedCellLayout.setIsDragOverlapping(shouldShowCellLayoutBorder);
+        }
+    }
+
     @Override
     protected boolean isOfType(int type) {
         return (type & TYPE_WIDGET_RESIZE_FRAME) != 0;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index fccb4d0..8a35185 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2128,7 +2128,7 @@
             actualIds.add(id);
         }
         int firstId = visibleIds.getArray().get(0);
-        int pairId = mWorkspace.getPagePair(firstId);
+        int pairId = mWorkspace.getScreenPair(firstId);
         // Double check that actual screenIds contains the visibleId, as empty screens are hidden
         // in single panel.
         if (actualIds.contains(firstId)) {
@@ -2212,7 +2212,7 @@
             // Some empty pages might have been removed while the phone was in a single panel
             // mode, so we want to add those empty pages back.
             IntSet screenIds = IntSet.wrap(orderedScreenIds);
-            orderedScreenIds.forEach(screenId -> screenIds.add(mWorkspace.getPagePair(screenId)));
+            orderedScreenIds.forEach(screenId -> screenIds.add(mWorkspace.getScreenPair(screenId)));
             orderedScreenIds = screenIds.getArray();
         }
 
diff --git a/src/com/android/launcher3/PagedView.java b/src/com/android/launcher3/PagedView.java
index a7198a8..d534c5d 100644
--- a/src/com/android/launcher3/PagedView.java
+++ b/src/com/android/launcher3/PagedView.java
@@ -208,7 +208,7 @@
     public void initParentViews(View parent) {
         if (mPageIndicatorViewId > -1) {
             mPageIndicator = parent.findViewById(mPageIndicatorViewId);
-            mPageIndicator.setMarkersCount(getChildCount());
+            mPageIndicator.setMarkersCount(getChildCount() / getPanelCount());
         }
     }
 
@@ -830,7 +830,7 @@
 
     private void dispatchPageCountChanged() {
         if (mPageIndicator != null) {
-            mPageIndicator.setMarkersCount(getChildCount());
+            mPageIndicator.setMarkersCount(getChildCount() / getPanelCount());
         }
         // This ensures that when children are added, they get the correct transforms / alphas
         // in accordance with any scroll effects.
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index bd2a14f..3faa3d0 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -651,7 +651,7 @@
 
             // If the icon was dragged from Hotseat, there is no page pair
             if (isTwoPanelEnabled() && !(mDragSourceInternal.getParent() instanceof Hotseat)) {
-                int pagePairScreenId = getPagePair(dragObject.dragInfo.screenId);
+                int pagePairScreenId = getScreenPair(dragObject.dragInfo.screenId);
                 CellLayout pagePair = mWorkspaceScreens.get(pagePairScreenId);
                 if (pagePair == null) {
                     // TODO: after http://b/198820019 is fixed, remove this
@@ -917,16 +917,33 @@
     }
 
     /**
-     * Returns the page that is shown together with the given page when two panel is enabled.
+     * Returns the screen ID of a page that is shown together with the given page screen ID when the
+     * two panel UI is enabled.
      */
-    public int getPagePair(int page) {
-        if (page % 2 == 0) {
-            return page + 1;
+    public int getScreenPair(int screenId) {
+        if (screenId % 2 == 0) {
+            return screenId + 1;
         } else {
-            return page - 1;
+            return screenId - 1;
         }
     }
 
+    /**
+     * Returns {@link CellLayout} that is shown together with the given {@link CellLayout} when the
+     * two panel UI is enabled.
+     */
+    @Nullable
+    public CellLayout getScreenPair(CellLayout cellLayout) {
+        if (!isTwoPanelEnabled()) {
+            return null;
+        }
+        int screenId = getIdForScreen(cellLayout);
+        if (screenId == -1) {
+            return null;
+        }
+        return getScreenWithId(getScreenPair(screenId));
+    }
+
     public void stripEmptyScreens() {
         if (mLauncher.isWorkspaceLoading()) {
             // Don't strip empty screens if the workspace is still loading.
@@ -959,7 +976,7 @@
             Iterator<Integer> removeScreensIterator = removeScreens.iterator();
             while (removeScreensIterator.hasNext()) {
                 int pageToRemove = removeScreensIterator.next();
-                int pagePair = getPagePair(pageToRemove);
+                int pagePair = getScreenPair(pageToRemove);
                 if (!removeScreens.contains(pagePair)) {
                     // The page pair isn't empty so we want to remove the current page from the
                     // removable pages' collection
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 2032b26..157df5d 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -162,7 +162,8 @@
             }
         }
 
-        if ((item instanceof AppInfo) || (item instanceof PendingAddItemInfo)) {
+        if ((item instanceof AppInfo) || (item instanceof WorkspaceItemInfo)
+                || (item instanceof PendingAddItemInfo)) {
             out.add(mActions.get(ADD_TO_WORKSPACE));
         }
     }
@@ -244,6 +245,13 @@
                     mLauncher.addPendingItem(info, Favorites.CONTAINER_DESKTOP,
                             screenId, coordinates, info.spanX, info.spanY);
                 }
+                else if (item instanceof WorkspaceItemInfo) {
+                    WorkspaceItemInfo info = ((WorkspaceItemInfo) item).clone();
+                    mLauncher.getModelWriter().addItemToDatabase(info,
+                            Favorites.CONTAINER_DESKTOP,
+                            screenId, coordinates[0], coordinates[1]);
+                    mLauncher.bindItems(Collections.singletonList(info), true, true);
+                }
             }));
             return true;
         } else if (action == MOVE_TO_WORKSPACE) {
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index ee5f7e4..3681704 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -714,6 +714,7 @@
 
     @Override
     public void drawOnScrim(Canvas canvas) {
+        if (!mHeader.isHeaderProtectionSupported()) return;
         mHeaderPaint.setColor(mHeaderColor);
         mHeaderPaint.setAlpha((int) (getAlpha() * Color.alpha(mHeaderColor)));
         if (mHeaderPaint.getColor() != mScrimColor && mHeaderPaint.getColor() != 0) {
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index a6d8552..fc78bea 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -39,7 +39,6 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.AnimatorListeners;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
 import com.android.launcher3.config.FeatureFlags;
@@ -61,7 +60,6 @@
         implements StateHandler<LauncherState>, OnDeviceProfileChangeListener {
     // This constant should match the second derivative of the animator interpolator.
     public static final float INTERP_COEFF = 1.7f;
-    private static final float CONTENT_VISIBLE_MAX_THRESHOLD = 0.5f;
 
     public static final FloatProperty<AllAppsTransitionController> ALL_APPS_PROGRESS =
             new FloatProperty<AllAppsTransitionController>("allAppsProgress") {
@@ -188,8 +186,7 @@
         int visibleElements = state.getVisibleElements(mLauncher);
         boolean hasAllAppsContent = (visibleElements & ALL_APPS_CONTENT) != 0;
 
-        Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE,
-                Interpolators.clampToProgress(LINEAR, 0, CONTENT_VISIBLE_MAX_THRESHOLD));
+        Interpolator allAppsFade = config.getInterpolator(ANIM_ALL_APPS_FADE, LINEAR);
         setter.setViewAlpha(mAppsView, hasAllAppsContent ? 1 : 0, allAppsFade);
 
         boolean shouldProtectHeader =
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
index 690e904..a395709 100644
--- a/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
+++ b/src/com/android/launcher3/model/data/WorkspaceItemInfo.java
@@ -204,7 +204,7 @@
     }
 
     @Override
-    public ItemInfoWithIcon clone() {
+    public WorkspaceItemInfo clone() {
         return new WorkspaceItemInfo(this);
     }
 }
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index bc3419a..454dc6e 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -480,12 +480,12 @@
 
     @Override
     protected void closeComplete() {
+        super.closeComplete();
         PopupContainerWithArrow openPopup = getOpen(mLauncher);
         if (openPopup == null || openPopup.mOriginalIcon != mOriginalIcon) {
             mOriginalIcon.setTextVisibility(mOriginalIcon.shouldTextBeVisible());
             mOriginalIcon.setForceHideDot(false);
         }
-        super.closeComplete();
     }
 
     /**
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index ab2652a..4894b3b 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -1,5 +1,5 @@
-/**
- * Copyright (C) 2019 The Android Open Source Project
+/*
+ * Copyright (C) 2015 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.
@@ -17,18 +17,31 @@
 
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
 
 import android.view.MotionEvent;
+import android.view.animation.Interpolator;
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.anim.Interpolators;
+import com.android.launcher3.states.StateAnimationConfig;
 
 /**
  * TouchController to switch between NORMAL and ALL_APPS state.
  */
 public class AllAppsSwipeController extends AbstractStateChangeTouchController {
 
+    private static final float ALLAPPS_STAGGERED_FADE_THRESHOLD = 0.5f;
+
+    public static final Interpolator ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER =
+            Interpolators.clampToProgress(LINEAR, 0, ALLAPPS_STAGGERED_FADE_THRESHOLD);
+    public static final Interpolator ALLAPPS_STAGGERED_FADE_LATE_RESPONDER =
+            Interpolators.clampToProgress(LINEAR, ALLAPPS_STAGGERED_FADE_THRESHOLD, 1f);
+
     public AllAppsSwipeController(Launcher l) {
         super(l, SingleAxisSwipeDetector.VERTICAL);
     }
@@ -65,12 +78,28 @@
     @Override
     protected float initCurrentAnimation() {
         float range = getShiftRange();
-        long maxAccuracy = (long) (2 * range);
+        StateAnimationConfig config = getConfigForStates(mFromState, mToState);
+        config.duration = (long) (2 * range);
+
         mCurrentAnimation = mLauncher.getStateManager()
-                .createAnimationToNewWorkspace(mToState, maxAccuracy);
+                .createAnimationToNewWorkspace(mToState, config);
         float startVerticalShift = mFromState.getVerticalProgress(mLauncher) * range;
         float endVerticalShift = mToState.getVerticalProgress(mLauncher) * range;
         float totalShift = endVerticalShift - startVerticalShift;
         return 1 / totalShift;
     }
+
+    @Override
+    protected StateAnimationConfig getConfigForStates(LauncherState fromState,
+            LauncherState toState) {
+        StateAnimationConfig config = super.getConfigForStates(fromState, toState);
+        if (fromState == NORMAL && toState == ALL_APPS) {
+            config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+            config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+        } else if (fromState == ALL_APPS && toState == NORMAL) {
+            config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+            config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+        }
+        return config;
+    }
 }