Merge "Skip sending user home when the overview command queue is pending." into udc-qpr-dev
diff --git a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
index 8c8e267..d241260 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/BaseRecentsViewStateController.java
@@ -46,6 +46,7 @@
 import com.android.launcher3.LauncherState;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.dragndrop.DragLayer;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
 import com.android.launcher3.states.StateAnimationConfig;
@@ -113,7 +114,9 @@
         setter.setFloat(mRecentsView, TASK_SECONDARY_TRANSLATION, 0f,
                 config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
 
-        if (mRecentsView.isSplitSelectionActive()) {
+        boolean exitingOverview = !FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
+                || !toState.overviewUi;
+        if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
             // TODO (b/238651489): Refactor state management to avoid need for double check
             FloatingTaskView floatingTask = mRecentsView.getFirstFloatingTaskView();
             if (floatingTask != null) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index 0b70b01..512d5f4 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -615,9 +615,10 @@
         mSplitSelectStateController.findLastActiveTaskAndRunCallback(
                 splitSelectSource.itemInfo.getComponentKey(),
                 foundTask -> {
-                    splitSelectSource.alreadyRunningTaskId = foundTask == null
-                            ? INVALID_TASK_ID
-                            : foundTask.key.id;
+                    boolean taskWasFound = foundTask != null;
+                    splitSelectSource.alreadyRunningTaskId = taskWasFound
+                            ? foundTask.key.id
+                            : INVALID_TASK_ID;
                     if (ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
                         startSplitToHome(splitSelectSource);
                     } else {
@@ -1295,7 +1296,7 @@
                 groupTask.task1.key.id,
                 groupTask.task2.key.id,
                 SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT,
-                /* callback= */ success -> {},
+                /* callback= */ success -> mSplitSelectStateController.resetState(),
                 /* freezeTaskList= */ true,
                 groupTask.mSplitBounds == null
                         ? DEFAULT_SPLIT_RATIO
diff --git a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
index 27fb476..84246e9 100644
--- a/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
+++ b/quickstep/src/com/android/quickstep/RemoteTargetGluer.java
@@ -19,6 +19,7 @@
 import android.app.WindowConfiguration;
 import android.content.Context;
 import android.graphics.Rect;
+import android.util.Log;
 import android.view.RemoteAnimationTarget;
 
 import androidx.annotation.Nullable;
@@ -37,6 +38,8 @@
  * {@link TaskViewSimulator}
  */
 public class RemoteTargetGluer {
+    private static final String TAG = "RemoteTargetGluer";
+
     private static final int DEFAULT_NUM_HANDLES = 2;
 
     private RemoteTargetHandle[] mRemoteTargetHandles;
@@ -118,7 +121,9 @@
         long appCount = Arrays.stream(targets.apps)
                 .filter(app -> app.mode == targets.targetMode)
                 .count();
+        Log.d(TAG, "appCount: " + appCount + " handleLength: " + mRemoteTargetHandles.length);
         if (appCount < mRemoteTargetHandles.length) {
+            Log.d(TAG, "resizing handles");
             RemoteTargetHandle[] newHandles = new RemoteTargetHandle[(int) appCount];
             System.arraycopy(mRemoteTargetHandles, 0/*src*/, newHandles, 0/*dst*/, (int) appCount);
             mRemoteTargetHandles = newHandles;
@@ -128,6 +133,8 @@
                 .anyMatch(remoteAnimationTarget ->
                         remoteAnimationTarget.windowConfiguration.getWindowingMode()
                                 == WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW);
+        Log.d(TAG, "containsSplitTargets? " + containsSplitTargets + " handleLength: " +
+                mRemoteTargetHandles.length + " appsLength: " + targets.apps.length);
 
         if (mRemoteTargetHandles.length == 1) {
             // Single fullscreen app
diff --git a/quickstep/src/com/android/quickstep/SplitSelectionListener.kt b/quickstep/src/com/android/quickstep/SplitSelectionListener.kt
new file mode 100644
index 0000000..5025c1c
--- /dev/null
+++ b/quickstep/src/com/android/quickstep/SplitSelectionListener.kt
@@ -0,0 +1,17 @@
+package com.android.quickstep
+
+interface SplitSelectionListener {
+    /** Called when the first app has been selected with the intention to launch split screen */
+    fun onSplitSelectionActive()
+
+    /** Called when the second app has been selected with the intention to launch split screen */
+    fun onSplitSelectionConfirmed()
+
+    /**
+     * Called when the user no longer is in the process of selecting apps for split screen.
+     * [launchedSplit] will be true if selected apps have launched successfully (either in
+     * split screen or fullscreen), false if the user canceled/exited the selection process
+     */
+    fun onSplitSelectionExit(launchedSplit: Boolean) {
+    }
+}
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 550bfb5..a9a57c6 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -35,6 +35,7 @@
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.statemanager.StateManager.StateListener;
 import com.android.launcher3.util.SplitConfigurationOptions;
@@ -251,7 +252,11 @@
             setOverviewSelectEnabled(false);
         }
         if (finalState != OVERVIEW_SPLIT_SELECT) {
-            resetFromSplitSelectionState();
+            if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+                mSplitSelectStateController.resetState();
+            } else {
+                resetFromSplitSelectionState();
+            }
         }
 
         if (isOverlayEnabled) {
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 2123253..e063b44 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -73,16 +73,18 @@
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
 import com.android.quickstep.RecentsModel;
+import com.android.quickstep.SplitSelectionListener;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskAnimationManager;
 import com.android.quickstep.TaskViewUtils;
 import com.android.quickstep.views.FloatingTaskView;
 import com.android.quickstep.views.GroupedTaskView;
-import com.android.quickstep.views.TaskView;
 import com.android.systemui.shared.recents.model.Task;
 import com.android.systemui.shared.system.RemoteAnimationRunnerCompat;
 
 import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.function.Consumer;
 
 /**
@@ -138,6 +140,8 @@
 
     private FloatingTaskView mFirstFloatingTaskView;
 
+    private final List<SplitSelectionListener> mSplitSelectionListeners = new ArrayList<>();
+
     public SplitSelectStateController(Context context, Handler handler, StateManager stateManager,
             DepthController depthController, StatsLogManager statsLogManager,
             SystemUiProxy systemUiProxy, RecentsModel recentsModel) {
@@ -248,6 +252,27 @@
     }
 
     /**
+     * Listener will only get callbacks going forward from the point of registration. No
+     * methods will be fired upon registering.
+     */
+    public void registerSplitListener(@NonNull SplitSelectionListener listener) {
+        if (mSplitSelectionListeners.contains(listener)) {
+            return;
+        }
+        mSplitSelectionListeners.add(listener);
+    }
+
+    public void unregisterSplitListener(@NonNull SplitSelectionListener listener) {
+        mSplitSelectionListeners.remove(listener);
+    }
+
+    private void dispatchOnSplitSelectionExit() {
+        for (SplitSelectionListener listener : mSplitSelectionListeners) {
+            listener.onSplitSelectionExit(false);
+        }
+    }
+
+    /**
      * To be called when the actual tasks ({@link #mInitialTaskId}, {@link #mSecondTaskId}) are
      * to be launched. Call after launcher side animations are complete.
      */
@@ -790,12 +815,16 @@
     }
 
     /**
-     * To be called if split select was cancelled
+     * To be called whenever we exit split selection state. If
+     * {@link FeatureFlags#ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE} is set, this should be the
+     * central way split is getting reset, which should then go through the callbacks to reset
+     * other state.
      */
     public void resetState() {
         if (FeatureFlags.ENABLE_SPLIT_LAUNCH_DATA_REFACTOR.get()) {
             mSplitSelectDataHolder.resetState();
         }
+        dispatchOnSplitSelectionExit();
         mInitialTaskId = INVALID_TASK_ID;
         mInitialTaskIntent = null;
         mSecondTaskId = INVALID_TASK_ID;
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 12d0f26..9e9b22f 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -37,6 +37,7 @@
 
 import com.android.launcher3.AbstractFloatingView;
 import com.android.launcher3.LauncherState;
+import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.statehandlers.DepthController;
 import com.android.launcher3.statehandlers.DesktopVisibilityController;
@@ -223,7 +224,11 @@
 
     @Override
     protected boolean canLaunchFullscreenTask() {
-        return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+        if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+            return !mSplitSelectStateController.isSplitSelectActive();
+        } else {
+            return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+        }
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 94085ae..f0daf8d 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -173,6 +173,7 @@
 import com.android.quickstep.RemoteTargetGluer;
 import com.android.quickstep.RemoteTargetGluer.RemoteTargetHandle;
 import com.android.quickstep.RotationTouchHelper;
+import com.android.quickstep.SplitSelectionListener;
 import com.android.quickstep.SystemUiProxy;
 import com.android.quickstep.TaskOverlayFactory;
 import com.android.quickstep.TaskThumbnailCache;
@@ -662,7 +663,8 @@
     /**
      * Placeholder view indicating where the first split screen selected app will be placed
      */
-    private SplitSelectStateController mSplitSelectStateController;
+    protected SplitSelectStateController mSplitSelectStateController;
+
     /**
      * The first task that split screen selection was initiated with. When split select state is
      * initialized, we create a
@@ -685,6 +687,19 @@
     @Nullable
     private SplitSelectSource mSplitSelectSource;
 
+    private final SplitSelectionListener mSplitSelectionListener = new SplitSelectionListener() {
+        @Override
+        public void onSplitSelectionConfirmed() { }
+
+        @Override
+        public void onSplitSelectionActive() { }
+
+        @Override
+        public void onSplitSelectionExit(boolean launchedSplit) {
+            resetFromSplitSelectionState();
+        }
+    };
+
     /**
      * Keeps track of the index of the TaskView that split screen was initialized with so we know
      * where to insert it back into list of taskViews in case user backs out of entering split
@@ -1065,6 +1080,9 @@
                 mIPipAnimationListener);
         mOrientationState.initListeners();
         mTaskOverlayFactory.initListeners();
+        if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+            mSplitSelectStateController.registerSplitListener(mSplitSelectionListener);
+        }
     }
 
     @Override
@@ -1083,6 +1101,9 @@
         mIPipAnimationListener.setActivityAndRecentsView(null, null);
         mOrientationState.destroyListeners();
         mTaskOverlayFactory.removeListeners();
+        if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+            mSplitSelectStateController.unregisterSplitListener(mSplitSelectionListener);
+        }
     }
 
     @Override
@@ -1660,8 +1681,8 @@
         // If we are entering Overview as a result of initiating a split from somewhere else
         // (e.g. split from Home), we need to make sure the staged app is not drawn as a thumbnail.
         int stagedTaskIdToBeRemovedFromGrid;
-        if (mSplitSelectSource != null) {
-            stagedTaskIdToBeRemovedFromGrid = mSplitSelectSource.alreadyRunningTaskId;
+        if (isSplitSelectionActive()) {
+            stagedTaskIdToBeRemovedFromGrid = mSplitSelectStateController.getInitialTaskId();
             updateCurrentTaskActionsVisibility();
         } else {
             stagedTaskIdToBeRemovedFromGrid = INVALID_TASK_ID;
@@ -2375,7 +2396,9 @@
             remoteTargetHandle.getTransformParams().setTargetSet(null);
             remoteTargetHandle.getTaskViewSimulator().setDrawsBelowRecents(false);
         });
-        resetFromSplitSelectionState();
+        if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+            resetFromSplitSelectionState();
+        }
 
         // These are relatively expensive and don't need to be done this frame (RecentsView isn't
         // visible anyway), so defer by a frame to get off the critical path, e.g. app to home.
@@ -3259,7 +3282,11 @@
                         InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
             } else {
                 // If transition to split select was interrupted, clean up to prevent glitches
-                resetFromSplitSelectionState();
+                if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+                    mSplitSelectStateController.resetState();
+                } else {
+                    resetFromSplitSelectionState();
+                }
                 InteractionJankMonitorWrapper.cancel(
                         InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
             }
@@ -3292,8 +3319,13 @@
                 true /* isStagedTask */);
 
         pendingAnimation.addEndListener(animationSuccess ->
-                mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess ->
-                        resetFromSplitSelectionState()));
+                mSplitSelectStateController.launchInitialAppFullscreen(launchSuccess -> {
+                    if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+                        mSplitSelectStateController.resetState();
+                    } else {
+                        resetFromSplitSelectionState();
+                    }
+                }));
 
         pendingAnimation.buildAnim().start();
     }
@@ -4745,7 +4777,13 @@
 
         pendingAnimation.addEndListener(aBoolean -> {
             mSplitSelectStateController.launchSplitTasks(
-                    aBoolean1 -> RecentsView.this.resetFromSplitSelectionState());
+                    aBoolean1 -> {
+                        if (FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+                            mSplitSelectStateController.resetState();
+                        } else {
+                            resetFromSplitSelectionState();
+                        }
+                    });
             InteractionJankMonitorWrapper.end(InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
         });
 
@@ -4767,7 +4805,8 @@
 
     @SuppressLint("WrongCall")
     protected void resetFromSplitSelectionState() {
-        if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
+        if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1 ||
+                FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
             safeRemoveDragLayerView(mSplitSelectStateController.getFirstFloatingTaskView());
             safeRemoveDragLayerView(mSecondFloatingTaskView);
             safeRemoveDragLayerView(mSplitInstructionsView);
@@ -4786,7 +4825,11 @@
         setTaskViewsPrimarySplitTranslation(0);
         setTaskViewsSecondarySplitTranslation(0);
 
-        mSplitSelectStateController.resetState();
+        if (!FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()) {
+            // When flag is on, this method gets called from resetState() call below, let's avoid
+            // infinite recursion today
+            mSplitSelectStateController.resetState();
+        }
         if (mSplitHiddenTaskViewIndex == -1) {
             return;
         }
diff --git a/res/layout/widget_cell.xml b/res/layout/widget_cell.xml
index 9868e20..55dd1de 100644
--- a/res/layout/widget_cell.xml
+++ b/res/layout/widget_cell.xml
@@ -19,7 +19,6 @@
     android:layout_height="wrap_content"
     android:paddingHorizontal="@dimen/widget_cell_horizontal_padding"
     android:paddingVertical="@dimen/widget_cell_vertical_padding"
-    android:layout_marginHorizontal="@dimen/widget_cell_horizontal_padding"
     android:layout_weight="1"
     android:orientation="vertical"
     android:focusable="true"
diff --git a/res/layout/widgets_table_container.xml b/res/layout/widgets_table_container.xml
index 4a32672..c41d0bb 100644
--- a/res/layout/widgets_table_container.xml
+++ b/res/layout/widgets_table_container.xml
@@ -16,6 +16,7 @@
 <com.android.launcher3.widget.picker.WidgetsListTableView
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/widgets_table"
+    android:paddingHorizontal="@dimen/widget_list_horizontal_margin"
     android:background="@drawable/bg_widgets_content"
     android:layout_width="match_parent"
     android:layout_height="wrap_content" />