Fix two bugs with rotation in split select state

This CL fixes two bugs that were triggered by rotating in split select state:
1) Rotating in split select state will no longer cause a jittery animation to play
2) Initiating split from home, then rotating will no longer create extra split placeholders on screen

The bugs were present because handleSplitSelectionState() animated every state transition into SplitSelect, including SplitSelect > SplitSelect (which happens when rotating). This caused a jittery animation to play, and in certain cases, caused additional copies of FloatingTaskView and SplitInstructionsView to be created.

Fixed by auto-skipping animations for SplitSelect > SplitSelect, and by safely removing views when entering SplitSelect (to prevent duplicates).

Fixes: 242965515
Fixes: 243088958
Test: Verified visually on-device.
Change-Id: Iab813b1fe599bfdc550fe9a1d354b28cedb4b659
diff --git a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
index 420c64a..0723f8a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/RecentsViewStateController.java
@@ -27,6 +27,7 @@
 import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION;
 import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL;
 
+import android.animation.AnimatorSet;
 import android.annotation.TargetApi;
 import android.os.Build;
 import android.util.FloatProperty;
@@ -108,6 +109,13 @@
      */
     private void handleSplitSelectionState(@NonNull LauncherState toState,
             @NonNull PendingAnimation builder, boolean animate) {
+        if (toState != OVERVIEW_SPLIT_SELECT) {
+            // Not going to split, nothing to do but ensure taskviews are at correct offset
+            mRecentsView.resetSplitPrimaryScrollOffset();
+            return;
+        }
+
+        // Create transition animations to split select
         PagedOrientationHandler orientationHandler =
                 ((RecentsView) mLauncher.getOverviewPanel()).getPagedOrientationHandler();
         Pair<FloatProperty, FloatProperty> taskViewsFloat =
@@ -115,22 +123,20 @@
                         TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
                         mLauncher.getDeviceProfile());
 
-        if (toState == OVERVIEW_SPLIT_SELECT) {
-            mRecentsView.createSplitSelectInitAnimation(builder,
-                    toState.getTransitionDuration(mLauncher, true /* isToState */));
-            // Add properties to shift remaining taskViews to get out of placeholder view
-            builder.setFloat(mRecentsView, taskViewsFloat.first,
-                    toState.getSplitSelectTranslation(mLauncher), LINEAR);
-            builder.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
+        mRecentsView.createSplitSelectInitAnimation(builder,
+                toState.getTransitionDuration(mLauncher, true /* isToState */));
+        // Add properties to shift remaining taskViews to get out of placeholder view
+        builder.setFloat(mRecentsView, taskViewsFloat.first,
+                toState.getSplitSelectTranslation(mLauncher), LINEAR);
+        builder.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
 
-            if (!animate) {
-                builder.buildAnim().start();
-            }
-
-            mRecentsView.applySplitPrimaryScrollOffset();
-        } else {
-            mRecentsView.resetSplitPrimaryScrollOffset();
+        if (!animate) {
+            AnimatorSet as = builder.buildAnim();
+            as.start();
+            as.end();
         }
+
+        mRecentsView.applySplitPrimaryScrollOffset();
     }
 
     private void setAlphas(PropertySetter propertySetter, StateAnimationConfig config,
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 8da08b4..3687f36 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -2858,6 +2858,7 @@
                 mSplitSelectStateController.getActiveSplitStagePosition(), mTempRect);
 
         RectF startingTaskRect = new RectF();
+        safeRemoveDragLayerView(mFirstFloatingTaskView);
         if (mSplitHiddenTaskView != null) {
             // Split staging is initiated
             mSplitHiddenTaskView.setThumbnailVisibility(INVISIBLE);
@@ -2881,6 +2882,7 @@
         }
 
         // SplitInstructionsView: animate in
+        safeRemoveDragLayerView(mSplitInstructionsView);
         mSplitInstructionsView = SplitInstructionsView.getSplitInstructionsView(mActivity);
         mSplitInstructionsView.setAlpha(0);
         anim.setViewAlpha(mSplitInstructionsView, 1, clampToProgress(LINEAR,
@@ -4230,6 +4232,7 @@
                 new RectF(firstTaskStartingBounds), firstTaskEndingBounds,
                 false /* fadeWithThumbnail */, true /* isStagedTask */);
 
+        safeRemoveDragLayerView(mSecondFloatingTaskView);
         mSecondFloatingTaskView = FloatingTaskView.getFloatingTaskView(mActivity,
                 thumbnailView, thumbnailView.getThumbnail(),
                 iconView.getDrawable(), secondTaskStartingBounds);
@@ -4262,17 +4265,13 @@
     @SuppressLint("WrongCall")
     protected void resetFromSplitSelectionState() {
         if (mSplitSelectSource != null || mSplitHiddenTaskViewIndex != -1) {
-            if (mSplitInstructionsView != null) {
-                mActivity.getDragLayer().removeView(mSplitInstructionsView);
-                mSplitInstructionsView = null;
-            }
-            if (mFirstFloatingTaskView != null) {
-                mActivity.getDragLayer().removeView(mFirstFloatingTaskView);
-                mFirstFloatingTaskView = null;
-            }
-            if (mSecondFloatingTaskView != null) {
-                mActivity.getDragLayer().removeView(mSecondFloatingTaskView);
-                mSecondFloatingTaskView = null;
+            safeRemoveDragLayerView(mFirstFloatingTaskView);
+            safeRemoveDragLayerView(mSecondFloatingTaskView);
+            safeRemoveDragLayerView(mSplitInstructionsView);
+            mFirstFloatingTaskView = null;
+            mSecondFloatingTaskView = null;
+            mSplitInstructionsView = null;
+            if (mSecondSplitHiddenView != null) {
                 mSecondSplitHiddenView.setVisibility(VISIBLE);
                 mSecondSplitHiddenView = null;
             }
@@ -4300,6 +4299,12 @@
         }
     }
 
+    private void safeRemoveDragLayerView(@Nullable View viewToRemove) {
+        if (viewToRemove != null) {
+            mActivity.getDragLayer().removeView(viewToRemove);
+        }
+    }
+
     /**
      * Returns how much additional translation there should be for each of the child TaskViews.
      * Note that the translation can be its primary or secondary dimension.