Merge changes from topic "allapps_bottomsheet_motion" into tm-dev

* changes:
  Tune AllApps bottom sheet VisD and motion
  Put taskbar all apps in separate overlay window and stash taskbar.
diff --git a/quickstep/res/layout/taskbar_all_apps.xml b/quickstep/res/layout/taskbar_all_apps.xml
index 11d75c7..7dc0cbe 100644
--- a/quickstep/res/layout/taskbar_all_apps.xml
+++ b/quickstep/res/layout/taskbar_all_apps.xml
@@ -14,12 +14,12 @@
      See the License for the specific language governing permissions and
      limitations under the License.
 -->
-<com.android.launcher3.taskbar.TaskbarAllAppsSlideInView
+<com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-    <com.android.launcher3.taskbar.TaskbarAllAppsContainerView
+    <com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView
         android:id="@+id/apps_view"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
@@ -52,5 +52,5 @@
         </com.android.launcher3.allapps.FloatingHeaderView>
 
         <include layout="@layout/all_apps_fast_scroller" />
-    </com.android.launcher3.taskbar.TaskbarAllAppsContainerView>
-</com.android.launcher3.taskbar.TaskbarAllAppsSlideInView>
+    </com.android.launcher3.taskbar.allapps.TaskbarAllAppsContainerView>
+</com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView>
diff --git a/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
new file mode 100644
index 0000000..17635df
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/BaseTaskbarContext.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2022 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.launcher3.taskbar;
+
+import android.content.Context;
+import android.view.ContextThemeWrapper;
+import android.view.LayoutInflater;
+
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.util.Themes;
+import com.android.launcher3.views.ActivityContext;
+
+import java.util.ArrayList;
+import java.util.List;
+
+// TODO(b/218912746): Share more behavior to avoid all apps context depending directly on taskbar.
+/** Base for common behavior between taskbar window contexts. */
+public abstract class BaseTaskbarContext extends ContextThemeWrapper implements ActivityContext,
+        DeviceProfileListenable {
+
+    protected final LayoutInflater mLayoutInflater;
+    private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
+
+    protected DeviceProfile mDeviceProfile;
+
+    public BaseTaskbarContext(Context windowContext) {
+        super(windowContext, Themes.getActivityThemeRes(windowContext));
+        mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
+    }
+
+    @Override
+    public final LayoutInflater getLayoutInflater() {
+        return mLayoutInflater;
+    }
+
+    @Override
+    public final DeviceProfile getDeviceProfile() {
+        return mDeviceProfile;
+    }
+
+    @Override
+    public final List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners() {
+        return mDPChangeListeners;
+    }
+
+    /** Updates the {@link DeviceProfile} instance to the latest representation of the screen. */
+    public abstract void updateDeviceProfile(DeviceProfile dp);
+
+    /** Callback invoked when a drag is initiated within this context. */
+    public abstract void onDragStart();
+
+    /** Callback invoked when a popup is shown or closed within this context. */
+    public abstract void onPopupVisibilityChanged(boolean isVisible);
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index fe091ef..8f0b934 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -42,10 +42,8 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Log;
-import android.view.ContextThemeWrapper;
 import android.view.Display;
 import android.view.Gravity;
-import android.view.LayoutInflater;
 import android.view.RoundedCorner;
 import android.view.View;
 import android.view.WindowManager;
@@ -58,11 +56,8 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DeviceProfile;
-import com.android.launcher3.DeviceProfile.DeviceProfileListenable;
-import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.R;
-import com.android.launcher3.Utilities;
 import com.android.launcher3.dot.DotInfo;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.folder.FolderIcon;
@@ -72,11 +67,10 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
 import com.android.launcher3.touch.ItemClickHandler;
-import com.android.launcher3.util.OnboardingPrefs;
 import com.android.launcher3.util.PackageManagerHelper;
 import com.android.launcher3.util.SettingsCache;
-import com.android.launcher3.util.Themes;
 import com.android.launcher3.util.TraceHelper;
 import com.android.launcher3.util.ViewCache;
 import com.android.launcher3.views.ActivityContext;
@@ -89,16 +83,13 @@
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
 import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
 
 /**
  * The {@link ActivityContext} with which we inflate Taskbar-related Views. This allows UI elements
  * that are used by both Launcher and Taskbar (such as Folder) to reference a generic
  * ActivityContext and BaseDragLayer instead of the Launcher activity and its DragLayer.
  */
-public class TaskbarActivityContext extends ContextThemeWrapper implements ActivityContext,
-        DeviceProfileListenable {
+public class TaskbarActivityContext extends BaseTaskbarContext {
 
     private static final boolean ENABLE_THREE_BUTTON_TASKBAR =
             SystemProperties.getBoolean("persist.debug.taskbar_three_button", false);
@@ -106,13 +97,8 @@
 
     private static final String WINDOW_TITLE = "Taskbar";
 
-    private final LayoutInflater mLayoutInflater;
     private final TaskbarDragLayer mDragLayer;
-    private final TaskbarAllAppsContainerView mAppsView;
     private final TaskbarControllers mControllers;
-    private final List<OnDeviceProfileChangeListener> mDPChangeListeners = new ArrayList<>();
-
-    private DeviceProfile mDeviceProfile;
 
     private final WindowManager mWindowManager;
     private final @Nullable RoundedCorner mLeftCorner, mRightCorner;
@@ -135,14 +121,12 @@
     private boolean mBindingItems = false;
 
     private final TaskbarShortcutMenuAccessibilityDelegate mAccessibilityDelegate;
-    private final OnboardingPrefs<TaskbarActivityContext> mOnboardingPrefs;
 
     public TaskbarActivityContext(Context windowContext, DeviceProfile dp,
             TaskbarNavButtonController buttonController, ScopedUnfoldTransitionProgressProvider
             unfoldTransitionProgressProvider) {
-        super(windowContext, Themes.getActivityThemeRes(windowContext));
+        super(windowContext);
         mDeviceProfile = dp;
-        mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
 
         mNavMode = SysUINavigationMode.getMode(windowContext);
         mImeDrawsImeNavBar = SysUINavigationMode.getImeDrawsImeNavBar(windowContext);
@@ -158,8 +142,6 @@
 
         mTaskbarHeightForIme = resources.getDimensionPixelSize(R.dimen.taskbar_ime_size);
 
-        mLayoutInflater = LayoutInflater.from(this).cloneInContext(this);
-
         // Inflate views.
         mDragLayer = (TaskbarDragLayer) mLayoutInflater.inflate(
                 R.layout.taskbar, null, false);
@@ -168,11 +150,6 @@
         FrameLayout navButtonsView = mDragLayer.findViewById(R.id.navbuttons_view);
         StashedHandleView stashedHandleView = mDragLayer.findViewById(R.id.stashed_handle);
 
-        TaskbarAllAppsSlideInView appsSlideInView =
-                (TaskbarAllAppsSlideInView) mLayoutInflater.inflate(R.layout.taskbar_all_apps,
-                        mDragLayer, false);
-        mAppsView = appsSlideInView.getAppsView();
-
         Display display = windowContext.getDisplay();
         Context c = display.getDisplayId() == Display.DEFAULT_DISPLAY
                 ? windowContext.getApplicationContext()
@@ -210,7 +187,7 @@
                 new TaskbarAutohideSuspendController(this),
                 new TaskbarPopupController(this),
                 new TaskbarForceVisibleImmersiveController(this),
-                new TaskbarAllAppsViewController(this, appsSlideInView));
+                new TaskbarAllAppsController(this));
     }
 
     public void init(TaskbarSharedState sharedState) {
@@ -236,7 +213,7 @@
         mWindowManager.addView(mDragLayer, mWindowLayoutParams);
     }
 
-    /** Updates the Device profile instance to the latest representation of the screen. */
+    @Override
     public void updateDeviceProfile(DeviceProfile dp) {
         mDeviceProfile = dp;
         updateIconSize(getResources());
@@ -297,31 +274,11 @@
     }
 
     @Override
-    public LayoutInflater getLayoutInflater() {
-        return mLayoutInflater;
-    }
-
-    @Override
     public TaskbarDragLayer getDragLayer() {
         return mDragLayer;
     }
 
     @Override
-    public TaskbarAllAppsContainerView getAppsView() {
-        return mAppsView;
-    }
-
-    @Override
-    public DeviceProfile getDeviceProfile() {
-        return mDeviceProfile;
-    }
-
-    @Override
-    public List<OnDeviceProfileChangeListener> getOnDeviceProfileChangeListeners() {
-        return mDPChangeListeners;
-    }
-
-    @Override
     public Rect getFolderBoundingBox() {
         return mControllers.taskbarDragLayerController.getFolderBoundingBox();
     }
@@ -412,11 +369,6 @@
     }
 
     @Override
-    public OnboardingPrefs<TaskbarActivityContext> getOnboardingPrefs() {
-        return mOnboardingPrefs;
-    }
-
-    @Override
     public boolean isBindingItems() {
         return mBindingItems;
     }
@@ -425,6 +377,16 @@
         mBindingItems = bindingItems;
     }
 
+    @Override
+    public void onDragStart() {
+        setTaskbarWindowFullscreen(true);
+    }
+
+    @Override
+    public void onPopupVisibilityChanged(boolean isVisible) {
+        setTaskbarWindowFocusable(isVisible);
+    }
+
     /**
      * Sets a new data-source for this taskbar instance
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsViewController.java
deleted file mode 100644
index 2670200..0000000
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsViewController.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2022 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.launcher3.taskbar;
-
-import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
-
-import com.android.launcher3.appprediction.AppsDividerView;
-import com.android.launcher3.appprediction.PredictionRowView;
-import com.android.launcher3.config.FeatureFlags;
-import com.android.launcher3.model.data.AppInfo;
-import com.android.launcher3.model.data.ItemInfo;
-
-import java.util.List;
-
-/** Handles the {@link TaskbarAllAppsContainerView} initialization and updates. */
-public final class TaskbarAllAppsViewController {
-
-    private final TaskbarActivityContext mContext;
-    private final TaskbarAllAppsSlideInView mSlideInView;
-    private final TaskbarAllAppsContainerView mAppsView;
-
-    public TaskbarAllAppsViewController(
-            TaskbarActivityContext context, TaskbarAllAppsSlideInView slideInView) {
-        mContext = context;
-        mSlideInView = slideInView;
-        mAppsView = mSlideInView.getAppsView();
-    }
-
-    /** Initialize the controller. */
-    public void init(TaskbarControllers controllers) {
-        if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
-            return;
-        }
-
-        mAppsView.setOnIconLongClickListener(
-                controllers.taskbarDragController::startDragOnLongClick);
-        mAppsView.getFloatingHeaderView().findFixedRowByType(
-                PredictionRowView.class).setOnIconLongClickListener(
-                controllers.taskbarDragController::startDragOnLongClick);
-    }
-
-    /** Binds the current {@link AppInfo} instances to the {@link TaskbarAllAppsContainerView}. */
-    public void setApps(AppInfo[] apps, int flags) {
-        if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
-            mAppsView.getAppsStore().setApps(apps, flags);
-        }
-    }
-
-    /** Binds the current app predictions to all apps {@link PredictionRowView}. */
-    public void setPredictedApps(List<ItemInfo> predictedApps) {
-        if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
-            PredictionRowView<?> predictionRowView =
-                    mAppsView.getFloatingHeaderView().findFixedRowByType(PredictionRowView.class);
-            predictionRowView.setPredictedApps(predictedApps);
-        }
-    }
-
-    /** Opens the {@link TaskbarAllAppsContainerView}. */
-    public void show() {
-        if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
-            return;
-        }
-
-        mAppsView.getFloatingHeaderView().findFixedRowByType(AppsDividerView.class)
-                .setShowAllAppsLabel(
-                        !mContext.getOnboardingPrefs().hasReachedMaxCount(ALL_APPS_VISITED_COUNT));
-        mContext.getOnboardingPrefs().incrementEventCount(ALL_APPS_VISITED_COUNT);
-        mContext.setTaskbarWindowFullscreen(true);
-        mSlideInView.show();
-    }
-}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 21fbb3b..d2e24e5 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -20,6 +20,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
+import com.android.launcher3.taskbar.allapps.TaskbarAllAppsController;
 import com.android.systemui.shared.rotation.RotationButtonController;
 
 import java.io.PrintWriter;
@@ -48,7 +49,7 @@
     public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
     public final TaskbarPopupController taskbarPopupController;
     public final TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController;
-    public final TaskbarAllAppsViewController taskbarAllAppsViewController;
+    public final TaskbarAllAppsController taskbarAllAppsController;
 
     @Nullable private LoggableTaskbarController[] mControllersToLog = null;
 
@@ -74,7 +75,7 @@
             TaskbarAutohideSuspendController taskbarAutoHideSuspendController,
             TaskbarPopupController taskbarPopupController,
             TaskbarForceVisibleImmersiveController taskbarForceVisibleImmersiveController,
-            TaskbarAllAppsViewController taskbarAllAppsViewController) {
+            TaskbarAllAppsController taskbarAllAppsController) {
         this.taskbarActivityContext = taskbarActivityContext;
         this.taskbarDragController = taskbarDragController;
         this.navButtonController = navButtonController;
@@ -91,7 +92,7 @@
         this.taskbarAutohideSuspendController = taskbarAutoHideSuspendController;
         this.taskbarPopupController = taskbarPopupController;
         this.taskbarForceVisibleImmersiveController = taskbarForceVisibleImmersiveController;
-        this.taskbarAllAppsViewController = taskbarAllAppsViewController;
+        this.taskbarAllAppsController = taskbarAllAppsController;
     }
 
     /**
@@ -115,7 +116,7 @@
         taskbarEduController.init(this);
         taskbarPopupController.init(this);
         taskbarForceVisibleImmersiveController.init(this);
-        taskbarAllAppsViewController.init(this);
+        taskbarAllAppsController.init(this);
 
         mControllersToLog = new LoggableTaskbarController[] {
                 taskbarDragController, navButtonController, navbarButtonsViewController,
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 6a2f622..c9f7f7e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -75,7 +75,7 @@
 /**
  * Handles long click on Taskbar items to start a system drag and drop operation.
  */
-public class TaskbarDragController extends DragController<TaskbarActivityContext> implements
+public class TaskbarDragController extends DragController<BaseTaskbarContext> implements
         TaskbarControllers.LoggableTaskbarController {
 
     private static boolean DEBUG_DRAG_SHADOW_SURFACE = false;
@@ -95,7 +95,7 @@
     // Animation for the drag shadow back into position after an unsuccessful drag
     private ValueAnimator mReturnAnimator;
 
-    public TaskbarDragController(TaskbarActivityContext activity) {
+    public TaskbarDragController(BaseTaskbarContext activity) {
         super(activity);
         Resources resources = mActivity.getResources();
         mDragIconSize = resources.getDimensionPixelSize(R.dimen.taskbar_icon_drag_icon_size);
@@ -110,7 +110,7 @@
      * generate the ClipDescription and Intent.
      * @return Whether {@link View#startDragAndDrop} started successfully.
      */
-    protected boolean startDragOnLongClick(View view) {
+    public boolean startDragOnLongClick(View view) {
         return startDragOnLongClick(view, null, null);
     }
 
@@ -131,8 +131,7 @@
         }
 
         BubbleTextView btv = (BubbleTextView) view;
-
-        mActivity.setTaskbarWindowFullscreen(true);
+        mActivity.onDragStart();
         btv.post(() -> {
             DragView dragView = startInternalDrag(btv, dragPreviewProvider);
             if (iconShift != null) {
@@ -185,7 +184,7 @@
             }
         };
         if (FeatureFlags.ENABLE_TASKBAR_POPUP_MENU.get()) {
-            PopupContainerWithArrow<TaskbarActivityContext> popupContainer =
+            PopupContainerWithArrow<BaseTaskbarContext> popupContainer =
                     mControllers.taskbarPopupController.showForIcon(btv);
             if (popupContainer != null) {
                 dragOptions.preDragCondition = popupContainer.createPreDragCondition(false);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java
index cf28eff..7a42432 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragView.java
@@ -25,8 +25,8 @@
  * while the pre-drag is still in progress (i.e. when the long press popup is still open). After
  * that ends, we switch to a system drag and drop view instead.
  */
-public class TaskbarDragView extends DragView<TaskbarActivityContext> {
-    public TaskbarDragView(TaskbarActivityContext launcher, Drawable drawable, int registrationX,
+public class TaskbarDragView extends DragView<BaseTaskbarContext> {
+    public TaskbarDragView(BaseTaskbarContext launcher, Drawable drawable, int registrationX,
             int registrationY, float initialScale, float scaleOnDrop, float finalScaleDps) {
         super(launcher, drawable, registrationX, registrationY, initialScale, scaleOnDrop,
                 finalScaleDps);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 2e18a40..62392ee 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -158,7 +158,7 @@
             mPredictedItems = item.items;
             commitItemsToUI();
         } else if (item.containerId == Favorites.CONTAINER_PREDICTION) {
-            mControllers.taskbarAllAppsViewController.setPredictedApps(item.items);
+            mControllers.taskbarAllAppsController.setPredictedApps(item.items);
         }
     }
 
@@ -201,7 +201,7 @@
 
     @Override
     public void bindAllApplications(AppInfo[] apps, int flags) {
-        mControllers.taskbarAllAppsViewController.setApps(apps, flags);
+        mControllers.taskbarAllAppsController.setApps(apps, flags);
     }
 
     protected void dumpLogs(String prefix, PrintWriter pw) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 68459ab..ea4fe34 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -52,7 +52,7 @@
  */
 public class TaskbarPopupController implements TaskbarControllers.LoggableTaskbarController {
 
-    private static final SystemShortcut.Factory<TaskbarActivityContext>
+    private static final SystemShortcut.Factory<BaseTaskbarContext>
             APP_INFO = SystemShortcut.AppInfo::new;
 
     private final TaskbarActivityContext mContext;
@@ -121,8 +121,8 @@
      * Shows the notifications and deep shortcuts associated with a Taskbar {@param icon}.
      * @return the container if shown or null.
      */
-    public PopupContainerWithArrow<TaskbarActivityContext> showForIcon(BubbleTextView icon) {
-        TaskbarActivityContext context = ActivityContext.lookupContext(icon.getContext());
+    public PopupContainerWithArrow<BaseTaskbarContext> showForIcon(BubbleTextView icon) {
+        BaseTaskbarContext context = ActivityContext.lookupContext(icon.getContext());
         if (PopupContainerWithArrow.getOpen(context) != null) {
             // There is already an items container open, so don't open this one.
             icon.clearFocus();
@@ -133,11 +133,11 @@
             return null;
         }
 
-        final PopupContainerWithArrow<TaskbarActivityContext> container =
-                (PopupContainerWithArrow) context.getLayoutInflater().inflate(
+        final PopupContainerWithArrow<BaseTaskbarContext> container =
+                (PopupContainerWithArrow<BaseTaskbarContext>) context.getLayoutInflater().inflate(
                         R.layout.popup_container, context.getDragLayer(), false);
         container.addOnAttachStateChangeListener(
-                new PopupLiveUpdateHandler<TaskbarActivityContext>(mContext, container) {
+                new PopupLiveUpdateHandler<BaseTaskbarContext>(context, container) {
                     @Override
                     protected void showPopupContainerForIcon(BubbleTextView originalIcon) {
                         showForIcon(originalIcon);
@@ -157,10 +157,9 @@
         container.requestFocus();
 
         // Make focusable to receive back events
-        mControllers.taskbarActivityContext.setTaskbarWindowFocusable(true);
+        context.onPopupVisibilityChanged(true);
         container.setOnCloseCallback(() -> {
-            mControllers.taskbarActivityContext.getDragLayer().post(
-                    () -> mControllers.taskbarActivityContext.setTaskbarWindowFocusable(false));
+            context.getDragLayer().post(() -> context.onPopupVisibilityChanged(false));
             container.setOnCloseCallback(null);
         });
 
@@ -207,7 +206,8 @@
             iconShift.x = mIconLastTouchPos.x - sv.getIconCenter().x;
             iconShift.y = mIconLastTouchPos.y - mContext.getDeviceProfile().iconSizePx;
 
-            mControllers.taskbarDragController.startDragOnLongClick(sv, iconShift);
+            ((TaskbarDragController) ActivityContext.lookupContext(
+                    v.getContext()).getDragController()).startDragOnLongClick(sv, iconShift);
 
             return false;
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 335b637..1d5fa4d 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -51,11 +51,12 @@
     public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
     public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible
     public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
+    public static final int FLAG_STASHED_IN_APP_ALL_APPS = 1 << 7; // All apps is visible.
 
     // If we're in an app and any of these flags are enabled, taskbar should be stashed.
     private static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
             | FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
-            | FLAG_STASHED_IN_APP_IME;
+            | FLAG_STASHED_IN_APP_IME | FLAG_STASHED_IN_APP_ALL_APPS;
 
     // If any of these flags are enabled, inset apps by our stashed height instead of our unstashed
     // height. This way the reported insets are consistent even during transitions out of the app.
@@ -585,6 +586,7 @@
         str.add((flags & FLAG_STASHED_IN_APP_IME) != 0 ? "FLAG_STASHED_IN_APP_IME" : "");
         str.add((flags & FLAG_IN_STASHED_LAUNCHER_STATE) != 0
                 ? "FLAG_IN_STASHED_LAUNCHER_STATE" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_ALL_APPS) != 0 ? "FLAG_STASHED_IN_APP_ALL_APPS" : "");
         return str.toString();
     }
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 8b6831b..153ed14 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -306,7 +306,7 @@
         }
 
         public View.OnClickListener getAllAppsButtonClickListener() {
-            return v -> mControllers.taskbarAllAppsViewController.show();
+            return v -> mControllers.taskbarAllAppsController.show();
         }
 
         public View.OnLongClickListener getIconOnLongClickListener() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsContainerView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
similarity index 83%
rename from quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsContainerView.java
rename to quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
index d6eb716..b36b9f1 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsContainerView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContainerView.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.launcher3.taskbar;
+package com.android.launcher3.taskbar.allapps;
 
 import android.content.Context;
 import android.util.AttributeSet;
@@ -29,10 +29,7 @@
 import com.android.launcher3.allapps.search.SearchAdapterProvider;
 
 /** All apps container accessible from taskbar. */
-public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<TaskbarActivityContext> {
-    public TaskbarAllAppsContainerView(Context context) {
-        this(context, null);
-    }
+public class TaskbarAllAppsContainerView extends BaseAllAppsContainerView<TaskbarAllAppsContext> {
 
     public TaskbarAllAppsContainerView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -44,8 +41,8 @@
 
     @Override
     protected SearchAdapterProvider<?> createMainAdapterProvider() {
-        // Task bar all apps does not yet support search, so this implementation is minimal.
-        return new SearchAdapterProvider<TaskbarActivityContext>(mActivityContext) {
+        // Taskbar all apps does not yet support search, so this implementation is minimal.
+        return new SearchAdapterProvider<TaskbarAllAppsContext>(mActivityContext) {
             @Override
             public boolean launchHighlightedItem() {
                 return false;
@@ -79,8 +76,7 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        // TODO(b/204696617): Switch to status bar insets once they work.
-        setInsets(insets.getInsets(WindowInsets.Type.tappableElement()).toRect());
+        setInsets(insets.getInsets(WindowInsets.Type.systemBars()).toRect());
         return super.onApplyWindowInsets(insets);
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
new file mode 100644
index 0000000..4245119
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsContext.java
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2022 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.launcher3.taskbar.allapps;
+
+import static android.view.KeyEvent.ACTION_UP;
+import static android.view.KeyEvent.KEYCODE_BACK;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import android.content.Context;
+import android.view.KeyEvent;
+import android.view.View;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.dot.DotInfo;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.popup.PopupDataProvider;
+import com.android.launcher3.taskbar.BaseTaskbarContext;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarDragController;
+import com.android.launcher3.taskbar.TaskbarStashController;
+import com.android.launcher3.util.OnboardingPrefs;
+import com.android.launcher3.util.TouchController;
+import com.android.launcher3.views.BaseDragLayer;
+
+/**
+ * Window context for the taskbar all apps overlay.
+ * <p>
+ * All apps has its own window and needs a window context. Some properties are delegated to the
+ * {@link TaskbarActivityContext} such as {@link DeviceProfile} and {@link PopupDataProvider}.
+ */
+class TaskbarAllAppsContext extends BaseTaskbarContext {
+    private final TaskbarActivityContext mTaskbarContext;
+    private final OnboardingPrefs<TaskbarAllAppsContext> mOnboardingPrefs;
+
+    private final TaskbarAllAppsViewController mAllAppsViewController;
+    private final TaskbarDragController mDragController;
+    private final TaskbarAllAppsDragLayer mDragLayer;
+    private final TaskbarAllAppsContainerView mAppsView;
+
+    TaskbarAllAppsContext(
+            TaskbarActivityContext taskbarContext,
+            TaskbarAllAppsController windowController,
+            TaskbarStashController taskbarStashController) {
+        super(taskbarContext.createWindowContext(TYPE_APPLICATION_OVERLAY, null));
+        mTaskbarContext = taskbarContext;
+        mDeviceProfile = taskbarContext.getDeviceProfile();
+        mDragController = new TaskbarDragController(this);
+        mOnboardingPrefs = new OnboardingPrefs<>(this, Utilities.getPrefs(this));
+
+        mDragLayer = new TaskbarAllAppsDragLayer(this);
+        TaskbarAllAppsSlideInView slideInView = (TaskbarAllAppsSlideInView) mLayoutInflater.inflate(
+                R.layout.taskbar_all_apps, mDragLayer, false);
+        mAllAppsViewController = new TaskbarAllAppsViewController(
+                this,
+                slideInView,
+                windowController,
+                taskbarStashController);
+        mAppsView = slideInView.getAppsView();
+    }
+
+    TaskbarAllAppsViewController getAllAppsViewController() {
+        return mAllAppsViewController;
+    }
+
+    @Override
+    public TaskbarDragController getDragController() {
+        return mDragController;
+    }
+
+    @Override
+    public TaskbarAllAppsDragLayer getDragLayer() {
+        return mDragLayer;
+    }
+
+    @Override
+    public TaskbarAllAppsContainerView getAppsView() {
+        return mAppsView;
+    }
+
+    @Override
+    public OnboardingPrefs<TaskbarAllAppsContext> getOnboardingPrefs() {
+        return mOnboardingPrefs;
+    }
+
+    @Override
+    public boolean isBindingItems() {
+        return mTaskbarContext.isBindingItems();
+    }
+
+    @Override
+    public View.OnClickListener getItemOnClickListener() {
+        return mTaskbarContext.getItemOnClickListener();
+    }
+
+    @Override
+    public PopupDataProvider getPopupDataProvider() {
+        return mTaskbarContext.getPopupDataProvider();
+    }
+
+    @Override
+    public DotInfo getDotInfoForItem(ItemInfo info) {
+        return mTaskbarContext.getDotInfoForItem(info);
+    }
+
+    @Override
+    public void updateDeviceProfile(DeviceProfile dp) {
+        mDeviceProfile = dp;
+        dispatchDeviceProfileChanged();
+    }
+
+    @Override
+    public void onDragStart() {}
+
+    @Override
+    public void onPopupVisibilityChanged(boolean isVisible) {}
+
+    /** Root drag layer for this context. */
+    private static class TaskbarAllAppsDragLayer extends BaseDragLayer<TaskbarAllAppsContext> {
+
+        private TaskbarAllAppsDragLayer(Context context) {
+            super(context, null, 1);
+            setClipChildren(false);
+            recreateControllers();
+        }
+
+        @Override
+        protected void onAttachedToWindow() {
+            super.onAttachedToWindow();
+            mActivity.mAllAppsViewController.show();
+        }
+
+        @Override
+        public void recreateControllers() {
+            mControllers = new TouchController[]{mActivity.mDragController};
+        }
+
+        @Override
+        public boolean dispatchKeyEvent(KeyEvent event) {
+            if (event.getAction() == ACTION_UP && event.getKeyCode() == KEYCODE_BACK) {
+                AbstractFloatingView topView = AbstractFloatingView.getTopOpenView(mActivity);
+                if (topView != null && topView.onBackPressed()) {
+                    return true;
+                }
+            }
+            return super.dispatchKeyEvent(event);
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
new file mode 100644
index 0000000..9302452
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsController.java
@@ -0,0 +1,199 @@
+/*
+ * Copyright (C) 2022 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.launcher3.taskbar.allapps;
+
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+
+import android.content.Context;
+import android.graphics.PixelFormat;
+import android.view.Gravity;
+import android.view.MotionEvent;
+import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
+
+import androidx.annotation.Nullable;
+
+import com.android.launcher3.AbstractFloatingView;
+import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.DeviceProfile.OnDeviceProfileChangeListener;
+import com.android.launcher3.appprediction.PredictionRowView;
+import com.android.launcher3.config.FeatureFlags;
+import com.android.launcher3.model.data.AppInfo;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.taskbar.TaskbarActivityContext;
+import com.android.launcher3.taskbar.TaskbarControllers;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Handles the all apps overlay window initialization, updates, and its data.
+ * <p>
+ * All apps is in an application overlay window instead of taskbar's navigation bar panel window,
+ * because a navigation bar panel is higher than UI components that all apps should be below such as
+ * the notification tray.
+ * <p>
+ * The all apps window is created and destroyed upon opening and closing all apps, respectively.
+ * Application data may be bound while the window does not exist, so this controller will store
+ * the models for the next all apps session.
+ */
+public final class TaskbarAllAppsController implements OnDeviceProfileChangeListener {
+
+    private static final String WINDOW_TITLE = "Taskbar All Apps";
+
+    private final TaskbarActivityContext mTaskbarContext;
+    private final TaskbarAllAppsProxyView mProxyView;
+    private final LayoutParams mLayoutParams;
+
+    private TaskbarControllers mControllers;
+    /** Window context for all apps if it is open. */
+    private @Nullable TaskbarAllAppsContext mAllAppsContext;
+
+    // Application data models.
+    private AppInfo[] mApps;
+    private int mAppsModelFlags;
+    private List<ItemInfo> mPredictedApps;
+
+    public TaskbarAllAppsController(TaskbarActivityContext context) {
+        mTaskbarContext = context;
+        mProxyView = new TaskbarAllAppsProxyView(mTaskbarContext);
+        mLayoutParams = createLayoutParams();
+    }
+
+    /** Initialize the controller. */
+    public void init(TaskbarControllers controllers) {
+        if (FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+            mControllers = controllers;
+        }
+    }
+
+    /** Updates the current {@link AppInfo} instances. */
+    public void setApps(AppInfo[] apps, int flags) {
+        if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+            return;
+        }
+
+        mApps = apps;
+        mAppsModelFlags = flags;
+        if (mAllAppsContext != null) {
+            mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags);
+        }
+    }
+
+    /** Updates the current predictions. */
+    public void setPredictedApps(List<ItemInfo> predictedApps) {
+        if (!FeatureFlags.ENABLE_ALL_APPS_IN_TASKBAR.get()) {
+            return;
+        }
+
+        mPredictedApps = predictedApps;
+        if (mAllAppsContext != null) {
+            mAllAppsContext.getAppsView().getFloatingHeaderView()
+                    .findFixedRowByType(PredictionRowView.class)
+                    .setPredictedApps(mPredictedApps);
+        }
+    }
+
+    /** Opens the {@link TaskbarAllAppsContainerView} in a new window. */
+    public void show() {
+        if (mProxyView.isOpen()) {
+            return;
+        }
+        mProxyView.show();
+
+        mAllAppsContext = new TaskbarAllAppsContext(mTaskbarContext,
+                this,
+                mControllers.taskbarStashController);
+        mAllAppsContext.getDragController().init(mControllers);
+        mTaskbarContext.addOnDeviceProfileChangeListener(this);
+        Optional.ofNullable(mAllAppsContext.getSystemService(WindowManager.class))
+                .ifPresent(m -> m.addView(mAllAppsContext.getDragLayer(), mLayoutParams));
+
+        mAllAppsContext.getAppsView().getAppsStore().setApps(mApps, mAppsModelFlags);
+        mAllAppsContext.getAppsView().getFloatingHeaderView()
+                .findFixedRowByType(PredictionRowView.class)
+                .setPredictedApps(mPredictedApps);
+    }
+
+    /**
+     * Removes the all apps window from the hierarchy.
+     * <p>
+     * This method should be called after an exit animation finishes, if applicable.
+     */
+    void closeWindow() {
+        mProxyView.close(false);
+        mTaskbarContext.removeOnDeviceProfileChangeListener(this);
+        Optional.ofNullable(mAllAppsContext)
+                .map(c -> c.getSystemService(WindowManager.class))
+                .ifPresent(m -> m.removeView(mAllAppsContext.getDragLayer()));
+        mAllAppsContext = null;
+    }
+
+    private LayoutParams createLayoutParams() {
+        LayoutParams layoutParams = new LayoutParams(
+                TYPE_APPLICATION_OVERLAY,
+                0,
+                PixelFormat.TRANSLUCENT);
+        layoutParams.setTitle(WINDOW_TITLE);
+        layoutParams.gravity = Gravity.BOTTOM;
+        layoutParams.packageName = mTaskbarContext.getPackageName();
+        layoutParams.setFitInsetsTypes(0); // Handled by container view.
+        layoutParams.setSystemApplicationOverlay(true);
+        return layoutParams;
+    }
+
+    @Override
+    public void onDeviceProfileChanged(DeviceProfile dp) {
+        Optional.ofNullable(mAllAppsContext).ifPresent(c -> c.updateDeviceProfile(dp));
+    }
+
+    /**
+     * Proxy view connecting taskbar drag layer to the all apps window.
+     * <p>
+     * The all apps view is in a separate window and has its own drag layer, but this proxy lets it
+     * behave as though its in the taskbar drag layer. For instance, when the taskbar closes all
+     * {@link AbstractFloatingView} instances, the all apps window will also close.
+     */
+    private class TaskbarAllAppsProxyView extends AbstractFloatingView {
+
+        private TaskbarAllAppsProxyView(Context context) {
+            super(context, null);
+        }
+
+        private void show() {
+            mIsOpen = true;
+            mTaskbarContext.getDragLayer().addView(this);
+        }
+
+        @Override
+        protected void handleClose(boolean animate) {
+            mTaskbarContext.getDragLayer().removeView(this);
+            Optional.ofNullable(mAllAppsContext)
+                    .map(TaskbarAllAppsContext::getAllAppsViewController)
+                    .ifPresent(v -> v.close(animate));
+        }
+
+        @Override
+        protected boolean isOfType(int type) {
+            return (type & TYPE_TASKBAR_ALL_APPS) != 0;
+        }
+
+        @Override
+        public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
+            return false;
+        }
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsSlideInView.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
similarity index 61%
rename from quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsSlideInView.java
rename to quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
index 63690c4..02aa3f2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAllAppsSlideInView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsSlideInView.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package com.android.launcher3.taskbar;
+package com.android.launcher3.taskbar.allapps;
 
 import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
 
@@ -23,18 +23,22 @@
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
 import com.android.launcher3.views.AbstractSlideInView;
 
-/** Wrapper for taskbar all apps with slide-in behavior. */
-public class TaskbarAllAppsSlideInView extends
-        AbstractSlideInView<TaskbarActivityContext> implements Insettable {
+import java.util.Optional;
 
-    private static final int DEFAULT_OPEN_DURATION = 500;
-    private static final int DEFAULT_CLOSE_DURATION = 200;
+/** Wrapper for taskbar all apps with slide-in behavior. */
+public class TaskbarAllAppsSlideInView extends AbstractSlideInView<TaskbarAllAppsContext>
+        implements Insettable, DeviceProfile.OnDeviceProfileChangeListener {
+    static final int DEFAULT_OPEN_DURATION = 500;
+    static final int DEFAULT_CLOSE_DURATION = 200;
 
     private TaskbarAllAppsContainerView mAppsView;
+    private OnCloseListener mOnCloseBeginListener;
+    private float mShiftRange;
 
     public TaskbarAllAppsSlideInView(Context context, AttributeSet attrs) {
         this(context, attrs, 0);
@@ -46,7 +50,7 @@
     }
 
     /** Opens the all apps view. */
-    public void show() {
+    void show() {
         if (mIsOpen || mOpenCloseAnimator.isRunning()) {
             return;
         }
@@ -60,12 +64,18 @@
     }
 
     /** The apps container inside this view. */
-    public TaskbarAllAppsContainerView getAppsView() {
+    TaskbarAllAppsContainerView getAppsView() {
         return mAppsView;
     }
 
+    /** Callback invoked when the view is beginning to close (e.g. close animation is started). */
+    void setOnCloseBeginListener(OnCloseListener onCloseBeginListener) {
+        mOnCloseBeginListener = onCloseBeginListener;
+    }
+
     @Override
     protected void handleClose(boolean animate) {
+        Optional.ofNullable(mOnCloseBeginListener).ifPresent(OnCloseListener::onSlideInViewClosed);
         handleClose(animate, DEFAULT_CLOSE_DURATION);
     }
 
@@ -79,6 +89,17 @@
         super.onFinishInflate();
         mAppsView = findViewById(R.id.apps_view);
         mContent = mAppsView;
+
+        DeviceProfile dp = mActivityContext.getDeviceProfile();
+        setShiftRange(dp.allAppsShiftRange);
+
+        mActivityContext.addOnDeviceProfileChangeListener(this);
+    }
+
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        setTranslationShift(mTranslationShift);
     }
 
     @Override
@@ -98,4 +119,24 @@
     public void setInsets(Rect insets) {
         mAppsView.setInsets(insets);
     }
+
+    @Override
+    public void onDeviceProfileChanged(DeviceProfile dp) {
+        setShiftRange(dp.allAppsShiftRange);
+        setTranslationShift(TRANSLATION_SHIFT_OPENED);
+    }
+
+    private void setShiftRange(float shiftRange) {
+        mShiftRange = shiftRange;
+    }
+
+    @Override
+    protected float getShiftRange() {
+        return mShiftRange;
+    }
+
+    @Override
+    protected boolean isEventOverContent(MotionEvent ev) {
+        return getPopupContainer().isEventOverView(mAppsView.getVisibleContainerView(), ev);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
new file mode 100644
index 0000000..c1abaac
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/allapps/TaskbarAllAppsViewController.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2022 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.launcher3.taskbar.allapps;
+
+import static com.android.launcher3.taskbar.TaskbarStashController.FLAG_STASHED_IN_APP_ALL_APPS;
+import static com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView.DEFAULT_CLOSE_DURATION;
+import static com.android.launcher3.taskbar.allapps.TaskbarAllAppsSlideInView.DEFAULT_OPEN_DURATION;
+import static com.android.launcher3.util.OnboardingPrefs.ALL_APPS_VISITED_COUNT;
+
+import com.android.launcher3.appprediction.AppsDividerView;
+import com.android.launcher3.appprediction.PredictionRowView;
+import com.android.launcher3.taskbar.TaskbarStashController;
+
+/**
+ * Handles the {@link TaskbarAllAppsContainerView} behavior and synchronizes its transitions with
+ * taskbar stashing.
+ */
+final class TaskbarAllAppsViewController {
+
+    private final TaskbarAllAppsContext mContext;
+    private final TaskbarAllAppsSlideInView mSlideInView;
+    private final TaskbarAllAppsContainerView mAppsView;
+    private final TaskbarStashController mTaskbarStashController;
+
+    TaskbarAllAppsViewController(
+            TaskbarAllAppsContext context,
+            TaskbarAllAppsSlideInView slideInView,
+            TaskbarAllAppsController windowController,
+            TaskbarStashController taskbarStashController) {
+
+        mContext = context;
+        mSlideInView = slideInView;
+        mAppsView = mSlideInView.getAppsView();
+        mTaskbarStashController = taskbarStashController;
+
+        setUpIconLongClick();
+        setUpAppDivider();
+        setUpTaskbarStashing();
+        mSlideInView.addOnCloseListener(windowController::closeWindow);
+    }
+
+    /** Starts the {@link TaskbarAllAppsSlideInView} enter transition. */
+    void show() {
+        mSlideInView.show();
+    }
+
+    /** Closes the {@link TaskbarAllAppsSlideInView}. */
+    void close(boolean animate) {
+        mSlideInView.close(animate);
+    }
+
+    private void setUpIconLongClick() {
+        mAppsView.setOnIconLongClickListener(
+                mContext.getDragController()::startDragOnLongClick);
+        mAppsView.getFloatingHeaderView()
+                .findFixedRowByType(PredictionRowView.class)
+                .setOnIconLongClickListener(
+                        mContext.getDragController()::startDragOnLongClick);
+    }
+
+    private void setUpAppDivider() {
+        mAppsView.getFloatingHeaderView()
+                .findFixedRowByType(AppsDividerView.class)
+                .setShowAllAppsLabel(!mContext.getOnboardingPrefs().hasReachedMaxCount(
+                        ALL_APPS_VISITED_COUNT));
+        mContext.getOnboardingPrefs().incrementEventCount(ALL_APPS_VISITED_COUNT);
+    }
+
+    private void setUpTaskbarStashing() {
+        mTaskbarStashController.updateStateForFlag(FLAG_STASHED_IN_APP_ALL_APPS, true);
+        mTaskbarStashController.applyState(DEFAULT_OPEN_DURATION);
+        mSlideInView.setOnCloseBeginListener(() -> {
+            mTaskbarStashController.updateStateForFlag(
+                    FLAG_STASHED_IN_APP_ALL_APPS, false);
+            mTaskbarStashController.applyState(DEFAULT_CLOSE_DURATION);
+        });
+    }
+}
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 26d8f30..fec591b 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -53,9 +53,16 @@
 
     @Override
     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
-        ScaleAndTranslation scaleAndTranslation = LauncherState.OVERVIEW
-                .getWorkspaceScaleAndTranslation(launcher);
-        scaleAndTranslation.scale = 1;
+        ScaleAndTranslation scaleAndTranslation =
+                new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
+        if (launcher.getDeviceProfile().isTablet) {
+            scaleAndTranslation.scale = 0.97f;
+        } else {
+            ScaleAndTranslation overviewScaleAndTranslation = LauncherState.OVERVIEW
+                    .getWorkspaceScaleAndTranslation(launcher);
+            scaleAndTranslation.translationX = overviewScaleAndTranslation.translationX;
+            scaleAndTranslation.translationY = overviewScaleAndTranslation.translationY;
+        }
         return scaleAndTranslation;
     }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
index 099915a..f93917f 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/touchcontrollers/PortraitStatesTouchController.java
@@ -23,8 +23,13 @@
 import static com.android.launcher3.LauncherState.OVERVIEW;
 import static com.android.launcher3.anim.Interpolators.ACCEL;
 import static com.android.launcher3.anim.Interpolators.DEACCEL;
+import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
+import static com.android.launcher3.anim.Interpolators.INSTANT;
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.LINEAR_TELEPORT;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
 
 import android.view.MotionEvent;
 
@@ -126,23 +131,31 @@
 
     private StateAnimationConfig getNormalToAllAppsAnimation() {
         StateAnimationConfig builder = new StateAnimationConfig();
-        builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(ACCEL,
-                ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD,
-                ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
+        boolean isTablet = mLauncher.getDeviceProfile().isTablet;
+        builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+                ? INSTANT
+                : Interpolators.clampToProgress(ACCEL,
+                        ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD,
+                        ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD));
         builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(ACCEL,
                 ALL_APPS_SCRIM_VISIBLE_THRESHOLD,
                 ALL_APPS_SCRIM_OPAQUE_THRESHOLD));
+        builder.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
         return builder;
     }
 
     private StateAnimationConfig getAllAppsToNormalAnimation() {
         StateAnimationConfig builder = new StateAnimationConfig();
-        builder.setInterpolator(ANIM_ALL_APPS_FADE, Interpolators.clampToProgress(DEACCEL,
-                1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
-                1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
+        boolean isTablet = mLauncher.getDeviceProfile().isTablet;
+        builder.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+                ? FINAL_FRAME
+                : Interpolators.clampToProgress(DEACCEL,
+                        1 - ALL_APPS_CONTENT_FADE_MAX_CLAMPING_THRESHOLD,
+                        1 - ALL_APPS_CONTENT_FADE_MIN_CLAMPING_THRESHOLD));
         builder.setInterpolator(ANIM_SCRIM_FADE, Interpolators.clampToProgress(DEACCEL,
                 1 - ALL_APPS_SCRIM_OPAQUE_THRESHOLD,
                 1 - ALL_APPS_SCRIM_VISIBLE_THRESHOLD));
+        builder.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
         return builder;
     }
 
diff --git a/res/drawable/bg_all_apps_bottom_sheet.xml b/res/drawable/bg_all_apps_bottom_sheet.xml
deleted file mode 100644
index dba2fee..0000000
--- a/res/drawable/bg_all_apps_bottom_sheet.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2022 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.
--->
-<ripple android:color="?android:attr/colorControlHighlight"
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android">
-    <item>
-        <shape android:shape="rectangle"
-            android:tint="?colorButtonNormal">
-            <corners
-                android:topLeftRadius="@dimen/dialogCornerRadius"
-                android:topRightRadius="@dimen/dialogCornerRadius"/>
-            <solid android:color="?attr/allAppsScrimColor" />
-        </shape>
-    </item>
-</ripple>
\ No newline at end of file
diff --git a/res/drawable/bg_rounded_corner_bottom_sheet.xml b/res/drawable/bg_rounded_corner_bottom_sheet.xml
index aa49bce..dfcd354 100644
--- a/res/drawable/bg_rounded_corner_bottom_sheet.xml
+++ b/res/drawable/bg_rounded_corner_bottom_sheet.xml
@@ -16,7 +16,7 @@
 
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle" >
-    <solid android:color="@color/surface" />
+    <solid android:color="?android:attr/colorBackground" />
     <corners
         android:topLeftRadius="@dimen/dialogCornerRadius"
         android:topRightRadius="@dimen/dialogCornerRadius" />
diff --git a/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml b/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml
new file mode 100644
index 0000000..c502178
--- /dev/null
+++ b/res/drawable/bg_rounded_corner_bottom_sheet_handle.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
+    android:shape="rectangle" >
+    <solid android:color="?androidprv:attr/colorSurfaceVariant"/>
+    <corners android:radius="@dimen/bottom_sheet_handle_corner_radius" />
+</shape>
diff --git a/res/layout/all_apps_bottom_sheet_background.xml b/res/layout/all_apps_bottom_sheet_background.xml
index ad10d68..12b6b7b 100644
--- a/res/layout/all_apps_bottom_sheet_background.xml
+++ b/res/layout/all_apps_bottom_sheet_background.xml
@@ -17,19 +17,19 @@
     android:id="@+id/bottom_sheet_background"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:background="@drawable/bg_all_apps_bottom_sheet">
+    android:background="@drawable/bg_rounded_corner_bottom_sheet">
 
     <View
         android:id="@+id/bottom_sheet_handle_area"
         android:layout_width="match_parent"
-        android:layout_height="34dp" />
+        android:layout_height="36dp" />
 
     <View
         android:id="@+id/bottom_sheet_handle"
-        android:layout_width="48dp"
-        android:layout_height="2dp"
+        android:layout_width="@dimen/bottom_sheet_handle_width"
+        android:layout_height="@dimen/bottom_sheet_handle_height"
         android:layout_gravity="center_horizontal"
-        android:layout_marginTop="16dp"
-        android:layout_marginBottom="16dp"
-        android:background="?android:attr/textColorSecondary" />
+        android:layout_marginTop="@dimen/bottom_sheet_handle_margin"
+        android:layout_marginBottom="@dimen/bottom_sheet_handle_margin"
+        android:background="@drawable/bg_rounded_corner_bottom_sheet_handle" />
 </FrameLayout>
diff --git a/res/layout/widgets_bottom_sheet_content.xml b/res/layout/widgets_bottom_sheet_content.xml
index 1a2cfc6..a5f72ef 100644
--- a/res/layout/widgets_bottom_sheet_content.xml
+++ b/res/layout/widgets_bottom_sheet_content.xml
@@ -19,16 +19,16 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:background="@drawable/bg_rounded_corner_bottom_sheet"
-        android:paddingTop="16dp"
+        android:paddingTop="@dimen/bottom_sheet_handle_margin"
         android:orientation="vertical">
         <View
             android:id="@+id/collapse_handle"
-            android:layout_width="48dp"
-            android:layout_height="2dp"
+            android:layout_width="@dimen/bottom_sheet_handle_width"
+            android:layout_height="@dimen/bottom_sheet_handle_height"
             android:layout_gravity="center_horizontal"
-            android:layout_marginBottom="16dp"
+            android:layout_marginBottom="@dimen/bottom_sheet_handle_margin"
             android:visibility="gone"
-            android:background="?android:attr/textColorSecondary"/>
+            android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/>
         <TextView
             style="@style/TextHeadline"
             android:id="@+id/title"
diff --git a/res/layout/widgets_full_sheet.xml b/res/layout/widgets_full_sheet.xml
index 309dc42..505ecb1 100644
--- a/res/layout/widgets_full_sheet.xml
+++ b/res/layout/widgets_full_sheet.xml
@@ -31,11 +31,11 @@
 
         <View
             android:id="@+id/collapse_handle"
-            android:layout_width="48dp"
-            android:layout_height="2dp"
-            android:layout_marginTop="16dp"
+            android:layout_width="@dimen/bottom_sheet_handle_width"
+            android:layout_height="@dimen/bottom_sheet_handle_height"
+            android:layout_marginTop="@dimen/bottom_sheet_handle_margin"
             android:layout_centerHorizontal="true"
-            android:background="?android:attr/textColorSecondary"/>
+            android:background="@drawable/bg_rounded_corner_bottom_sheet_handle"/>
 
         <TextView
             android:id="@+id/no_widgets_text"
diff --git a/res/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 3dde3f6..92f806e 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -22,7 +22,8 @@
     <dimen name="widget_list_horizontal_margin">32dp</dimen>
 
 <!-- AllApps -->
-    <dimen name="all_apps_bottom_sheet_horizontal_padding">32dp</dimen>
+    <dimen name="all_apps_search_bar_content_overlap">0dp</dimen>
+    <dimen name="all_apps_bottom_sheet_horizontal_padding">46dp</dimen>
 
 <!-- Fast scroll -->
     <dimen name="fastscroll_popup_width">75dp</dimen>
diff --git a/res/values-sw720dp-land/dimens.xml b/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..a9e0fb8
--- /dev/null
+++ b/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2022 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.
+-->
+
+<resources>
+<!-- AllApps -->
+    <dimen name="all_apps_top_padding">0dp</dimen>
+</resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 9d7941f..5c314d5 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -16,5 +16,6 @@
 
 <resources>
 <!-- AllApps -->
-    <dimen name="all_apps_bottom_sheet_horizontal_padding">41dp</dimen>
+    <dimen name="all_apps_top_padding">300dp</dimen>
+    <dimen name="all_apps_bottom_sheet_horizontal_padding">65dp</dimen>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index ddc7d10..3e666fc 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -93,8 +93,11 @@
     <dimen name="fastscroll_end_margin">-26dp</dimen>
 
     <!-- All Apps -->
-    <dimen name="all_apps_open_vertical_translate">320dp</dimen>
+    <dimen name="all_apps_starting_vertical_translate">320dp</dimen>
+    <dimen name="all_apps_top_padding">0dp</dimen>
     <dimen name="all_apps_search_bar_field_height">48dp</dimen>
+    <!-- all_apps_search_bar_field_height / 2 -->
+    <dimen name="all_apps_search_bar_content_overlap">24dp</dimen>
     <dimen name="all_apps_search_bar_bottom_padding">30dp</dimen>
     <dimen name="all_apps_empty_search_message_top_offset">40dp</dimen>
     <dimen name="all_apps_empty_search_bg_top_offset">144dp</dimen>
@@ -363,4 +366,9 @@
     <dimen name="search_row_small_icon_size">32dp</dimen>
     <dimen name="padded_rounded_button_padding">8dp</dimen>
 
+<!-- Bottom sheet related parameters -->
+    <dimen name="bottom_sheet_handle_width">32dp</dimen>
+    <dimen name="bottom_sheet_handle_height">4dp</dimen>
+    <dimen name="bottom_sheet_handle_margin">16dp</dimen>
+    <dimen name="bottom_sheet_handle_corner_radius">2dp</dimen>
 </resources>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 62703ad..7189ef7 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -171,7 +171,8 @@
 
     // All apps
     public Point allAppsBorderSpacePx;
-    public int allAppsOpenVerticalTranslate;
+    public int allAppsShiftRange;
+    public int allAppsTopPadding;
     public int allAppsCellHeightPx;
     public int allAppsCellWidthPx;
     public int allAppsIconSizePx;
@@ -288,8 +289,11 @@
         desiredWorkspaceHorizontalMarginPx = getHorizontalMarginPx(inv, res);
         desiredWorkspaceHorizontalMarginOriginalPx = desiredWorkspaceHorizontalMarginPx;
 
-        allAppsOpenVerticalTranslate = res.getDimensionPixelSize(
-                R.dimen.all_apps_open_vertical_translate);
+        allAppsTopPadding = res.getDimensionPixelSize(R.dimen.all_apps_top_padding)
+                + (isTablet ? heightPx - availableHeightPx : 0);
+        allAppsShiftRange = isTablet
+                ? heightPx - allAppsTopPadding
+                : res.getDimensionPixelSize(R.dimen.all_apps_starting_vertical_translate);
 
         folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale);
         folderContentPaddingLeftRight =
diff --git a/src/com/android/launcher3/allapps/AllAppsTransitionController.java b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
index b6a2459..cdc313f 100644
--- a/src/com/android/launcher3/allapps/AllAppsTransitionController.java
+++ b/src/com/android/launcher3/allapps/AllAppsTransitionController.java
@@ -89,15 +89,15 @@
     private float mShiftRange;      // changes depending on the orientation
     private float mProgress;        // [0, 1], mShiftRange * mProgress = shiftCurrent
 
-    private float mScrollRangeDelta = 0;
     private ScrimView mScrimView;
 
     public AllAppsTransitionController(Launcher l) {
         mLauncher = l;
-        mShiftRange = mLauncher.getDeviceProfile().heightPx;
+        DeviceProfile dp = mLauncher.getDeviceProfile();
+        setShiftRange(dp.allAppsShiftRange);
         mProgress = 1f;
 
-        mIsVerticalLayout = mLauncher.getDeviceProfile().isVerticalBarLayout();
+        mIsVerticalLayout = dp.isVerticalBarLayout();
         mLauncher.addOnDeviceProfileChangeListener(this);
     }
 
@@ -108,7 +108,7 @@
     @Override
     public void onDeviceProfileChanged(DeviceProfile dp) {
         mIsVerticalLayout = dp.isVerticalBarLayout();
-        setScrollRangeDelta(mScrollRangeDelta);
+        setShiftRange(dp.allAppsShiftRange);
 
         if (mIsVerticalLayout) {
             mLauncher.getHotseat().setTranslationY(0);
@@ -160,12 +160,14 @@
         }
 
         // need to decide depending on the release velocity
-        Interpolator interpolator = (config.userControlled ? LINEAR : DEACCEL_1_7);
-
+        Interpolator verticalProgressInterpolator = config.getInterpolator(ANIM_VERTICAL_PROGRESS,
+                config.userControlled ? LINEAR : DEACCEL_1_7);
         Animator anim = createSpringAnimation(mProgress, targetProgress);
-        anim.setInterpolator(config.getInterpolator(ANIM_VERTICAL_PROGRESS, interpolator));
+        anim.setInterpolator(verticalProgressInterpolator);
         anim.addListener(getProgressAnimatorListener());
         builder.add(anim);
+        // Use ANIM_VERTICAL_PROGRESS's interpolator to determine state transition threshold.
+        builder.setInterpolator(verticalProgressInterpolator);
 
         setAlphas(toState, config, builder);
 
@@ -215,9 +217,8 @@
     /**
      * Updates the total scroll range but does not update the UI.
      */
-    public void setScrollRangeDelta(float delta) {
-        mScrollRangeDelta = delta;
-        mShiftRange = mLauncher.getDeviceProfile().heightPx - mScrollRangeDelta;
+    public void setShiftRange(float shiftRange) {
+        mShiftRange = shiftRange;
     }
 
     /**
diff --git a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
index 59e21c0..bfc7515 100644
--- a/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/BaseAllAppsContainerView.java
@@ -408,7 +408,7 @@
         if (grid.isVerticalBarLayout()) {
             setPadding(grid.workspacePadding.left, 0, grid.workspacePadding.right, 0);
         } else {
-            setPadding(0, grid.isTablet ? insets.top : 0, 0, 0);
+            setPadding(0, grid.allAppsTopPadding, 0, 0);
         }
 
         InsettableFrameLayout.dispatchInsets(this, insets);
@@ -765,4 +765,11 @@
                     && mVerticalFadingEdge);
         }
     }
+
+    /**
+     * Returns a view that denotes the visible part of all apps container view.
+     */
+    public View getVisibleContainerView() {
+        return mActivityContext.getDeviceProfile().isTablet ? mBottomSheetBackground : this;
+    }
 }
diff --git a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
index 30d33f9..8601819 100644
--- a/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/LauncherAllAppsContainerView.java
@@ -16,7 +16,6 @@
 package com.android.launcher3.allapps;
 
 import android.content.Context;
-import android.graphics.Rect;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
 
@@ -59,12 +58,4 @@
         }
         return super.onTouchEvent(ev);
     }
-
-    @Override
-    public void setInsets(Rect insets) {
-        super.setInsets(insets);
-        int allAppsStartingPositionY = mActivityContext.getDeviceProfile().availableHeightPx
-                - mActivityContext.getDeviceProfile().allAppsOpenVerticalTranslate;
-        mActivityContext.getAllAppsController().setScrollRangeDelta(allAppsStartingPositionY);
-    }
 }
diff --git a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
index ffc049b..4a886a4 100644
--- a/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
+++ b/src/com/android/launcher3/allapps/search/AppsSearchContainerLayout.java
@@ -82,7 +82,7 @@
         setHint(prefixTextWithIcon(getContext(), R.drawable.ic_allapps_search, getHint()));
 
         mContentOverlap =
-                getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_field_height) / 2;
+                getResources().getDimensionPixelSize(R.dimen.all_apps_search_bar_content_overlap);
     }
 
     @Override
diff --git a/src/com/android/launcher3/anim/Interpolators.java b/src/com/android/launcher3/anim/Interpolators.java
index 1e7b224..9c12abd 100644
--- a/src/com/android/launcher3/anim/Interpolators.java
+++ b/src/com/android/launcher3/anim/Interpolators.java
@@ -130,6 +130,23 @@
         }
     };
 
+    public static final Interpolator LINEAR_TELEPORT = t -> {
+        float startTeleport = 0.2f;
+        float endTeleport = 0.4f;
+        float teleportProgress = 0.5f;
+        float v;
+        if (t < startTeleport) {
+            v = LINEAR.getInterpolation(t);
+        } else if (t < endTeleport) {
+            v = Utilities.mapToRange(t, startTeleport, endTeleport, startTeleport,
+                    endTeleport + teleportProgress, ACCEL_DEACCEL);
+        } else {
+            v = LINEAR.getInterpolation(t) + teleportProgress;
+        }
+        v = Utilities.boundToRange(v, 0f, 1f);
+        return v;
+    };
+
     private static final float FAST_FLING_PX_MS = 10;
 
     public static Interpolator scrollInterpolatorForVelocity(float velocity) {
diff --git a/src/com/android/launcher3/anim/PendingAnimation.java b/src/com/android/launcher3/anim/PendingAnimation.java
index 3ab893b..1300ce7 100644
--- a/src/com/android/launcher3/anim/PendingAnimation.java
+++ b/src/com/android/launcher3/anim/PendingAnimation.java
@@ -77,6 +77,13 @@
         addAnimationHoldersRecur(a, mDuration, springProperty, mAnimHolders);
     }
 
+    /**
+     * Configures interpolator of the underlying AnimatorSet.
+     */
+    public void setInterpolator(TimeInterpolator interpolator) {
+        mAnim.setInterpolator(interpolator);
+    }
+
     @Override
     public void setViewAlpha(View view, float alpha, TimeInterpolator interpolator) {
         if (view == null || view.getAlpha() == alpha) {
diff --git a/src/com/android/launcher3/touch/AllAppsSwipeController.java b/src/com/android/launcher3/touch/AllAppsSwipeController.java
index 989a9e4..f7d3492 100644
--- a/src/com/android/launcher3/touch/AllAppsSwipeController.java
+++ b/src/com/android/launcher3/touch/AllAppsSwipeController.java
@@ -17,9 +17,13 @@
 
 import static com.android.launcher3.LauncherState.ALL_APPS;
 import static com.android.launcher3.LauncherState.NORMAL;
+import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
+import static com.android.launcher3.anim.Interpolators.INSTANT;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.anim.Interpolators.LINEAR_TELEPORT;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_APPS_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
+import static com.android.launcher3.states.StateAnimationConfig.ANIM_VERTICAL_PROGRESS;
 
 import android.view.MotionEvent;
 import android.view.animation.Interpolator;
@@ -94,9 +98,9 @@
             LauncherState toState) {
         StateAnimationConfig config = super.getConfigForStates(fromState, toState);
         if (fromState == NORMAL && toState == ALL_APPS) {
-            applyNormalToAllAppsAnimConfig(config);
+            applyNormalToAllAppsAnimConfig(mLauncher, config);
         } else if (fromState == ALL_APPS && toState == NORMAL) {
-            applyAllAppsToNormalConfig(config);
+            applyAllAppsToNormalConfig(mLauncher, config);
         }
         return config;
     }
@@ -104,17 +108,24 @@
     /**
      * Applies Animation config values for transition from all apps to home
      */
-    public static void applyAllAppsToNormalConfig(StateAnimationConfig config) {
+    public static void applyAllAppsToNormalConfig(Launcher launcher, StateAnimationConfig config) {
+        boolean isTablet = launcher.getDeviceProfile().isTablet;
         config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
-        config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+        config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+                ? FINAL_FRAME : ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
+        config.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
     }
 
     /**
      * Applies Animation config values for transition from home to all apps
      */
-    public static void applyNormalToAllAppsAnimConfig(StateAnimationConfig config) {
+    public static void applyNormalToAllAppsAnimConfig(Launcher launcher,
+            StateAnimationConfig config) {
+        boolean isTablet = launcher.getDeviceProfile().isTablet;
         config.setInterpolator(ANIM_SCRIM_FADE, ALLAPPS_STAGGERED_FADE_EARLY_RESPONDER);
-        config.setInterpolator(ANIM_ALL_APPS_FADE, ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+        config.setInterpolator(ANIM_ALL_APPS_FADE, isTablet
+                ? INSTANT : ALLAPPS_STAGGERED_FADE_LATE_RESPONDER);
+        config.setInterpolator(ANIM_VERTICAL_PROGRESS, isTablet ? LINEAR_TELEPORT : LINEAR);
     }
 
 
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index c22d60d..5d88884 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -113,9 +113,16 @@
         return -1;
     }
 
+    /**
+     * Returns the range in height that the slide in view can be dragged.
+     */
+    protected float getShiftRange() {
+        return mContent.getHeight();
+    }
+
     protected void setTranslationShift(float translationShift) {
         mTranslationShift = translationShift;
-        mContent.setTranslationY(mTranslationShift * mContent.getHeight());
+        mContent.setTranslationY(mTranslationShift * getShiftRange());
         if (mColorScrim != null) {
             mColorScrim.setAlpha(1 - mTranslationShift);
         }
@@ -132,8 +139,7 @@
         mSwipeDetector.setDetectableScrollConditions(
                 directionsToDetectScroll, false);
         mSwipeDetector.onTouchEvent(ev);
-        return mSwipeDetector.isDraggingOrSettling()
-                || !getPopupContainer().isEventOverView(mContent, ev);
+        return mSwipeDetector.isDraggingOrSettling() || !isEventOverContent(ev);
     }
 
     @Override
@@ -142,13 +148,23 @@
         if (ev.getAction() == MotionEvent.ACTION_UP && mSwipeDetector.isIdleState()
                 && !isOpeningAnimationRunning()) {
             // If we got ACTION_UP without ever starting swipe, close the panel.
-            if (!getPopupContainer().isEventOverView(mContent, ev)) {
+            if (!isEventOverContent(ev)) {
                 close(true);
             }
         }
         return true;
     }
 
+    /**
+     * Returns {@code true} if the touch event is over the visible area of the bottom sheet.
+     *
+     * By default will check if the touch event is over {@code mContent}, subclasses should override
+     * this method if the visible area of the bottom sheet is different from {@code mContent}.
+     */
+    protected boolean isEventOverContent(MotionEvent ev) {
+        return getPopupContainer().isEventOverView(mContent, ev);
+    }
+
     private boolean isOpeningAnimationRunning() {
         return mIsOpen && mOpenCloseAnimator.isRunning();
     }
@@ -160,7 +176,7 @@
 
     @Override
     public boolean onDrag(float displacement) {
-        float range = mContent.getHeight();
+        float range = getShiftRange();
         displacement = Utilities.boundToRange(displacement, 0, range);
         setTranslationShift(displacement / range);
         return true;
diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
index 5543cc2..8a435c9 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -55,8 +55,15 @@
 
     @Override
     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
-        return new ScaleAndTranslation(1f, 0,
-                -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT);
+        ScaleAndTranslation scaleAndTranslation =
+                new ScaleAndTranslation(NO_SCALE, NO_OFFSET, NO_OFFSET);
+        if (launcher.getDeviceProfile().isTablet) {
+            scaleAndTranslation.scale = 0.97f;
+        } else {
+            scaleAndTranslation.translationY =
+                    -launcher.getAllAppsController().getShiftRange() * PARALLAX_COEFFICIENT;
+        }
+        return scaleAndTranslation;
     }
 
     @Override