Merge "Defer gesture when IME is currently rendering nav buttons"
diff --git a/quickstep/res/values/strings.xml b/quickstep/res/values/strings.xml
index 9604a77..3ee2af0 100644
--- a/quickstep/res/values/strings.xml
+++ b/quickstep/res/values/strings.xml
@@ -246,6 +246,10 @@
     <string name="taskbar_button_ime_switcher">IME switcher</string>
     <!-- Content description for recents button [CHAR_LIMIT=16] -->
     <string name="taskbar_button_recents">Recents</string>
+    <!-- Content description for notifications button [CHAR_LIMIT=16] -->
+    <string name="taskbar_button_notifications">Notifications</string>
+    <!-- Content description for quick settings button [CHAR_LIMIT=16] -->
+    <string name="taskbar_button_quick_settings">Quick Settings</string>
 
     <!-- Label for moving drop target to the top or left side of the screen, depending on orientation (from the taskbar only). -->
     <string name="move_drop_target_top_or_left">Move to top&#47;left</string>
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index 65b346a..d9829c6 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -39,6 +39,7 @@
 import android.hardware.devicestate.DeviceStateManager;
 import android.os.Bundle;
 import android.os.CancellationSignal;
+import android.view.Display;
 import android.view.View;
 import android.view.WindowInsets;
 import android.window.SplashScreen;
@@ -509,6 +510,9 @@
                     activityOptions.options, mLastTouchUpTime);
         }
         activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+        activityOptions.options.setLaunchDisplayId(
+                (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+                        : Display.DEFAULT_DISPLAY);
         addLaunchCookie(item, activityOptions.options);
         return activityOptions;
     }
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 6e2fadd..49b2cc5 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -367,7 +367,7 @@
         if (launcherClosing) {
             // Delay animation by a frame to avoid jank.
             Pair<AnimatorSet, Runnable> launcherContentAnimator =
-                    getLauncherContentAnimator(true /* isAppOpening */, startDelay);
+                    getLauncherContentAnimator(true /* isAppOpening */, startDelay, false);
             anim.play(launcherContentAnimator.first);
             anim.addListener(new AnimatorListenerAdapter() {
                 @Override
@@ -464,9 +464,10 @@
      * @param isAppOpening True when this is called when an app is opening.
      *                     False when this is called when an app is closing.
      * @param startDelay   Start delay duration.
+     * @param skipAllAppsScale True if we want to avoid scaling All Apps
      */
     private Pair<AnimatorSet, Runnable> getLauncherContentAnimator(boolean isAppOpening,
-            int startDelay) {
+            int startDelay, boolean skipAllAppsScale) {
         AnimatorSet launcherAnimator = new AnimatorSet();
         Runnable endListener;
 
@@ -484,7 +485,6 @@
             final float startAlpha = appsView.getAlpha();
             final float startScale = SCALE_PROPERTY.get(appsView);
             appsView.setAlpha(alphas[0]);
-            SCALE_PROPERTY.set(appsView, scales[0]);
 
             ObjectAnimator alpha = ObjectAnimator.ofFloat(appsView, View.ALPHA, alphas);
             alpha.setDuration(CONTENT_ALPHA_DURATION);
@@ -496,12 +496,16 @@
                     appsView.setLayerType(View.LAYER_TYPE_NONE, null);
                 }
             });
-            ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales);
-            scale.setInterpolator(AGGRESSIVE_EASE);
-            scale.setDuration(CONTENT_SCALE_DURATION);
+
+            if (!skipAllAppsScale) {
+                SCALE_PROPERTY.set(appsView, scales[0]);
+                ObjectAnimator scale = ObjectAnimator.ofFloat(appsView, SCALE_PROPERTY, scales);
+                scale.setInterpolator(AGGRESSIVE_EASE);
+                scale.setDuration(CONTENT_SCALE_DURATION);
+                launcherAnimator.play(scale);
+            }
 
             launcherAnimator.play(alpha);
-            launcherAnimator.play(scale);
 
             endListener = () -> {
                 appsView.setAlpha(startAlpha);
@@ -1565,6 +1569,7 @@
                         || mLauncher.getWorkspace().isOverlayShown();
 
                 boolean playWorkspaceReveal = true;
+                boolean skipAllAppsScale = false;
                 if (mFromUnlock) {
                     anim.play(getUnlockWindowAnimator(appTargets, wallpaperTargets));
                 } else if (ENABLE_BACK_SWIPE_HOME_ANIMATION.get()
@@ -1579,6 +1584,10 @@
                                 true /* animateOverviewScrim */, launcherView).getAnimators());
                         // We play StaggeredWorkspaceAnim as a part of the closing window animation.
                         playWorkspaceReveal = false;
+                    } else {
+                        // Skip scaling all apps, otherwise FloatingIconView will get wrong
+                        // layout bounds.
+                        skipAllAppsScale = true;
                     }
                 } else {
                     anim.play(getFallbackClosingWindowAnimators(appTargets));
@@ -1600,7 +1609,8 @@
 
                     if (mLauncher.isInState(LauncherState.ALL_APPS)) {
                         Pair<AnimatorSet, Runnable> contentAnimator =
-                                getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY);
+                                getLauncherContentAnimator(false, LAUNCHER_RESUME_START_DELAY,
+                                        skipAllAppsScale);
                         anim.play(contentAnimator.first);
                         anim.addListener(new AnimatorListenerAdapter() {
                             @Override
diff --git a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
index 1b0f967..4f987d2 100644
--- a/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
+++ b/quickstep/src/com/android/launcher3/appprediction/AppsDividerView.java
@@ -209,7 +209,7 @@
     private Layout getAllAppsLabelLayout() {
         if (mAllAppsLabelLayout == null) {
             mPaint.setAntiAlias(true);
-            mPaint.setTypeface(Typeface.create("sans-serif-medium", Typeface.NORMAL));
+            mPaint.setTypeface(Typeface.create("google-sans", Typeface.NORMAL));
             mPaint.setTextSize(
                     getResources().getDimensionPixelSize(R.dimen.all_apps_label_text_size));
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
new file mode 100644
index 0000000..0ab3cfd5
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/DesktopNavbarButtonsViewController.java
@@ -0,0 +1,65 @@
+/*
+ * 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.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
+import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
+
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import com.android.launcher3.R;
+
+/**
+ * Controller for managing buttons and status icons in taskbar in a desktop environment.
+ */
+public class DesktopNavbarButtonsViewController extends NavbarButtonsViewController {
+
+    private final TaskbarActivityContext mContext;
+    private final FrameLayout mNavButtonsView;
+    private final ViewGroup mNavButtonContainer;
+
+    private TaskbarControllers mControllers;
+
+    public DesktopNavbarButtonsViewController(TaskbarActivityContext context,
+            FrameLayout navButtonsView) {
+        super(context, navButtonsView);
+        mContext = context;
+        mNavButtonsView = navButtonsView;
+        mNavButtonContainer = mNavButtonsView.findViewById(R.id.end_nav_buttons);
+    }
+
+    /**
+     * Initializes the controller
+     */
+    @Override
+    public void init(TaskbarControllers controllers) {
+        mControllers = controllers;
+        mNavButtonsView.getLayoutParams().height = mContext.getDeviceProfile().taskbarSize;
+
+        // Quick settings and notifications buttons
+        addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
+                mNavButtonContainer, mControllers.navButtonController,
+                R.id.quick_settings_button);
+        addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
+                mNavButtonContainer, mControllers.navButtonController,
+                R.id.notifications_button);
+    }
+
+    /** Cleans up on destroy */
+    @Override
+    public void onDestroy() { }
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
index 094bced..7e4fa08 100644
--- a/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/NavbarButtonsViewController.java
@@ -15,15 +15,11 @@
  */
 package com.android.launcher3.taskbar;
 
-import static android.content.pm.PackageManager.FEATURE_PC;
-
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_A11Y;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_BACK;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_HOME;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_IME_SWITCH;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_NOTIFICATIONS;
-import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_QUICK_SETTINGS;
 import static com.android.launcher3.taskbar.TaskbarNavButtonController.BUTTON_RECENTS;
 import static com.android.launcher3.taskbar.TaskbarViewController.ALPHA_INDEX_KEYGUARD;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_A11Y_BUTTON_CLICKABLE;
@@ -77,15 +73,18 @@
 import com.android.systemui.shared.rotation.FloatingRotationButton;
 import com.android.systemui.shared.rotation.RotationButton;
 import com.android.systemui.shared.rotation.RotationButtonController;
+import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.ViewTreeObserverWrapper;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.StringJoiner;
 import java.util.function.IntPredicate;
 
 /**
  * Controller for managing nav bar buttons in taskbar
  */
-public class NavbarButtonsViewController {
+public class NavbarButtonsViewController implements TaskbarControllers.LoggableTaskbarController {
 
     private final Rect mTempRect = new Rect();
 
@@ -325,16 +324,6 @@
         applyState();
         mPropertyHolders.forEach(StatePropertyHolder::endAnimation);
 
-        // quick setting and notification buttons
-        if (mContext.getPackageManager().hasSystemFeature(FEATURE_PC)) {
-            addButton(R.drawable.ic_sysbar_quick_settings, BUTTON_QUICK_SETTINGS,
-                    mNavButtonContainer, mControllers.navButtonController,
-                    R.id.quick_settings_button);
-            addButton(R.drawable.ic_sysbar_notifications, BUTTON_NOTIFICATIONS,
-                    mNavButtonContainer, mControllers.navButtonController,
-                    R.id.notifications_button);
-        }
-
         // Initialize things needed to move nav buttons to separate window.
         mSeparateWindowParent = new BaseDragLayer<TaskbarActivityContext>(mContext, null, 0) {
             @Override
@@ -546,7 +535,7 @@
         }
     }
 
-    private ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
+    protected ImageView addButton(@DrawableRes int drawableId, @TaskbarButton int buttonType,
             ViewGroup parent, TaskbarNavButtonController navButtonController, @IdRes int id) {
         return addButton(drawableId, buttonType, parent, navButtonController, id,
                 R.layout.taskbar_nav_button);
@@ -645,6 +634,42 @@
         insetsInfo.setTouchableInsets(TOUCHABLE_INSETS_REGION);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "NavbarButtonsViewController:");
+
+        pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
+        pw.println(String.format(
+                "%s\tmLightIconColor=0x%s", prefix, Integer.toHexString(mLightIconColor)));
+        pw.println(String.format(
+                "%s\tmDarkIconColor=0x%s", prefix, Integer.toHexString(mDarkIconColor)));
+        pw.println(String.format(
+                "%s\tmFloatingRotationButtonBounds=%s", prefix, mFloatingRotationButtonBounds));
+        pw.println(String.format(
+                "%s\tmSysuiStateFlags=%s",
+                prefix,
+                QuickStepContract.getSystemUiStateString(mSysuiStateFlags)));
+    }
+
+    private static String getStateString(int flags) {
+        StringJoiner str = new StringJoiner("|");
+        str.add((flags & FLAG_SWITCHER_SUPPORTED) != 0 ? "FLAG_SWITCHER_SUPPORTED" : "");
+        str.add((flags & FLAG_IME_VISIBLE) != 0 ? "FLAG_IME_VISIBLE" : "");
+        str.add((flags & FLAG_ROTATION_BUTTON_VISIBLE) != 0 ? "FLAG_ROTATION_BUTTON_VISIBLE" : "");
+        str.add((flags & FLAG_A11Y_VISIBLE) != 0 ? "FLAG_A11Y_VISIBLE" : "");
+        str.add((flags & FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE) != 0
+                ? "FLAG_ONLY_BACK_FOR_BOUNCER_VISIBLE" : "");
+        str.add((flags & FLAG_KEYGUARD_VISIBLE) != 0 ? "FLAG_KEYGUARD_VISIBLE" : "");
+        str.add((flags & FLAG_KEYGUARD_OCCLUDED) != 0 ? "FLAG_KEYGUARD_OCCLUDED" : "");
+        str.add((flags & FLAG_DISABLE_HOME) != 0 ? "FLAG_DISABLE_HOME" : "");
+        str.add((flags & FLAG_DISABLE_RECENTS) != 0 ? "FLAG_DISABLE_RECENTS" : "");
+        str.add((flags & FLAG_DISABLE_BACK) != 0 ? "FLAG_DISABLE_BACK" : "");
+        str.add((flags & FLAG_NOTIFICATION_SHADE_EXPANDED) != 0
+                ? "FLAG_NOTIFICATION_SHADE_EXPANDED" : "");
+        str.add((flags & FLAG_SCREEN_PINNING_ACTIVE) != 0 ? "FLAG_SCREEN_PINNING_ACTIVE" : "");
+        return str.toString();
+    }
+
     private class RotationButtonListener implements RotationButton.RotationButtonUpdatesCallback {
         @Override
         public void onVisibilityChanged(boolean isVisible) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
index 22ca63f..a9ae7bd 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleViewController.java
@@ -34,10 +34,12 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.systemui.shared.navigationbar.RegionSamplingHelper;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, then passes the results to our stashed handle View to render.
  */
-public class StashedHandleViewController {
+public class StashedHandleViewController implements TaskbarControllers.LoggableTaskbarController {
 
     public static final int ALPHA_INDEX_STASHED = 0;
     public static final int ALPHA_INDEX_HOME_DISABLED = 1;
@@ -200,4 +202,15 @@
     public boolean isStashedHandleVisible() {
         return mStashedHandleView.getVisibility() == View.VISIBLE;
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "StashedHandleViewController:");
+
+        pw.println(String.format(
+                "%s\tisStashedHandleVisible=%b", prefix, isStashedHandleVisible()));
+        pw.println(String.format("%s\tmStashedHandleWidth=%dpx", prefix, mStashedHandleWidth));
+        pw.println(String.format("%s\tmStashedHandleHeight=%dpx", prefix, mStashedHandleHeight));
+        mRegionSamplingHelper.dump(prefix, pw);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index a60d434..88a29df 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -15,6 +15,7 @@
  */
 package com.android.launcher3.taskbar;
 
+import static android.content.pm.PackageManager.FEATURE_PC;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
 import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
@@ -82,6 +83,8 @@
 import com.android.systemui.shared.system.WindowManagerWrapper;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
+import java.io.PrintWriter;
+
 /**
  * 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
@@ -166,7 +169,9 @@
         mControllers = new TaskbarControllers(this,
                 new TaskbarDragController(this),
                 buttonController,
-                new NavbarButtonsViewController(this, navButtonsView),
+                getPackageManager().hasSystemFeature(FEATURE_PC)
+                        ? new DesktopNavbarButtonsViewController(this, navButtonsView) :
+                        new NavbarButtonsViewController(this, navButtonsView),
                 new RotationButtonController(this,
                         c.getColor(R.color.taskbar_nav_icon_light_color),
                         c.getColor(R.color.taskbar_nav_icon_dark_color),
@@ -667,4 +672,16 @@
         setTaskbarWindowFullscreen(true);
         btv.post(() -> mControllers.taskbarPopupController.showForIcon(btv));
     }
+
+    protected void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarActivityContext:");
+
+        pw.println(String.format(
+                "%s\tmNavMode=%s", prefix, mNavMode));
+        pw.println(String.format(
+                "%s\tmIsUserSetupComplete=%b", prefix, mIsUserSetupComplete));
+        pw.println(String.format(
+                "%s\tmWindowLayoutParams.height=%dpx", prefix, mWindowLayoutParams.height));
+        mControllers.dumpLogs(prefix + "\t", pw);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
index e42f83d..31a6aa6 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarAutohideSuspendController.java
@@ -19,17 +19,21 @@
 
 import com.android.quickstep.SystemUiProxy;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
+import java.util.StringJoiner;
 
 /**
  * Normally Taskbar will auto-hide when entering immersive (fullscreen) apps. This controller allows
  * us to suspend that behavior in certain cases (e.g. opening a Folder or dragging an icon).
  */
-public class TaskbarAutohideSuspendController {
+public class TaskbarAutohideSuspendController implements
+        TaskbarControllers.LoggableTaskbarController {
 
     public static final int FLAG_AUTOHIDE_SUSPEND_FULLSCREEN = 1 << 0;
     public static final int FLAG_AUTOHIDE_SUSPEND_DRAGGING = 1 << 1;
+
     @IntDef(flag = true, value = {
             FLAG_AUTOHIDE_SUSPEND_FULLSCREEN,
             FLAG_AUTOHIDE_SUSPEND_DRAGGING,
@@ -60,4 +64,21 @@
         }
         mSystemUiProxy.notifyTaskbarAutohideSuspend(mAutohideSuspendFlags != 0);
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarAutohideSuspendController:");
+
+        pw.println(String.format(
+                "%s\tmAutohideSuspendFlags=%s", prefix, getStateString(mAutohideSuspendFlags)));
+    }
+
+    private static String getStateString(int flags) {
+        StringJoiner str = new StringJoiner("|");
+        str.add((flags & FLAG_AUTOHIDE_SUSPEND_FULLSCREEN) != 0
+                ? "FLAG_AUTOHIDE_SUSPEND_FULLSCREEN" : "");
+        str.add((flags & FLAG_AUTOHIDE_SUSPEND_DRAGGING) != 0
+                ? "FLAG_AUTOHIDE_SUSPEND_DRAGGING" : "");
+        return str.toString();
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
index 488c822..f491669 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarControllers.java
@@ -18,9 +18,11 @@
 import android.content.pm.ActivityInfo.Config;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.systemui.shared.rotation.RotationButtonController;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -30,6 +32,7 @@
 public class TaskbarControllers {
 
     public final TaskbarActivityContext taskbarActivityContext;
+
     public final TaskbarDragController taskbarDragController;
     public final TaskbarNavButtonController navButtonController;
     public final NavbarButtonsViewController navbarButtonsViewController;
@@ -45,6 +48,8 @@
     public final TaskbarAutohideSuspendController taskbarAutohideSuspendController;
     public final TaskbarPopupController taskbarPopupController;
 
+    @Nullable private LoggableTaskbarController[] mControllersToLog = null;
+
     /** Do not store this controller, as it may change at runtime. */
     @NonNull public TaskbarUIController uiController = TaskbarUIController.DEFAULT;
 
@@ -104,6 +109,14 @@
         taskbarEduController.init(this);
         taskbarPopupController.init(this);
 
+        mControllersToLog = new LoggableTaskbarController[] {
+                taskbarDragController, navButtonController, navbarButtonsViewController,
+                taskbarDragLayerController, taskbarScrimViewController, taskbarViewController,
+                taskbarUnfoldAnimationController, taskbarKeyguardController,
+                stashedHandleViewController, taskbarStashController, taskbarEduController,
+                taskbarAutohideSuspendController, taskbarPopupController
+        };
+
         mAreAllControllersInitialized = true;
         for (Runnable postInitCallback : mPostInitCallbacks) {
             postInitCallback.run();
@@ -129,6 +142,8 @@
         stashedHandleViewController.onDestroy();
         taskbarAutohideSuspendController.onDestroy();
         taskbarPopupController.onDestroy();
+
+        mControllersToLog = null;
     }
 
     /**
@@ -143,4 +158,23 @@
             mPostInitCallbacks.add(callback);
         }
     }
+
+    protected void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarControllers:");
+
+        if (mControllersToLog == null) {
+            pw.println(String.format(
+                    "%s\t%s", prefix, "All taskbar controllers have already been destroyed."));
+            return;
+        }
+
+        for (LoggableTaskbarController controller : mControllersToLog) {
+            controller.dumpLogs(prefix + "\t", pw);
+        }
+        rotationButtonController.dumpLogs(prefix + "\t", pw);
+    }
+
+    protected interface LoggableTaskbarController {
+        void dumpLogs(String prefix, PrintWriter pw);
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index 3315f8c..a698279 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -57,10 +57,14 @@
 import com.android.systemui.shared.system.ClipDescriptionCompat;
 import com.android.systemui.shared.system.LauncherAppsCompat;
 
+import java.io.PrintWriter;
+import java.util.Arrays;
+
 /**
  * Handles long click on Taskbar items to start a system drag and drop operation.
  */
-public class TaskbarDragController extends DragController<TaskbarActivityContext>  {
+public class TaskbarDragController extends DragController<TaskbarActivityContext> implements
+        TaskbarControllers.LoggableTaskbarController {
 
     private final int mDragIconSize;
     private final int[] mTempXY = new int[2];
@@ -415,4 +419,18 @@
     protected DropTarget getDefaultDropTarget(int[] dropCoordinates) {
         return null;
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarDragController:");
+
+        pw.println(String.format("%s\tmDragIconSize=%dpx", prefix, mDragIconSize));
+        pw.println(String.format("%s\tmTempXY=%s", prefix, Arrays.toString(mTempXY)));
+        pw.println(String.format("%s\tmRegistrationX=%d", prefix, mRegistrationX));
+        pw.println(String.format("%s\tmRegistrationY=%d", prefix, mRegistrationY));
+        pw.println(String.format(
+                "%s\tmIsSystemDragInProgress=%b", prefix, mIsSystemDragInProgress));
+        pw.println(String.format(
+                "%s\tisInternalDragInProgess=%b", prefix, super.isDragging()));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index a918016..fa40992 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -29,10 +29,12 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.systemui.shared.system.ViewTreeObserverWrapper.InsetsInfo;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, then passes the results to TaskbarDragLayer to render.
  */
-public class TaskbarDragLayerController {
+public class TaskbarDragLayerController implements TaskbarControllers.LoggableTaskbarController {
 
     private final TaskbarActivityContext mActivity;
     private final TaskbarDragLayer mTaskbarDragLayer;
@@ -144,6 +146,16 @@
         mNavButtonDarkIntensityMultiplier.updateValue(1 - effectiveBgAlpha);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarDragLayerController:");
+
+        pw.println(String.format("%s\tmBgOffset=%.2f", prefix, mBgOffset.value));
+        pw.println(String.format("%s\tmFolderMargin=%dpx", prefix, mFolderMargin));
+        pw.println(String.format(
+                "%s\tmLastSetBackgroundAlpha=%.2f", prefix, mLastSetBackgroundAlpha));
+    }
+
     /**
      * Callbacks for {@link TaskbarDragLayer} to interact with its controller.
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
index fd5c2ea..e29b14b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduController.java
@@ -37,12 +37,13 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.uioverrides.PredictedAppIcon;
 
+import java.io.PrintWriter;
 import java.util.Collections;
 import java.util.List;
 import java.util.stream.Collectors;
 
 /** Handles the Taskbar Education flow. */
-public class TaskbarEduController {
+public class TaskbarEduController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final long WAVE_ANIM_DELAY = 250;
     private static final long WAVE_ANIM_STAGGER = 50;
@@ -186,6 +187,18 @@
         return waveAnim;
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarEduController:");
+
+        pw.println(String.format("%s\tisShowingEdu=%b", prefix, mTaskbarEduView != null));
+        pw.println(String.format("%s\tmWaveAnimTranslationY=%.2f", prefix, mWaveAnimTranslationY));
+        pw.println(String.format(
+                "%s\tmWaveAnimTranslationYReturnOvershoot=%.2f",
+                prefix,
+                mWaveAnimTranslationYReturnOvershoot));
+    }
+
     /**
      * Callbacks for {@link TaskbarEduView} to interact with its controller.
      */
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
index 5fc0695..991bcec 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarKeyguardController.java
@@ -14,10 +14,14 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 
+import com.android.systemui.shared.system.QuickStepContract;
+
+import java.io.PrintWriter;
+
 /**
  * Controller for managing keyguard state for taskbar
  */
-public class TaskbarKeyguardController {
+public class TaskbarKeyguardController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final int KEYGUARD_SYSUI_FLAGS = SYSUI_STATE_BOUNCER_SHOWING |
             SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING | SYSUI_STATE_DEVICE_DOZING |
@@ -95,4 +99,16 @@
     public void onDestroy() {
         mContext.unregisterReceiver(mScreenOffReceiver);
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarKeyguardController:");
+
+        pw.println(String.format(
+                "%s\tmKeyguardSysuiFlags=%s",
+                prefix,
+                QuickStepContract.getSystemUiStateString(mKeyguardSysuiFlags)));
+        pw.println(String.format("%s\tmBouncerShowing=%b", prefix, mBouncerShowing));
+        pw.println(String.format("%s\tmIsScreenOff=%b", prefix, mIsScreenOff));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
index a654a56..30f2073 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarLauncherStateController.java
@@ -208,51 +208,83 @@
 
     private Animator onStateChangeApplied(int changedFlags, long duration, boolean start) {
         AnimatorSet animatorSet = new AnimatorSet();
-        if (hasAnyFlag(changedFlags, FLAG_RESUMED)) {
+
+        // Add the state animation first to ensure FLAG_IN_STASHED_LAUNCHER_STATE is set and we can
+        // determine whether goingToUnstashedLauncherStateChanged.
+        boolean wasGoingToUnstashedLauncherState = goingToUnstashedLauncherState();
+        if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) {
+            boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING);
+            playStateTransitionAnim(animatorSet, duration, committed);
+
+            if (committed && mLauncherState == LauncherState.QUICK_SWITCH) {
+                // We're about to be paused, set immediately to ensure seamless handoff.
+                updateStateForFlag(FLAG_RESUMED, false);
+                applyState(0 /* duration */);
+            }
+        }
+        boolean goingToUnstashedLauncherStateChanged = wasGoingToUnstashedLauncherState
+                != goingToUnstashedLauncherState();
+
+        boolean launcherStateChangedDuringAnimToResumeAlignment =
+                mIconAlignmentForResumedState.isAnimating() && goingToUnstashedLauncherStateChanged;
+        if (hasAnyFlag(changedFlags, FLAG_RESUMED)
+                || launcherStateChangedDuringAnimToResumeAlignment) {
             boolean isResumed = isResumed();
-            ObjectAnimator anim = mIconAlignmentForResumedState
-                    .animateToValue(isResumed && goingToUnstashedLauncherState()
-                            ? 1 : 0)
-                    .setDuration(duration);
+            float toAlignmentForResumedState = isResumed && goingToUnstashedLauncherState() ? 1 : 0;
+            // If we're already animating to the value, just leave it be instead of restarting it.
+            if (!mIconAlignmentForResumedState.isAnimatingToValue(toAlignmentForResumedState)) {
+                ObjectAnimator resumeAlignAnim = mIconAlignmentForResumedState
+                        .animateToValue(toAlignmentForResumedState)
+                        .setDuration(duration);
 
-            anim.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mIsAnimatingToLauncherViaResume = false;
-                }
+                resumeAlignAnim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mIsAnimatingToLauncherViaResume = false;
+                    }
 
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    mIsAnimatingToLauncherViaResume = isResumed;
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        mIsAnimatingToLauncherViaResume = isResumed;
 
-                    TaskbarStashController stashController = mControllers.taskbarStashController;
-                    stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
-                    stashController.applyState(duration);
-                }
-            });
-            animatorSet.play(anim);
+                        TaskbarStashController stashController =
+                                mControllers.taskbarStashController;
+                        stashController.updateStateForFlag(FLAG_IN_APP, !isResumed);
+                        stashController.applyState(duration);
+                    }
+                });
+                animatorSet.play(resumeAlignAnim);
+            }
         }
 
-        if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)) {
-            boolean isRecentsAnimationRunning = isRecentsAnimationRunning();
-            Animator animator = mIconAlignmentForGestureState
-                    .animateToValue(isRecentsAnimationRunning && goingToUnstashedLauncherState()
-                            ? 1 : 0);
-            if (isRecentsAnimationRunning) {
-                animator.setDuration(duration);
-            }
-            animator.addListener(new AnimatorListenerAdapter() {
-                @Override
-                public void onAnimationEnd(Animator animation) {
-                    mIsAnimatingToLauncherViaGesture = false;
-                }
 
-                @Override
-                public void onAnimationStart(Animator animation) {
-                    mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning();
+        boolean launcherStateChangedDuringAnimToGestureAlignment =
+                mIconAlignmentForGestureState.isAnimating() && goingToUnstashedLauncherStateChanged;
+        if (hasAnyFlag(changedFlags, FLAG_RECENTS_ANIMATION_RUNNING)
+                || launcherStateChangedDuringAnimToGestureAlignment) {
+            boolean isRecentsAnimationRunning = isRecentsAnimationRunning();
+            float toAlignmentForGestureState = isRecentsAnimationRunning
+                    && goingToUnstashedLauncherState() ? 1 : 0;
+            // If we're already animating to the value, just leave it be instead of restarting it.
+            if (!mIconAlignmentForGestureState.isAnimatingToValue(toAlignmentForGestureState)) {
+                Animator gestureAlignAnim = mIconAlignmentForGestureState
+                        .animateToValue(toAlignmentForGestureState);
+                if (isRecentsAnimationRunning) {
+                    gestureAlignAnim.setDuration(duration);
                 }
-            });
-            animatorSet.play(animator);
+                gestureAlignAnim.addListener(new AnimatorListenerAdapter() {
+                    @Override
+                    public void onAnimationEnd(Animator animation) {
+                        mIsAnimatingToLauncherViaGesture = false;
+                    }
+
+                    @Override
+                    public void onAnimationStart(Animator animation) {
+                        mIsAnimatingToLauncherViaGesture = isRecentsAnimationRunning();
+                    }
+                });
+                animatorSet.play(gestureAlignAnim);
+            }
         }
 
         if (hasAnyFlag(changedFlags, FLAG_RESUMED | FLAG_RECENTS_ANIMATION_RUNNING)) {
@@ -265,17 +297,6 @@
                     .setDuration(duration));
         }
 
-        if (hasAnyFlag(changedFlags, FLAG_TRANSITION_STATE_RUNNING)) {
-            boolean committed = !hasAnyFlag(FLAG_TRANSITION_STATE_RUNNING);
-            playStateTransitionAnim(animatorSet, duration, committed);
-
-            if (committed && mLauncherState == LauncherState.QUICK_SWITCH) {
-                // We're about to be paused, set immediately to ensure seamless handoff.
-                updateStateForFlag(FLAG_RESUMED, false);
-                applyState(0 /* duration */);
-            }
-        }
-
         if (start) {
             animatorSet.start();
         }
@@ -315,8 +336,11 @@
             animatorSet.play(stashAnimator);
         }
 
-        animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
-                .setDuration(duration));
+        // If we're already animating to the value, just leave it be instead of restarting it.
+        if (!mIconAlignmentForLauncherState.isAnimatingToValue(toAlignment)) {
+            animatorSet.play(mIconAlignmentForLauncherState.animateToValue(toAlignment)
+                    .setDuration(duration));
+        }
     }
 
     private boolean isResumed() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
index a262674..83ae98a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarManager.java
@@ -54,6 +54,8 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
+import java.io.PrintWriter;
+
 /**
  * Class to manage taskbar lifecycle
  */
@@ -305,4 +307,13 @@
     public @Nullable TaskbarActivityContext getCurrentActivityContext() {
         return mTaskbarActivityContext;
     }
+
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarManager:");
+        if (mTaskbarActivityContext == null) {
+            pw.println(prefix + "\tTaskbarActivityContext: null");
+        } else {
+            mTaskbarActivityContext.dumpLogs(prefix + "\t", pw);
+        }
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
index 37a9b5e..910752a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarModelCallbacks.java
@@ -29,6 +29,7 @@
 import com.android.launcher3.util.ItemInfoMatcher;
 import com.android.launcher3.util.LauncherBindableItemsContainer;
 
+import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -196,4 +197,15 @@
     public void bindDeepShortcutMap(HashMap<ComponentKey, Integer> deepShortcutMapCopy) {
         mControllers.taskbarPopupController.setDeepShortcutMap(deepShortcutMapCopy);
     }
+
+    protected void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarModelCallbacks:");
+
+        pw.println(String.format("%s\thotseat items count=%s", prefix, mHotseatItems.size()));
+        if (mPredictedItems != null) {
+            pw.println(
+                    String.format("%s\tpredicted items count=%s", prefix, mPredictedItems.size()));
+        }
+        pw.println(String.format("%s\tmBindInProgress=%b", prefix, mBindInProgress));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
index a601984..d72c3d2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarNavButtonController.java
@@ -33,6 +33,7 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TouchInteractionService;
 
+import java.io.PrintWriter;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
@@ -41,7 +42,7 @@
  * Handles all the functionality of the various buttons, making/routing the right calls into
  * launcher or sysui/system.
  */
-public class TaskbarNavButtonController {
+public class TaskbarNavButtonController implements TaskbarControllers.LoggableTaskbarController {
 
     /** Allow some time in between the long press for back and recents. */
     static final int SCREEN_PIN_LONG_PRESS_THRESHOLD = 200;
@@ -50,6 +51,15 @@
     private long mLastScreenPinLongPress;
     private boolean mScreenPinned;
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarNavButtonController:");
+
+        pw.println(String.format(
+                "%s\tmLastScreenPinLongPress=%dms", prefix, mLastScreenPinLongPress));
+        pw.println(String.format("%s\tmScreenPinned=%b", prefix, mScreenPinned));
+    }
+
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(value = {
             BUTTON_BACK,
@@ -143,6 +153,10 @@
                 return R.string.taskbar_button_ime_switcher;
             case BUTTON_RECENTS:
                 return R.string.taskbar_button_recents;
+            case BUTTON_NOTIFICATIONS:
+                return R.string.taskbar_button_notifications;
+            case BUTTON_QUICK_SETTINGS:
+                return R.string.taskbar_button_quick_settings;
             default:
                 return 0;
         }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index 7af9c9d..68459ab 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -40,6 +40,7 @@
 import com.android.launcher3.util.PackageUserKey;
 import com.android.launcher3.views.ActivityContext;
 
+import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.Objects;
 import java.util.function.Predicate;
@@ -49,7 +50,7 @@
 /**
  * Implements interfaces required to show and allow interacting with a PopupContainerWithArrow.
  */
-public class TaskbarPopupController {
+public class TaskbarPopupController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final SystemShortcut.Factory<TaskbarActivityContext>
             APP_INFO = SystemShortcut.AppInfo::new;
@@ -166,6 +167,13 @@
         return container;
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarPopupController:");
+
+        mPopupDataProvider.dump(prefix + "\t", pw);
+    }
+
     private class TaskbarPopupItemDragHandler implements
             PopupContainerWithArrow.PopupItemDragHandler {
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
index 4b4ee44..02bbae4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarScrimViewController.java
@@ -25,10 +25,12 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.quickstep.SystemUiProxy;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, and passes the results to {@link TaskbarScrimView} to render.
  */
-public class TaskbarScrimViewController {
+public class TaskbarScrimViewController implements TaskbarControllers.LoggableTaskbarController {
 
     private static final float SCRIM_ALPHA = 0.6f;
 
@@ -94,4 +96,11 @@
     private void onClick() {
         SystemUiProxy.INSTANCE.get(mActivity).onBackPressed();
     }
+
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarScrimViewController:");
+
+        pw.println(String.format("%s\tmScrimAlpha.value=%.2f", prefix, mScrimAlpha.value));
+    }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 076eea1..748557b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -36,13 +36,15 @@
 import com.android.quickstep.AnimatedFloat;
 import com.android.quickstep.SystemUiProxy;
 
+import java.io.PrintWriter;
+import java.util.StringJoiner;
 import java.util.function.IntPredicate;
 
 /**
  * Coordinates between controllers such as TaskbarViewController and StashedHandleViewController to
  * create a cohesive animation between stashed/unstashed states.
  */
-public class TaskbarStashController {
+public class TaskbarStashController implements TaskbarControllers.LoggableTaskbarController {
 
     public static final int FLAG_IN_APP = 1 << 0;
     public static final int FLAG_STASHED_IN_APP_MANUAL = 1 << 1; // long press, persisted
@@ -544,6 +546,34 @@
         mControllers.rotationButtonController.onTaskbarStateChange(visible, stashed);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarStashController:");
+
+        pw.println(String.format("%s\tmStashedHeight=%dpx", prefix, mStashedHeight));
+        pw.println(String.format("%s\tmUnstashedHeight=%dpx", prefix, mUnstashedHeight));
+        pw.println(String.format("%s\tmIsStashed=%b", prefix, mIsStashed));
+        pw.println(String.format(
+                "%s\tappliedState=%s", prefix, getStateString(mStatePropertyHolder.mPrevFlags)));
+        pw.println(String.format("%s\tmState=%s", prefix, getStateString(mState)));
+        pw.println(String.format(
+                "%s\tmIsSystemGestureInProgress=%b", prefix, mIsSystemGestureInProgress));
+        pw.println(String.format("%s\tmIsImeShowing=%b", prefix, mIsImeShowing));
+    }
+
+    private static String getStateString(int flags) {
+        StringJoiner str = new StringJoiner("|");
+        str.add((flags & FLAG_IN_APP) != 0 ? "FLAG_IN_APP" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_MANUAL) != 0 ? "FLAG_STASHED_IN_APP_MANUAL" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_PINNED) != 0 ? "FLAG_STASHED_IN_APP_PINNED" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_EMPTY) != 0 ? "FLAG_STASHED_IN_APP_EMPTY" : "");
+        str.add((flags & FLAG_STASHED_IN_APP_SETUP) != 0 ? "FLAG_STASHED_IN_APP_SETUP" : "");
+        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" : "");
+        return str.toString();
+    }
+
     private class StatePropertyHolder {
         private final IntPredicate mStashCondition;
 
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
index c785186..d5ea570 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUnfoldAnimationController.java
@@ -23,10 +23,13 @@
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
 import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider;
 
+import java.io.PrintWriter;
+
 /**
  * Controls animation of taskbar icons when unfolding foldable devices
  */
-public class TaskbarUnfoldAnimationController {
+public class TaskbarUnfoldAnimationController implements
+        TaskbarControllers.LoggableTaskbarController {
 
     private final ScopedUnfoldTransitionProgressProvider mUnfoldTransitionProgressProvider;
     private final UnfoldMoveFromCenterAnimator mMoveFromCenterAnimator;
@@ -59,6 +62,11 @@
         mUnfoldTransitionProgressProvider.removeCallback(mTransitionListener);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarUnfoldAnimationController:");
+    }
+
     private class TransitionListener implements TransitionProgressListener {
 
         @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index e00d177..0508994 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -39,10 +39,12 @@
 import com.android.launcher3.util.MultiValueAlpha;
 import com.android.quickstep.AnimatedFloat;
 
+import java.io.PrintWriter;
+
 /**
  * Handles properties/data collection, then passes the results to TaskbarView to render.
  */
-public class TaskbarViewController {
+public class TaskbarViewController implements TaskbarControllers.LoggableTaskbarController {
     private static final Runnable NO_OP = () -> { };
 
     public static final int ALPHA_INDEX_HOME = 0;
@@ -258,6 +260,12 @@
         return mTaskbarView.isEventOverAnyItem(ev);
     }
 
+    @Override
+    public void dumpLogs(String prefix, PrintWriter pw) {
+        pw.println(prefix + "TaskbarViewController:");
+        mModelCallbacks.dumpLogs(prefix + "\t", pw);
+    }
+
     /**
      * Callbacks for {@link TaskbarView} to interact with its controller.
      */
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
index 8f89d30..330e496 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -33,13 +33,6 @@
 
     private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE | FLAG_CLOSE_POPUPS;
 
-    private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
-        @Override
-        public float getPageAlpha(int pageIndex) {
-            return 0;
-        }
-    };
-
     public AllAppsState(int id) {
         super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
     }
@@ -82,7 +75,15 @@
 
     @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
-        return PAGE_ALPHA_PROVIDER;
+        PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
+        return new PageAlphaProvider(DEACCEL_2) {
+            @Override
+            public float getPageAlpha(int pageIndex) {
+                return launcher.getDeviceProfile().isTablet
+                        ? superPageAlphaProvider.getPageAlpha(pageIndex)
+                        : 0;
+            }
+        };
     }
 
     @Override
@@ -97,6 +98,8 @@
 
     @Override
     public int getWorkspaceScrimColor(Launcher launcher) {
-        return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
+        return launcher.getDeviceProfile().isTablet
+                ? launcher.getResources().getColor(R.color.widgets_picker_scrim)
+                : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/AnimatedFloat.java b/quickstep/src/com/android/quickstep/AnimatedFloat.java
index 95c8710..6a7d066 100644
--- a/quickstep/src/com/android/quickstep/AnimatedFloat.java
+++ b/quickstep/src/com/android/quickstep/AnimatedFloat.java
@@ -42,6 +42,8 @@
 
     private final Runnable mUpdateCallback;
     private ObjectAnimator mValueAnimator;
+    // Only non-null when an animation is playing to this value.
+    private Float mEndValue;
 
     public float value;
 
@@ -68,9 +70,17 @@
         mValueAnimator = ObjectAnimator.ofFloat(this, VALUE, start, end);
         mValueAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
+            public void onAnimationStart(Animator animator) {
+                if (mValueAnimator == animator) {
+                    mEndValue = end;
+                }
+            }
+
+            @Override
             public void onAnimationEnd(Animator animator) {
                 if (mValueAnimator == animator) {
                     mValueAnimator = null;
+                    mEndValue = null;
                 }
             }
         });
@@ -103,4 +113,15 @@
     public ObjectAnimator getCurrentAnimation() {
         return mValueAnimator;
     }
+
+    public boolean isAnimating() {
+        return mValueAnimator != null;
+    }
+
+    /**
+     * Returns whether we are currently animating, and the animation's end value matches the given.
+     */
+    public boolean isAnimatingToValue(float endValue) {
+        return isAnimating() && mEndValue != null && mEndValue == endValue;
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/RecentsActivity.java b/quickstep/src/com/android/quickstep/RecentsActivity.java
index af53bca..3e00279 100644
--- a/quickstep/src/com/android/quickstep/RecentsActivity.java
+++ b/quickstep/src/com/android/quickstep/RecentsActivity.java
@@ -38,6 +38,7 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.Looper;
+import android.view.Display;
 import android.view.SurfaceControl.Transaction;
 import android.view.View;
 import android.window.SplashScreen;
@@ -256,6 +257,9 @@
                 ActivityOptionsCompat.makeRemoteAnimation(adapterCompat),
                 onEndCallback);
         activityOptions.options.setSplashScreenStyle(SplashScreen.SPLASH_SCREEN_STYLE_ICON);
+        activityOptions.options.setLaunchDisplayId(
+                (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+                        : Display.DEFAULT_DISPLAY);
         return activityOptions;
     }
 
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 8e2b566..afb4d4d 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -27,6 +27,8 @@
 import com.android.quickstep.util.TransformParams;
 import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
 
+import java.util.ArrayList;
+
 /**
  * Glues together the necessary components to animate a remote target using a
  * {@link TaskViewSimulator}
@@ -144,20 +146,29 @@
      */
     private RemoteAnimationTargets createRemoteAnimationTargetsForTarget(
             RemoteAnimationTargets targets,
-            @Nullable RemoteAnimationTargetCompat targetToExclude) {
-        int finalLength = targets.unfilteredApps.length - (targetToExclude == null ? 0 : 1);
-        RemoteAnimationTargetCompat[] targetsWithoutExcluded =
-                new RemoteAnimationTargetCompat[finalLength];
-        int i = 0;
+            RemoteAnimationTargetCompat targetToExclude) {
+        ArrayList<RemoteAnimationTargetCompat> targetsWithoutExcluded =
+                new ArrayList<RemoteAnimationTargetCompat>();
+
         for (RemoteAnimationTargetCompat targetCompat : targets.unfilteredApps) {
             if (targetCompat == targetToExclude) {
                 continue;
             }
-            targetsWithoutExcluded[i] = targetCompat;
-            i++;
+            if (targetToExclude != null
+                    && targetToExclude.taskInfo != null
+                    && targetCompat.taskInfo != null
+                    && targetToExclude.taskInfo.parentTaskId == targetCompat.taskInfo.taskId) {
+                // Also exclude corresponding parent task
+                continue;
+            }
+
+            targetsWithoutExcluded.add(targetCompat);
         }
-        return new RemoteAnimationTargets(targetsWithoutExcluded,
-                targets.wallpapers, targets.nonApps, targets.targetMode);
+        final RemoteAnimationTargetCompat[] filteredApps =
+                targetsWithoutExcluded.toArray(
+                        new RemoteAnimationTargetCompat[targetsWithoutExcluded.size()]);
+        return new RemoteAnimationTargets(
+                filteredApps, targets.wallpapers, targets.nonApps, targets.targetMode);
     }
 
     public RemoteTargetHandle[] getRemoteTargetHandles() {
diff --git a/quickstep/src/com/android/quickstep/TaskAnimationManager.java b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
index 1af1532..914c939 100644
--- a/quickstep/src/com/android/quickstep/TaskAnimationManager.java
+++ b/quickstep/src/com/android/quickstep/TaskAnimationManager.java
@@ -220,6 +220,22 @@
         return mCallbacks;
     }
 
+    public void endLiveTile() {
+        if (mLastGestureState == null) {
+            return;
+        }
+        BaseActivityInterface activityInterface = mLastGestureState.getActivityInterface();
+        if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityInterface.isInLiveTileMode()
+                && activityInterface.getCreatedActivity() != null) {
+            RecentsView recentsView = activityInterface.getCreatedActivity().getOverviewPanel();
+            if (recentsView != null) {
+                recentsView.switchToScreenshot(null,
+                        () -> recentsView.finishRecentsAnimation(true /* toRecents */,
+                                false /* shouldPip */, null));
+            }
+        }
+    }
+
     public void setLiveTileCleanUpHandler(Runnable cleanUpHandler) {
         mLiveTileCleanUpHandler = cleanUpHandler;
     }
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index f620b62..a3d48da 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -33,6 +33,7 @@
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SHELL_STARTING_WINDOW;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SMARTSPACE_TRANSITION_CONTROLLER;
 import static com.android.systemui.shared.system.QuickStepContract.KEY_EXTRA_SYSUI_PROXY;
+import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_TRACING_ENABLED;
 
 import android.annotation.TargetApi;
@@ -479,6 +480,15 @@
             mOverviewComponentObserver.onSystemUiStateChanged();
             mTaskbarManager.onSystemUiFlagsChanged(systemUiStateFlags);
 
+            boolean wasExpanded = (lastSysUIFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
+            boolean isExpanded =
+                    (systemUiStateFlags & SYSUI_STATE_NOTIFICATION_PANEL_EXPANDED) != 0;
+            if (wasExpanded != isExpanded && isExpanded) {
+                // End live tile when expanding the notification panel for the first time from
+                // overview.
+                mTaskAnimationManager.endLiveTile();
+            }
+
             if ((lastSysUIFlags & SYSUI_STATE_TRACING_ENABLED) !=
                     (systemUiStateFlags & SYSUI_STATE_TRACING_ENABLED)) {
                 // Update the tracing state
@@ -951,6 +961,7 @@
             RecentsModel.INSTANCE.get(this).dump("", pw);
             pw.println("ProtoTrace:");
             pw.println("  file=" + ProtoTracer.INSTANCE.get(this).getTraceFile());
+            mTaskbarManager.dumpLogs("", pw);
         }
     }
 
diff --git a/res/drawable/bg_all_apps_bottom_sheet.xml b/res/drawable/bg_all_apps_bottom_sheet.xml
new file mode 100644
index 0000000..dba2fee
--- /dev/null
+++ b/res/drawable/bg_all_apps_bottom_sheet.xml
@@ -0,0 +1,29 @@
+<?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/values-sw600dp/dimens.xml b/res/values-sw600dp/dimens.xml
index 3727932..157cefa 100644
--- a/res/values-sw600dp/dimens.xml
+++ b/res/values-sw600dp/dimens.xml
@@ -20,4 +20,7 @@
 
 <!-- Widgets pickers -->
     <dimen name="widget_list_horizontal_margin">32dp</dimen>
+
+<!-- AllApps -->
+    <dimen name="all_apps_bottom_sheet_horizontal_padding">32dp</dimen>
 </resources>
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
new file mode 100644
index 0000000..9d7941f
--- /dev/null
+++ b/res/values-sw720dp/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_bottom_sheet_horizontal_padding">41dp</dimen>
+</resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 086a254..167c6b2 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -114,6 +114,7 @@
     <dimen name="all_apps_content_fade_in_offset">150dp</dimen>
     <dimen name="all_apps_tip_bottom_margin">8dp</dimen>
     <dimen name="all_apps_height_extra">6dp</dimen>
+    <dimen name="all_apps_bottom_sheet_horizontal_padding">0dp</dimen>
 
     <!-- The size of corner radius of the arrow in the arrow toast. -->
     <dimen name="arrow_toast_corner_radius">2dp</dimen>
diff --git a/src/com/android/launcher3/BaseDraggingActivity.java b/src/com/android/launcher3/BaseDraggingActivity.java
index dd56ca3..80c2d9e 100644
--- a/src/com/android/launcher3/BaseDraggingActivity.java
+++ b/src/com/android/launcher3/BaseDraggingActivity.java
@@ -182,6 +182,10 @@
         }
         ActivityOptions options =
                 ActivityOptions.makeClipRevealAnimation(v, left, top, width, height);
+
+        options.setLaunchDisplayId(
+                (v != null && v.getDisplay() != null) ? v.getDisplay().getDisplayId()
+                        : Display.DEFAULT_DISPLAY);
         RunnableList callback = new RunnableList();
         addOnResumeCallback(callback::executeAllAndDestroy);
         return new ActivityOptionsWrapper(options, callback);
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 8a5b888..a2324ac 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -174,6 +174,7 @@
     public int allAppsIconSizePx;
     public int allAppsIconDrawablePaddingPx;
     public int allAppsLeftRightPadding;
+    public int allAppsLeftRightMargin;
     public final int numShownAllAppsColumns;
     public float allAppsIconTextSizePx;
 
@@ -595,11 +596,16 @@
                 + textHeight + (topBottomPadding * 2);
     }
 
-    private void updateAllAppsWidth() {
-        if (isTwoPanels) {
+    private void updateAllAppsWidth(Resources res) {
+
+        if (isTablet) {
+            allAppsLeftRightPadding =
+                    res.getDimensionPixelSize(R.dimen.all_apps_bottom_sheet_horizontal_padding)
+                            + cellLayoutPaddingLeftRightPx;
             int usedWidth = (allAppsCellWidthPx * numShownAllAppsColumns)
-                    + (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1));
-            allAppsLeftRightPadding = Math.max(1, (availableWidthPx - usedWidth) / 2);
+                    + (allAppsBorderSpacePx.x * (numShownAllAppsColumns + 1))
+                    + allAppsLeftRightPadding * 2;
+            allAppsLeftRightMargin = Math.max(1, (availableWidthPx - usedWidth) / 2);
         } else {
             allAppsLeftRightPadding =
                     desiredWorkspaceHorizontalMarginPx + cellLayoutPaddingLeftRightPx;
@@ -709,7 +715,7 @@
             allAppsCellHeightPx = getCellSize().y;
         }
         allAppsCellWidthPx = allAppsIconSizePx + (2 * allAppsIconDrawablePaddingPx);
-        updateAllAppsWidth();
+        updateAllAppsWidth(res);
 
         if (isVerticalLayout) {
             hideWorkspaceLabelsIfNotEnoughSpace();
@@ -1102,7 +1108,10 @@
         writer.println(prefix + pxToDpStr("allAppsIconDrawablePaddingPx",
                 allAppsIconDrawablePaddingPx));
         writer.println(prefix + pxToDpStr("allAppsCellHeightPx", allAppsCellHeightPx));
+        writer.println(prefix + pxToDpStr("allAppsCellWidthPx", allAppsCellWidthPx));
         writer.println(prefix + "\tnumShownAllAppsColumns: " + numShownAllAppsColumns);
+        writer.println(prefix + pxToDpStr("allAppsLeftRightPadding", allAppsLeftRightPadding));
+        writer.println(prefix + pxToDpStr("allAppsLeftRightMargin", allAppsLeftRightMargin));
 
         writer.println(prefix + pxToDpStr("hotseatBarSizePx", hotseatBarSizePx));
         writer.println(prefix + pxToDpStr("hotseatCellHeightPx", hotseatCellHeightPx));
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 3ba6ea4..f06ec4f 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -161,6 +161,8 @@
         mNavBarScrimPaint.setColor(Themes.getAttrColor(context, R.attr.allAppsNavBarScrimColor));
 
         mAllAppsStore.addUpdateListener(this::onAppsUpdated);
+
+        updateBackground(mLauncher.getDeviceProfile());
     }
 
     @Override
@@ -224,6 +226,13 @@
                 holder.recyclerView.getRecycledViewPool().clear();
             }
         }
+        updateBackground(dp);
+    }
+
+    private void updateBackground(DeviceProfile deviceProfile) {
+        setBackground(deviceProfile.isTablet
+                ? getContext().getDrawable(R.drawable.bg_all_apps_bottom_sheet)
+                : null);
     }
 
     private void onAppsUpdated() {
@@ -389,8 +398,10 @@
         }
 
         ViewGroup.MarginLayoutParams mlp = (MarginLayoutParams) getLayoutParams();
-        mlp.leftMargin = insets.left;
-        mlp.rightMargin = insets.right;
+        mlp.topMargin = grid.isTablet ? insets.top : 0;
+        int leftRightMargin = grid.allAppsLeftRightMargin;
+        mlp.leftMargin = insets.left + leftRightMargin;
+        mlp.rightMargin = insets.right + leftRightMargin;
         setLayoutParams(mlp);
 
         if (grid.isVerticalBarLayout()) {
diff --git a/src/com/android/launcher3/allapps/FloatingHeaderView.java b/src/com/android/launcher3/allapps/FloatingHeaderView.java
index 85ee636..1f7822d 100644
--- a/src/com/android/launcher3/allapps/FloatingHeaderView.java
+++ b/src/com/android/launcher3/allapps/FloatingHeaderView.java
@@ -30,12 +30,12 @@
 import androidx.annotation.Nullable;
 import androidx.recyclerview.widget.RecyclerView;
 
-import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Insettable;
 import com.android.launcher3.R;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.uioverrides.plugins.PluginManagerWrapper;
+import com.android.launcher3.views.ActivityContext;
 import com.android.systemui.plugins.AllAppsRow;
 import com.android.systemui.plugins.AllAppsRow.OnHeightUpdatedListener;
 import com.android.systemui.plugins.PluginListener;
@@ -118,7 +118,9 @@
         mHeaderTopPadding = context.getResources()
                 .getDimensionPixelSize(R.dimen.all_apps_header_top_padding);
         mHeaderProtectionSupported = context.getResources().getBoolean(
-                R.bool.config_header_protection_supported);
+                R.bool.config_header_protection_supported)
+                // TODO(b/208599118) Support header protection for bottom sheet.
+                && !ActivityContext.lookupContext(context).getDeviceProfile().isTablet;
     }
 
     @Override
@@ -413,7 +415,7 @@
 
     @Override
     public void setInsets(Rect insets) {
-        DeviceProfile grid = BaseDraggingActivity.fromContext(getContext()).getDeviceProfile();
+        DeviceProfile grid = ActivityContext.lookupContext(getContext()).getDeviceProfile();
         for (FloatingHeaderRow row : mAllRows) {
             row.setInsets(insets, grid);
         }
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index c050c6c..1641083 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -353,6 +353,8 @@
                     mPerDisplayBounds.put(displayKey, displayBounds);
                 }
             }
+            Log.d("b/211775278", "displayId: " + displayId + ", currentSize: " + currentSize);
+            Log.d("b/211775278", "perDisplayBounds: " + mPerDisplayBounds);
         }
 
         private static Set<WindowBounds> getSupportedBoundsForDisplay(Display display, Point size) {
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 978c321..5543cc2 100644
--- a/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
+++ b/src_ui_overrides/com/android/launcher3/uioverrides/states/AllAppsState.java
@@ -34,13 +34,6 @@
 
     private static final int STATE_FLAGS = FLAG_WORKSPACE_INACCESSIBLE;
 
-    private static final PageAlphaProvider PAGE_ALPHA_PROVIDER = new PageAlphaProvider(DEACCEL_2) {
-        @Override
-        public float getPageAlpha(int pageIndex) {
-            return 0;
-        }
-    };
-
     public AllAppsState(int id) {
         super(id, LAUNCHER_STATE_ALLAPPS, STATE_FLAGS);
     }
@@ -68,7 +61,15 @@
 
     @Override
     public PageAlphaProvider getWorkspacePageAlphaProvider(Launcher launcher) {
-        return PAGE_ALPHA_PROVIDER;
+        PageAlphaProvider superPageAlphaProvider = super.getWorkspacePageAlphaProvider(launcher);
+        return new PageAlphaProvider(DEACCEL_2) {
+            @Override
+            public float getPageAlpha(int pageIndex) {
+                return launcher.getDeviceProfile().isTablet
+                        ? superPageAlphaProvider.getPageAlpha(pageIndex)
+                        : 0;
+            }
+        };
     }
 
     @Override
@@ -78,6 +79,8 @@
 
     @Override
     public int getWorkspaceScrimColor(Launcher launcher) {
-        return Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
+        return launcher.getDeviceProfile().isTablet
+                ? launcher.getResources().getColor(R.color.widgets_picker_scrim)
+                : Themes.getAttrColor(launcher, R.attr.allAppsScrimColor);
     }
 }