Merge "Play window close animation to home for most app to launcher scenarios" into sc-v2-dev
diff --git a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
index fcbea77..c80818a 100644
--- a/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/BaseQuickstepLauncher.java
@@ -24,6 +24,7 @@
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
 import static com.android.launcher3.util.DisplayController.CHANGE_ACTIVE_SCREEN;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
 import static com.android.quickstep.SysUINavigationMode.Mode.TWO_BUTTONS;
 import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_HOME_KEY;
 
@@ -35,6 +36,7 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.ServiceConnection;
+import android.graphics.Insets;
 import android.hardware.SensorManager;
 import android.hardware.devicestate.DeviceStateManager;
 import android.os.Bundle;
@@ -43,6 +45,7 @@
 import android.os.IBinder;
 import android.util.Log;
 import android.view.View;
+import android.view.WindowInsets;
 import android.window.SplashScreen;
 
 import androidx.annotation.Nullable;
@@ -639,4 +642,17 @@
             mDepthController.dump(prefix, writer);
         }
     }
+
+    @Override
+    public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
+            WindowInsets oldInsets) {
+        // Override the tappable insets to be 0 on the bottom for gesture nav (otherwise taskbar
+        // would count towards it). This is used for the bottom protection in All Apps for example.
+        if (SysUINavigationMode.getMode(this) == NO_BUTTON) {
+            Insets oldTappableInsets = oldInsets.getInsets(WindowInsets.Type.tappableElement());
+            Insets newTappableInsets = Insets.of(oldTappableInsets.left, oldTappableInsets.top,
+                    oldTappableInsets.right, 0);
+            updatedInsetsBuilder.setInsets(WindowInsets.Type.tappableElement(), newTappableInsets);
+        }
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
index 978fb57..e3e7b33 100644
--- a/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskOverlayFactory.java
@@ -51,6 +51,7 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskThumbnailView;
 import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.model.ThumbnailData;
 
@@ -63,11 +64,16 @@
 public class TaskOverlayFactory implements ResourceBasedOverride {
 
     public static List<SystemShortcut> getEnabledShortcuts(TaskView taskView,
-            DeviceProfile deviceProfile) {
+            DeviceProfile deviceProfile, TaskIdAttributeContainer taskContainer) {
         final ArrayList<SystemShortcut> shortcuts = new ArrayList<>();
         final BaseDraggingActivity activity = BaseActivity.fromContext(taskView.getContext());
+        boolean hasMultipleTasks = taskView.getTaskIds()[1] != -1;
         for (TaskShortcutFactory menuOption : MENU_OPTIONS) {
-            SystemShortcut shortcut = menuOption.getShortcut(activity, taskView);
+            if (hasMultipleTasks && !menuOption.showForSplitscreen()) {
+                continue;
+            }
+
+            SystemShortcut shortcut = menuOption.getShortcut(activity, taskContainer);
             if (shortcut == null) {
                 continue;
             }
@@ -87,7 +93,7 @@
         if (!canLauncherRotate && isInLandscape) {
             // Add screenshot action to task menu.
             SystemShortcut screenshotShortcut = TaskShortcutFactory.SCREENSHOT
-                    .getShortcut(activity, taskView);
+                    .getShortcut(activity, taskContainer);
             if (screenshotShortcut != null) {
                 shortcuts.add(screenshotShortcut);
             }
@@ -95,7 +101,7 @@
             // Add modal action only if display orientation is the same as the device orientation.
             if (orientedState.getDisplayRotation() == ROTATION_0) {
                 SystemShortcut modalShortcut = TaskShortcutFactory.MODAL
-                        .getShortcut(activity, taskView);
+                        .getShortcut(activity, taskContainer);
                 if (modalShortcut != null) {
                     shortcuts.add(modalShortcut);
                 }
@@ -105,7 +111,7 @@
     }
 
 
-    public static void addSplitOptions(List<SystemShortcut> outShortcuts,
+    private static void addSplitOptions(List<SystemShortcut> outShortcuts,
             BaseDraggingActivity activity, TaskView taskView, DeviceProfile deviceProfile) {
         int[] taskViewTaskIds = taskView.getTaskIds();
         boolean alreadyHasMultipleTasks = taskViewTaskIds[0] != -1 &&
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index 559125e..dbb5f10 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -45,6 +45,7 @@
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskThumbnailView;
 import com.android.quickstep.views.TaskView;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecCompat;
 import com.android.systemui.shared.recents.view.AppTransitionAnimationSpecsFuture;
@@ -61,9 +62,25 @@
  * Represents a system shortcut that can be shown for a recent task.
  */
 public interface TaskShortcutFactory {
-    SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView view);
+    SystemShortcut getShortcut(BaseDraggingActivity activity,
+            TaskIdAttributeContainer taskContainer);
 
-    TaskShortcutFactory APP_INFO = (activity, view) -> new AppInfo(activity, view.getItemInfo());
+    default boolean showForSplitscreen() {
+        return false;
+    }
+
+    TaskShortcutFactory APP_INFO = new TaskShortcutFactory() {
+        @Override
+        public SystemShortcut getShortcut(BaseDraggingActivity activity,
+                TaskIdAttributeContainer taskContainer) {
+            return new AppInfo(activity, taskContainer.getItemInfo());
+        }
+
+        @Override
+        public boolean showForSplitscreen() {
+            return true;
+        }
+    };
 
     abstract class MultiWindowFactory implements TaskShortcutFactory {
 
@@ -82,15 +99,16 @@
         protected abstract boolean onActivityStarted(BaseDraggingActivity activity);
 
         @Override
-        public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
-            final Task task  = taskView.getTask();
+        public SystemShortcut getShortcut(BaseDraggingActivity activity,
+                TaskIdAttributeContainer taskContainer) {
+            final Task task  = taskContainer.getTask();
             if (!task.isDockable) {
                 return null;
             }
             if (!isAvailable(activity, task.key.displayId)) {
                 return null;
             }
-            return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskView, this,
+            return new MultiWindowSystemShortcut(mIconRes, mTextRes, activity, taskContainer, this,
                     mLauncherEvent);
         }
     }
@@ -123,13 +141,14 @@
         private final LauncherEvent mLauncherEvent;
 
         public MultiWindowSystemShortcut(int iconRes, int textRes, BaseDraggingActivity activity,
-                TaskView taskView, MultiWindowFactory factory, LauncherEvent launcherEvent) {
-            super(iconRes, textRes, activity, taskView.getItemInfo());
+                TaskIdAttributeContainer taskContainer, MultiWindowFactory factory,
+                LauncherEvent launcherEvent) {
+            super(iconRes, textRes, activity, taskContainer.getItemInfo());
             mLauncherEvent = launcherEvent;
             mHandler = new Handler(Looper.getMainLooper());
-            mTaskView = taskView;
+            mTaskView = taskContainer.getTaskView();
             mRecentsView = activity.getOverviewPanel();
-            mThumbnailView = taskView.getThumbnail();
+            mThumbnailView = taskContainer.getThumbnailView();
             mFactory = factory;
         }
 
@@ -233,11 +252,13 @@
         }
 
         @Override
-        public SystemShortcut getShortcut(BaseDraggingActivity activity, TaskView taskView) {
-            SystemShortcut shortcut = super.getShortcut(activity, taskView);
+        public SystemShortcut getShortcut(BaseDraggingActivity activity,
+                TaskIdAttributeContainer taskContainer) {
+            SystemShortcut shortcut = super.getShortcut(activity, taskContainer);
             if (shortcut != null && FeatureFlags.ENABLE_SPLIT_SELECT.get()) {
                 // Disable if there's only one recent app for split screen
-                shortcut.setEnabled(taskView.getRecentsView().getTaskViewCount() > 1);
+                shortcut.setEnabled(taskContainer.getTaskView().
+                        getRecentsView().getTaskViewCount() > 1);
             }
             return shortcut;
         }
@@ -284,7 +305,7 @@
         }
     };
 
-    TaskShortcutFactory PIN = (activity, tv) -> {
+    TaskShortcutFactory PIN = (activity, taskContainer) -> {
         if (!SystemUiProxy.INSTANCE.get(activity).isActive()) {
             return null;
         }
@@ -295,7 +316,7 @@
             // We shouldn't be able to pin while an app is locked.
             return null;
         }
-        return new PinSystemShortcut(activity, tv);
+        return new PinSystemShortcut(activity, taskContainer);
     };
 
     class PinSystemShortcut extends SystemShortcut {
@@ -304,9 +325,11 @@
 
         private final TaskView mTaskView;
 
-        public PinSystemShortcut(BaseDraggingActivity target, TaskView tv) {
-            super(R.drawable.ic_pin, R.string.recent_task_option_pin, target, tv.getItemInfo());
-            mTaskView = tv;
+        public PinSystemShortcut(BaseDraggingActivity target,
+                TaskIdAttributeContainer taskContainer) {
+            super(R.drawable.ic_pin, R.string.recent_task_option_pin, target,
+                    taskContainer.getItemInfo());
+            mTaskView = taskContainer.getTaskView();
         }
 
         @Override
@@ -320,20 +343,22 @@
         }
     }
 
-    TaskShortcutFactory INSTALL = (activity, view) ->
+    TaskShortcutFactory INSTALL = (activity, taskContainer) ->
             InstantAppResolver.newInstance(activity).isInstantApp(activity,
-                 view.getTask().getTopComponent().getPackageName())
-                    ? new SystemShortcut.Install(activity, view.getItemInfo()) : null;
+                 taskContainer.getTask().getTopComponent().getPackageName())
+                    ? new SystemShortcut.Install(activity, taskContainer.getItemInfo()) : null;
 
-    TaskShortcutFactory WELLBEING = (activity, view) ->
-            WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, view.getItemInfo());
+    TaskShortcutFactory WELLBEING = (activity, taskContainer) ->
+            WellbeingModel.SHORTCUT_FACTORY.getShortcut(activity, taskContainer.getItemInfo());
 
-    TaskShortcutFactory SCREENSHOT = (activity, tv) -> tv.getThumbnail().getTaskOverlay()
-            .getScreenshotShortcut(activity, tv.getItemInfo());
+    TaskShortcutFactory SCREENSHOT = (activity, taskContainer) ->
+            taskContainer.getThumbnailView().getTaskOverlay()
+                    .getScreenshotShortcut(activity, taskContainer.getItemInfo());
 
-    TaskShortcutFactory MODAL = (activity, tv) -> {
+    TaskShortcutFactory MODAL = (activity, taskContainer) -> {
         if (ENABLE_OVERVIEW_SELECTIONS.get()) {
-            return tv.getThumbnail().getTaskOverlay().getModalStateSystemShortcut(tv.getItemInfo());
+            return taskContainer.getThumbnailView()
+                    .getTaskOverlay().getModalStateSystemShortcut(taskContainer.getItemInfo());
         }
         return null;
     };
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index b1b4b54..72d3731 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -1,5 +1,8 @@
 package com.android.quickstep.views;
 
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
+
 import android.content.Context;
 import android.graphics.Rect;
 import android.util.AttributeSet;
@@ -11,7 +14,6 @@
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.util.RunnableList;
-import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
 import com.android.launcher3.util.TransformingTouchDelegate;
 import com.android.quickstep.RecentsModel;
@@ -72,7 +74,9 @@
         super.bind(primary, orientedState);
         mSecondaryTask = secondary;
         mTaskIdContainer[1] = secondary.key.id;
-        mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2);
+        mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2,
+                STAGE_POSITION_BOTTOM_OR_RIGHT);
+        mTaskIdAttributeContainer[0].setStagePosition(STAGE_POSITION_TOP_OR_LEFT);
         mSnapshotView2.bind(secondary);
         mSplitBoundsConfig = splitBoundsConfig;
     }
@@ -112,6 +116,10 @@
         }
     }
 
+    protected boolean showTaskMenuWithContainer(IconView iconView) {
+        return TaskMenuView.showForTask(mTaskIdAttributeContainer[iconView == mIconView ? 0 : 1]);
+    }
+
     public void updateSplitBoundsConfig(StagedSplitBounds stagedSplitBounds) {
         mSplitBoundsConfig = stagedSplitBounds;
         invalidate();
@@ -143,14 +151,14 @@
     @Override
     public RunnableList launchTaskAnimated() {
         getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
-                SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
+                STAGE_POSITION_TOP_OR_LEFT, null /*callback*/);
         return null;
     }
 
     @Override
     public void launchTask(@NonNull Consumer<Boolean> callback, boolean freezeTaskList) {
         getRecentsView().getSplitPlaceholder().launchTasks(mTask, mSecondaryTask,
-                SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT, callback);
+                STAGE_POSITION_TOP_OR_LEFT, callback);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/views/TaskMenuView.java b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
index bfc7eea..5ddbf87 100644
--- a/quickstep/src/com/android/quickstep/views/TaskMenuView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskMenuView.java
@@ -16,6 +16,8 @@
 
 package com.android.quickstep.views;
 
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
 import static com.android.quickstep.views.TaskThumbnailView.DIM_ALPHA;
 
 import android.animation.Animator;
@@ -39,6 +41,7 @@
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.BaseDraggingActivity;
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimationSuccessListener;
 import com.android.launcher3.anim.Interpolators;
@@ -49,6 +52,7 @@
 import com.android.quickstep.TaskOverlayFactory;
 import com.android.quickstep.TaskUtils;
 import com.android.quickstep.util.TaskCornerRadius;
+import com.android.quickstep.views.TaskView.TaskIdAttributeContainer;
 
 /**
  * Contains options for a recent task when long-pressing its icon.
@@ -65,6 +69,7 @@
     private TextView mTaskName;
     private AnimatorSet mOpenCloseAnimator;
     private TaskView mTaskView;
+    private TaskIdAttributeContainer mTaskContainer;
     private LinearLayout mOptionLayout;
 
     public TaskMenuView(Context context, AttributeSet attrs) {
@@ -129,7 +134,8 @@
         // Inset due to margin
         PointF additionalInset = pagedOrientationHandler
                 .getAdditionalInsetForTaskMenu(mTaskInsetMargin);
-        int taskTopMargin = mActivity.getDeviceProfile().overviewTaskThumbnailTopMarginPx;
+        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        int taskTopMargin = deviceProfile.overviewTaskThumbnailTopMarginPx;
 
         float adjustedY = y + taskTopMargin - additionalInset.y;
         float adjustedX = x - additionalInset.x;
@@ -137,7 +143,7 @@
         // NOTE: Changing the pivots means the rotated view gets rotated about the new pivots set,
         // which would render the X and Y position set here incorrect
         setPivotX(0);
-        if (mActivity.getDeviceProfile().overviewShowAsGrid) {
+        if (deviceProfile.overviewShowAsGrid) {
             // In tablet, set pivotY to original position without mThumbnailTopMargin adjustment.
             setPivotY(-taskTopMargin);
         } else {
@@ -145,9 +151,26 @@
         }
         setRotation(pagedOrientationHandler.getDegreesRotated());
         setX(pagedOrientationHandler.getTaskMenuX(adjustedX,
-                mTaskView.getThumbnail(), overscrollShift));
+                mTaskContainer.getThumbnailView(), overscrollShift));
         setY(pagedOrientationHandler.getTaskMenuY(
-                adjustedY, mTaskView.getThumbnail(), overscrollShift));
+                adjustedY, mTaskContainer.getThumbnailView(), overscrollShift));
+
+        // TODO(b/193432925) temporary menu placement for split screen task menus
+        TaskIdAttributeContainer[] taskIdAttributeContainers =
+                mTaskView.getTaskIdAttributeContainers();
+        if (taskIdAttributeContainers[0].getStagePosition() != STAGE_POSITION_UNDEFINED) {
+            if (mTaskContainer.getStagePosition() != STAGE_POSITION_BOTTOM_OR_RIGHT) {
+                return;
+            }
+            Rect r = new Rect();
+            mTaskContainer.getThumbnailView().getBoundsOnScreen(r);
+            if (deviceProfile.isLandscape) {
+                setX(r.left);
+            } else {
+                setY(r.top);
+
+            }
+        }
     }
 
     public void onRotationChanged() {
@@ -162,19 +185,21 @@
         }
     }
 
-    public static boolean showForTask(TaskView taskView) {
-        BaseDraggingActivity activity = BaseDraggingActivity.fromContext(taskView.getContext());
+    public static boolean showForTask(TaskIdAttributeContainer taskContainer) {
+        BaseDraggingActivity activity = BaseDraggingActivity.fromContext(
+                taskContainer.getTaskView().getContext());
         final TaskMenuView taskMenuView = (TaskMenuView) activity.getLayoutInflater().inflate(
                         R.layout.task_menu, activity.getDragLayer(), false);
-        return taskMenuView.populateAndShowForTask(taskView);
+        return taskMenuView.populateAndShowForTask(taskContainer);
     }
 
-    private boolean populateAndShowForTask(TaskView taskView) {
+    private boolean populateAndShowForTask(TaskIdAttributeContainer taskContainer) {
         if (isAttachedToWindow()) {
             return false;
         }
         mActivity.getDragLayer().addView(this);
-        mTaskView = taskView;
+        mTaskView = taskContainer.getTaskView();
+        mTaskContainer = taskContainer;
         if (!populateAndLayoutMenu()) {
             return false;
         }
@@ -192,20 +217,21 @@
 
     /** @return true if successfully able to populate task view menu, false otherwise */
     private boolean populateAndLayoutMenu() {
-        if (mTaskView.getTask().icon == null) {
+        if (mTaskContainer.getTask().icon == null) {
             // Icon may not be loaded
             return false;
         }
-        addMenuOptions(mTaskView);
-        orientAroundTaskView(mTaskView);
+        addMenuOptions(mTaskContainer);
+        orientAroundTaskView(mTaskContainer);
         return true;
     }
 
-    private void addMenuOptions(TaskView taskView) {
-        mTaskName.setText(TaskUtils.getTitle(getContext(), taskView.getTask()));
+    private void addMenuOptions(TaskIdAttributeContainer taskContainer) {
+        mTaskName.setText(TaskUtils.getTitle(getContext(), taskContainer.getTask()));
         mTaskName.setOnClickListener(v -> close(true));
         
-        TaskOverlayFactory.getEnabledShortcuts(taskView, mActivity.getDeviceProfile())
+        TaskOverlayFactory.getEnabledShortcuts(mTaskView, mActivity.getDeviceProfile(),
+                taskContainer)
                 .forEach(this::addMenuOption);
     }
 
@@ -223,23 +249,25 @@
         mOptionLayout.addView(menuOptionView);
     }
 
-    private void orientAroundTaskView(TaskView taskView) {
-        PagedOrientationHandler orientationHandler = taskView.getPagedOrientationHandler();
+    private void orientAroundTaskView(TaskIdAttributeContainer taskContainer) {
+        RecentsView recentsView = mActivity.getOverviewPanel();
+        PagedOrientationHandler orientationHandler = recentsView.getPagedOrientationHandler();
         measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
         orientationHandler.setTaskMenuAroundTaskView(this, mTaskInsetMargin);
 
         // Get Position
-        mActivity.getDragLayer().getDescendantRectRelativeToSelf(taskView, sTempRect);
+        mActivity.getDragLayer().getDescendantRectRelativeToSelf(mTaskView, sTempRect);
         Rect insets = mActivity.getDragLayer().getInsets();
         BaseDragLayer.LayoutParams params = (BaseDragLayer.LayoutParams) getLayoutParams();
         int padding = getResources()
                 .getDimensionPixelSize(R.dimen.task_menu_vertical_padding);
-        params.width = orientationHandler.getTaskMenuWidth(taskView.getThumbnail()) - (2 * padding);
+        params.width = orientationHandler
+                .getTaskMenuWidth(taskContainer.getThumbnailView()) - (2 * padding);
         // Gravity set to Left instead of Start as sTempRect.left measures Left distance not Start
         params.gravity = Gravity.LEFT;
         setLayoutParams(params);
-        setScaleX(taskView.getScaleX());
-        setScaleY(taskView.getScaleY());
+        setScaleX(mTaskView.getScaleX());
+        setScaleY(mTaskView.getScaleY());
 
         // Set divider spacing
         ShapeDrawable divider = new ShapeDrawable(new RectShape());
@@ -272,7 +300,7 @@
         revealAnimator.setInterpolator(Interpolators.DEACCEL);
         mOpenCloseAnimator.playTogether(revealAnimator,
                 ObjectAnimator.ofFloat(
-                        mTaskView.getThumbnail(), DIM_ALPHA,
+                        mTaskContainer.getThumbnailView(), DIM_ALPHA,
                         closing ? 0 : TaskView.MAX_PAGE_SCRIM_ALPHA),
                 ObjectAnimator.ofFloat(this, ALPHA, closing ? 0 : 1));
         mOpenCloseAnimator.addListener(new AnimationSuccessListener() {
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 461a89b..053d07c 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -18,13 +18,6 @@
 
 import static android.view.Gravity.BOTTOM;
 import static android.view.Gravity.CENTER_HORIZONTAL;
-import static android.view.Gravity.CENTER_VERTICAL;
-import static android.view.Gravity.END;
-import static android.view.Gravity.START;
-import static android.view.Gravity.TOP;
-import static android.view.Surface.ROTATION_180;
-import static android.view.Surface.ROTATION_270;
-import static android.view.Surface.ROTATION_90;
 import static android.widget.Toast.LENGTH_SHORT;
 
 import static com.android.launcher3.AbstractFloatingView.TYPE_TASK_MENU;
@@ -39,6 +32,7 @@
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASK_LAUNCH_TAP;
 import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
 import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
+import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_UNDEFINED;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
@@ -58,7 +52,6 @@
 import android.util.FloatProperty;
 import android.util.Log;
 import android.view.MotionEvent;
-import android.view.Surface;
 import android.view.TouchDelegate;
 import android.view.View;
 import android.view.ViewGroup;
@@ -86,6 +79,7 @@
 import com.android.launcher3.util.ActivityOptionsWrapper;
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.RunnableList;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.util.TransformingTouchDelegate;
 import com.android.launcher3.util.ViewPool.Reusable;
@@ -466,7 +460,10 @@
      * Builds proto for logging
      */
     public WorkspaceItemInfo getItemInfo() {
-        final Task task = getTask();
+        return getItemInfo(mTask);
+    }
+
+    protected WorkspaceItemInfo getItemInfo(Task task) {
         ComponentKey componentKey = TaskUtils.getLaunchComponentKeyForTask(task.key);
         WorkspaceItemInfo stubInfo = new WorkspaceItemInfo();
         stubInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_TASK;
@@ -569,7 +566,8 @@
         cancelPendingLoadTasks();
         mTask = task;
         mTaskIdContainer[0] = mTask.key.id;
-        mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView);
+        mTaskIdAttributeContainer[0] = new TaskIdAttributeContainer(task, mSnapshotView,
+                STAGE_POSITION_UNDEFINED);
         mSnapshotView.bind(task);
         setOrientationState(orientedState);
     }
@@ -825,7 +823,7 @@
         }
     }
 
-    private boolean showTaskMenu() {
+    private boolean showTaskMenu(IconView iconView) {
         if (getRecentsView().mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
             // Don't show menu when selecting second split screen app
             return true;
@@ -837,10 +835,14 @@
         } else {
             mActivity.getStatsLogManager().logger().withItemInfo(getItemInfo())
                     .log(LAUNCHER_TASK_ICON_TAP_OR_LONGPRESS);
-            return TaskMenuView.showForTask(this);
+            return showTaskMenuWithContainer(iconView);
         }
     }
 
+    protected boolean showTaskMenuWithContainer(IconView iconView) {
+        return TaskMenuView.showForTask(mTaskIdAttributeContainer[0]);
+    }
+
     protected void setIcon(IconView iconView, Drawable icon) {
         if (icon != null) {
             iconView.setDrawable(icon);
@@ -850,14 +852,14 @@
                     recentsView.switchToScreenshot(
                             () -> recentsView.finishRecentsAnimation(true /* toRecents */,
                                     false /* shouldPip */,
-                                    this::showTaskMenu));
+                                    () -> showTaskMenu(iconView)));
                 } else {
-                    showTaskMenu();
+                    showTaskMenu(iconView);
                 }
             });
             iconView.setOnLongClickListener(v -> {
                 requestDisallowInterceptTouchEvent(true);
-                return showTaskMenu();
+                return showTaskMenu(iconView);
             });
         } else {
             iconView.setDrawable(null);
@@ -1328,8 +1330,9 @@
                         getContext().getText(R.string.accessibility_close)));
 
         final Context context = getContext();
+        // TODO(b/200609838) Determine which task to run A11y action on when in split screen
         for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
-                mActivity.getDeviceProfile())) {
+                mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) {
             info.addAction(s.createAccessibilityAction(context));
         }
 
@@ -1361,8 +1364,9 @@
             return true;
         }
 
+        // TODO(b/200609838) Determine which task to run A11y action on when in split screen
         for (SystemShortcut s : TaskOverlayFactory.getEnabledShortcuts(this,
-                mActivity.getDeviceProfile())) {
+                mActivity.getDeviceProfile(), mTaskIdAttributeContainer[0])) {
             if (s.hasHandlerForAction(action)) {
                 s.onClick(this);
                 return true;
@@ -1581,20 +1585,40 @@
     }
 
     public class TaskIdAttributeContainer {
-        private final TaskThumbnailView thumbnailView;
-        private final Task task;
+        private final TaskThumbnailView mThumbnailView;
+        private final Task mTask;
+        /** Defaults to STAGE_POSITION_UNDEFINED if in not a split screen task view */
+        private @SplitConfigurationOptions.StagePosition int mStagePosition;
 
-        public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView) {
-            this.task = task;
-            this.thumbnailView = thumbnailView;
+        public TaskIdAttributeContainer(Task task, TaskThumbnailView thumbnailView,
+                int stagePosition) {
+            this.mTask = task;
+            this.mThumbnailView = thumbnailView;
+            this.mStagePosition = stagePosition;
         }
 
         public TaskThumbnailView getThumbnailView() {
-            return thumbnailView;
+            return mThumbnailView;
         }
 
         public Task getTask() {
-            return task;
+            return mTask;
+        }
+
+        public WorkspaceItemInfo getItemInfo() {
+            return TaskView.this.getItemInfo(mTask);
+        }
+
+        public TaskView getTaskView() {
+            return TaskView.this;
+        }
+
+        public int getStagePosition() {
+            return mStagePosition;
+        }
+
+        void setStagePosition(@SplitConfigurationOptions.StagePosition int stagePosition) {
+            this.mStagePosition = stagePosition;
         }
     }
 }
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index f26cfe8..28afc57 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -4,15 +4,20 @@
 
 import android.annotation.TargetApi;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Canvas;
+import android.graphics.Insets;
 import android.graphics.Rect;
 import android.os.Build;
 import android.util.AttributeSet;
 import android.view.ViewDebug;
 import android.view.WindowInsets;
 
+import androidx.annotation.RequiresApi;
+
 import com.android.launcher3.graphics.SysUiScrim;
 import com.android.launcher3.statemanager.StatefulActivity;
+import com.android.launcher3.uioverrides.ApiWrapper;
 
 import java.util.Collections;
 import java.util.List;
@@ -61,12 +66,75 @@
 
     @Override
     public WindowInsets onApplyWindowInsets(WindowInsets insets) {
-        mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
-                insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+        if (Utilities.ATLEAST_R) {
+            insets = updateInsetsDueToTaskbar(insets);
+            Insets systemWindowInsets = insets.getInsetsIgnoringVisibility(
+                    WindowInsets.Type.systemBars() | WindowInsets.Type.displayCutout());
+            mTempRect.set(systemWindowInsets.left, systemWindowInsets.top, systemWindowInsets.right,
+                    systemWindowInsets.bottom);
+        } else {
+            mTempRect.set(insets.getSystemWindowInsetLeft(), insets.getSystemWindowInsetTop(),
+                    insets.getSystemWindowInsetRight(), insets.getSystemWindowInsetBottom());
+        }
         handleSystemWindowInsets(mTempRect);
         return insets;
     }
 
+    /**
+     * Taskbar provides nav bar and tappable insets. However, taskbar is not attached immediately,
+     * and can be destroyed and recreated. Thus, instead of relying on taskbar being present to
+     * get its insets, we calculate them ourselves so they are stable regardless of whether taskbar
+     * is currently attached.
+     *
+     * TODO(b/198798034): Currently we always calculate nav insets as taskbarSize, but then we
+     * subtract nonOverlappingTaskbarInset in handleSystemWindowInsets(). Instead, we should just
+     * calculate the normal nav bar height here, and remove nonOverlappingTaskbarInset altogether.
+     *
+     * @param oldInsets The system-provided insets, which we are modifying.
+     * @return The updated insets.
+     */
+    @RequiresApi(api = Build.VERSION_CODES.R)
+    private WindowInsets updateInsetsDueToTaskbar(WindowInsets oldInsets) {
+        if (!ApiWrapper.TASKBAR_DRAWN_IN_PROCESS) {
+            // 3P launchers based on Launcher3 should still be inset like normal.
+            return oldInsets;
+        }
+
+        WindowInsets.Builder updatedInsetsBuilder = new WindowInsets.Builder(oldInsets);
+
+        DeviceProfile dp = mActivity.getDeviceProfile();
+        Resources resources = getResources();
+
+        Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
+        Rect newNavInsets = new Rect(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
+                oldNavInsets.bottom);
+        if (dp.isTaskbarPresent) {
+            // TODO (see javadoc): Remove this block and fall into the next one instead.
+            newNavInsets.bottom = dp.taskbarSize;
+        } else if (dp.isLandscape) {
+            if (dp.isTablet) {
+                newNavInsets.bottom = ResourceUtils.getNavbarSize(
+                        "navigation_bar_height_landscape", resources);
+            } else {
+                int navWidth = ResourceUtils.getNavbarSize("navigation_bar_width", resources);
+                if (dp.isSeascape()) {
+                    newNavInsets.left = navWidth;
+                } else {
+                    newNavInsets.right = navWidth;
+                }
+            }
+        } else {
+            newNavInsets.bottom = ResourceUtils.getNavbarSize("navigation_bar_height", resources);
+        }
+        updatedInsetsBuilder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(newNavInsets));
+        updatedInsetsBuilder.setInsetsIgnoringVisibility(WindowInsets.Type.navigationBars(),
+                Insets.of(newNavInsets));
+
+        mActivity.updateWindowInsets(updatedInsetsBuilder, oldInsets);
+
+        return updatedInsetsBuilder.build();
+    }
+
     @Override
     public void setInsets(Rect insets) {
         // If the insets haven't changed, this is a no-op. Avoid unnecessary layout caused by
diff --git a/src/com/android/launcher3/allapps/AllAppsContainerView.java b/src/com/android/launcher3/allapps/AllAppsContainerView.java
index 63fd9a0..a701548 100644
--- a/src/com/android/launcher3/allapps/AllAppsContainerView.java
+++ b/src/com/android/launcher3/allapps/AllAppsContainerView.java
@@ -426,8 +426,7 @@
     @Override
     public WindowInsets dispatchApplyWindowInsets(WindowInsets insets) {
         if (Utilities.ATLEAST_Q) {
-            mNavBarScrimHeight = insets.getTappableElementInsets().bottom
-                    - mLauncher.getDeviceProfile().nonOverlappingTaskbarInset;
+            mNavBarScrimHeight = insets.getTappableElementInsets().bottom;
         } else {
             mNavBarScrimHeight = insets.getStableInsetBottom();
         }
diff --git a/src/com/android/launcher3/statemanager/StatefulActivity.java b/src/com/android/launcher3/statemanager/StatefulActivity.java
index 8a35cb3..7a23caa 100644
--- a/src/com/android/launcher3/statemanager/StatefulActivity.java
+++ b/src/com/android/launcher3/statemanager/StatefulActivity.java
@@ -17,11 +17,15 @@
 
 import static com.android.launcher3.LauncherState.FLAG_NON_INTERACTIVE;
 
+import android.graphics.Insets;
+import android.os.Build;
 import android.os.Handler;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.WindowInsets;
 
 import androidx.annotation.CallSuper;
+import androidx.annotation.RequiresApi;
 
 import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.LauncherRootView;
@@ -173,4 +177,12 @@
         mHandler.removeCallbacks(mHandleDeferredResume);
         Utilities.postAsyncCallback(mHandler, mHandleDeferredResume);
     }
+
+    /**
+     * Gives subclasses a chance to override some window insets (via
+     * {@link android.view.WindowInsets.Builder#setInsets(int, Insets)}).
+     */
+    @RequiresApi(api = Build.VERSION_CODES.R)
+    public void updateWindowInsets(WindowInsets.Builder updatedInsetsBuilder,
+            WindowInsets oldInsets) { }
 }
diff --git a/src/com/android/launcher3/widget/WidgetsBottomSheet.java b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
index bb4638a..68532ca 100644
--- a/src/com/android/launcher3/widget/WidgetsBottomSheet.java
+++ b/src/com/android/launcher3/widget/WidgetsBottomSheet.java
@@ -36,7 +36,6 @@
 import android.widget.TableRow;
 import android.widget.TextView;
 
-import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.model.WidgetItem;
@@ -70,7 +69,6 @@
     private static final long EDUCATION_TIP_DELAY_MS = 300;
 
     private ItemInfo mOriginalItemInfo;
-    private final int mMaxTableHeight;
     private int mMaxHorizontalSpan = DEFAULT_MAX_HORIZONTAL_SPANS;
     private final int mWidgetCellHorizontalPadding;
 
@@ -110,10 +108,6 @@
     public WidgetsBottomSheet(Context context, AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
         setWillNotDraw(false);
-        DeviceProfile deviceProfile = mActivityContext.getDeviceProfile();
-        // Set the max table height to 2 / 3 of the grid height so that the bottom picker won't
-        // take over the entire view vertically.
-        mMaxTableHeight = deviceProfile.inv.numRows * 2 / 3  * deviceProfile.cellHeightPx;
         if (!hasSeenEducationTip()) {
             addOnLayoutChangeListener(mLayoutChangeListenerToShowTips);
         }
@@ -162,13 +156,9 @@
 
         setTranslationShift(mTranslationShift);
 
-        // Ensure the scroll view height is not larger than mMaxTableHeight, which is a value
-        // smaller than the entire screen height.
         ScrollView widgetsTableScrollView = findViewById(R.id.widgets_table_scroll_view);
-        if (widgetsTableScrollView.getMeasuredHeight() > mMaxTableHeight) {
-            ViewGroup.LayoutParams layoutParams = widgetsTableScrollView.getLayoutParams();
-            layoutParams.height = mMaxTableHeight;
-            widgetsTableScrollView.setLayoutParams(layoutParams);
+        TableLayout widgetsTable = findViewById(R.id.widgets_table);
+        if (widgetsTable.getMeasuredHeight() > widgetsTableScrollView.getMeasuredHeight()) {
             findViewById(R.id.collapse_handle).setVisibility(VISIBLE);
         }
     }