Merge "Prevent double selection of second split app" into tm-dev
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index eda2c5a..48af802 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -268,4 +268,9 @@
         super.initiateSplitSelect(splitSelectSource);
         mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
     }
+
+    @Override
+    protected boolean canLaunchFullscreenTask() {
+        return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index ee69fc3..2502359 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -73,6 +73,7 @@
     private Intent mInitialTaskIntent;
     private int mInitialTaskId = INVALID_TASK_ID;
     private int mSecondTaskId = INVALID_TASK_ID;
+    private String mSecondTaskPackageName;
     private boolean mRecentsAnimationRunning;
     /** If not null, this is the TaskView we want to launch from */
     @Nullable
@@ -103,15 +104,15 @@
     }
 
     /**
-     * To be called after second task selected
+     * To be called when the actual tasks ({@link #mInitialTaskId}, {@link #mSecondTaskId}) are
+     * to be launched. Call after launcher side animations are complete.
      */
-    public void setSecondTask(Task task, Consumer<Boolean> callback) {
-        mSecondTaskId = task.key.id;
+    public void launchSplitTasks(Consumer<Boolean> callback) {
         final Intent fillInIntent;
         if (mInitialTaskIntent != null) {
             fillInIntent = new Intent();
             if (TextUtils.equals(mInitialTaskIntent.getComponent().getPackageName(),
-                    task.getTopComponent().getPackageName())) {
+                    mSecondTaskPackageName)) {
                 fillInIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
             }
         } else {
@@ -124,6 +125,18 @@
                 callback, false /* freezeTaskList */, DEFAULT_SPLIT_RATIO);
     }
 
+
+    /**
+     * To be called as soon as user selects the second task (even if animations aren't complete)
+     * @param task The second task that will be launched.
+     */
+    public void setSecondTask(Task task) {
+        mSecondTaskId = task.key.id;
+        if (mInitialTaskIntent != null) {
+            mSecondTaskPackageName = task.getTopComponent().getPackageName();
+        }
+    }
+
     /**
      * To be called when we want to launch split pairs from an existing GroupedTaskView.
      */
@@ -303,7 +316,18 @@
      *         chosen
      */
     public boolean isSplitSelectActive() {
-        return (mInitialTaskId != INVALID_TASK_ID || mInitialTaskIntent != null)
-                && mSecondTaskId == INVALID_TASK_ID;
+        return isInitialTaskIntentSet() && mSecondTaskId == INVALID_TASK_ID;
+    }
+
+    /**
+     * @return {@code true} if the first and second task have been chosen and split is waiting to
+     *          be launched
+     */
+    public boolean isBothSplitAppsConfirmed() {
+        return isInitialTaskIntentSet() && mSecondTaskId != INVALID_TASK_ID;
+    }
+
+    private boolean isInitialTaskIntentSet() {
+        return (mInitialTaskId != INVALID_TASK_ID || mInitialTaskIntent != null);
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 8d717d2..45aaf35 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -181,4 +181,9 @@
         super.initiateSplitSelect(splitSelectSource);
         mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
     }
+
+    @Override
+    protected boolean canLaunchFullscreenTask() {
+        return !mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index c6d26a1..ed00b8e 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -878,6 +878,14 @@
         return mSplitSelectStateController.isSplitSelectActive();
     }
 
+    /**
+     * See overridden implementations
+     * @return {@code true} if child TaskViews can be launched when user taps on them
+     */
+    protected boolean canLaunchFullscreenTask() {
+        return true;
+    }
+
     @Override
     protected void onAttachedToWindow() {
         super.onAttachedToWindow();
@@ -3991,15 +3999,25 @@
     /**
      * Confirms the selection of the next split task. The extra data is passed through because the
      * user may be selecting a subtask in a group.
+     *
+     * @return true if waiting for confirmation of second app or if split animations are running,
+     *          false otherwise
      */
-    public void confirmSplitSelect(TaskView containerTaskView, Task task, IconView iconView,
+    public boolean confirmSplitSelect(TaskView containerTaskView, Task task, IconView iconView,
             TaskThumbnailView thumbnailView) {
+        if (canLaunchFullscreenTask()) {
+            return false;
+        }
+        if (mSplitSelectStateController.isBothSplitAppsConfirmed()) {
+            return true;
+        }
         mSplitToast.cancel();
         if (!task.isDockable) {
             // Task not split screen supported
             mSplitUnsupportedToast.show();
-            return;
+            return true;
         }
+        mSplitSelectStateController.setSecondTask(task);
         RectF secondTaskStartingBounds = new RectF();
         Rect secondTaskEndingBounds = new Rect();
         // TODO(194414938) starting bounds seem slightly off, investigate
@@ -4027,8 +4045,8 @@
         mSecondFloatingTaskView.addAnimation(pendingAnimation, secondTaskStartingBounds,
                 secondTaskEndingBounds, true /* fadeWithThumbnail */, false /* isStagedTask */);
         pendingAnimation.addEndListener(aBoolean ->
-                mSplitSelectStateController.setSecondTask(
-                        task, aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()));
+                mSplitSelectStateController.launchSplitTasks(
+                        aBoolean1 -> RecentsView.this.resetFromSplitSelectionState()));
         if (containerTaskView.containsMultipleTasks()) {
             // If we are launching from a child task, then only hide the thumbnail itself
             mSecondSplitHiddenView = thumbnailView;
@@ -4037,6 +4055,7 @@
         }
         mSecondSplitHiddenView.setVisibility(INVISIBLE);
         pendingAnimation.buildAnim().start();
+        return true;
     }
 
     /** TODO(b/181707736) More gracefully handle exiting split selection state */
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index ce033e5..9c5c643 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -698,14 +698,10 @@
      *         second app. {@code false} otherwise
      */
     private boolean confirmSecondSplitSelectApp() {
-        boolean isSelectingSecondSplitApp = getRecentsView().isSplitSelectionActive();
-        if (isSelectingSecondSplitApp) {
-            int index = getChildTaskIndexAtPosition(mLastTouchDownPosition);
-            TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
-            getRecentsView().confirmSplitSelect(this, container.getTask(), container.getIconView(),
-                    container.getThumbnailView());
-        }
-        return isSelectingSecondSplitApp;
+        int index = getChildTaskIndexAtPosition(mLastTouchDownPosition);
+        TaskIdAttributeContainer container = mTaskIdAttributeContainer[index];
+        return getRecentsView().confirmSplitSelect(this, container.getTask(),
+                container.getIconView(), container.getThumbnailView());
     }
 
     /**
@@ -855,7 +851,7 @@
     }
 
     private boolean showTaskMenu(IconView iconView) {
-        if (getRecentsView().mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
+        if (!getRecentsView().canLaunchFullscreenTask()) {
             // Don't show menu when selecting second split screen app
             return true;
         }