Add split support for 3P launcher

* Copied logic mostly from
Base/RecentsViewStateController
* There's one KI crash specific to 3P
(b/209694087)
* Swipe to home animation is TODO, but
then again it also seems incorrect for
full-screen app. 3P has many cosmetic issues
throughout.

Bug: 195607777
Test: Tested w/ Nova launcher with grid
and non-grid, able to invoke split screen with
same animations as 1P launcher

Change-Id: I35a1bc92a51caccac4214289e614000cd47bb503
diff --git a/quickstep/res/layout/overview_panel.xml b/quickstep/res/layout/overview_panel.xml
index f303f31..01d675f 100644
--- a/quickstep/res/layout/overview_panel.xml
+++ b/quickstep/res/layout/overview_panel.xml
@@ -25,13 +25,6 @@
         android:clipToPadding="false"
         android:visibility="invisible" />
 
-    <com.android.quickstep.views.SplitPlaceholderView
-        android:id="@+id/split_placeholder"
-        android:layout_width="match_parent"
-        android:layout_height="@dimen/split_placeholder_size"
-        android:background="@android:color/darker_gray"
-        android:visibility="gone" />
-
     <include
         android:id="@+id/overview_actions_view"
         layout="@layout/overview_actions_container" />
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
index 50b69dc..ff175f1 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsStateController.java
@@ -24,14 +24,22 @@
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
 import static com.android.launcher3.states.StateAnimationConfig.ANIM_SCRIM_FADE;
 import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
+import static com.android.quickstep.fallback.RecentsState.OVERVIEW_SPLIT_SELECT;
 import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
 import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
 import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
 import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
 import static com.android.quickstep.views.RecentsView.TASK_MODALNESS;
+import static com.android.quickstep.views.RecentsView.TASK_PRIMARY_SPLIT_TRANSLATION;
+import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_SPLIT_TRANSLATION;
 import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
 import static com.android.quickstep.views.TaskView.FLAG_UPDATE_ALL;
 
+import android.util.FloatProperty;
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.anim.PropertySetter;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
@@ -100,5 +108,31 @@
 
         setter.setViewBackgroundColor(mActivity.getScrimView(), state.getScrimColor(mActivity),
                 config.getInterpolator(ANIM_SCRIM_FADE, LINEAR));
+
+        RecentsState currentState = mActivity.getStateManager().getState();
+        if (isSplitSelectionState(state) && !isSplitSelectionState(currentState)) {
+            setter.add(mRecentsView.createSplitSelectInitAnimation().buildAnim());
+        }
+
+        Pair<FloatProperty, FloatProperty> taskViewsFloat =
+                mRecentsView.getPagedOrientationHandler().getSplitSelectTaskOffset(
+                        TASK_PRIMARY_SPLIT_TRANSLATION, TASK_SECONDARY_SPLIT_TRANSLATION,
+                        mActivity.getDeviceProfile());
+        setter.setFloat(mRecentsView, taskViewsFloat.second, 0, LINEAR);
+        if (isSplitSelectionState(state)) {
+            mRecentsView.applySplitPrimaryScrollOffset();
+            setter.setFloat(mRecentsView, taskViewsFloat.first,
+                    mRecentsView.getSplitSelectTranslation(), LINEAR);
+        } else {
+            mRecentsView.resetSplitPrimaryScrollOffset();
+            setter.setFloat(mRecentsView, taskViewsFloat.first, 0, LINEAR);
+        }
+    }
+
+    /**
+     * @return true if {@param toState} is {@link RecentsState#OVERVIEW_SPLIT_SELECT}
+     */
+    private boolean isSplitSelectionState(@NonNull RecentsState toState) {
+        return toState == OVERVIEW_SPLIT_SELECT;
     }
 }
diff --git a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
index 169b208..6d22b17 100644
--- a/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
+++ b/quickstep/src/com/android/quickstep/fallback/FallbackRecentsView.java
@@ -19,12 +19,12 @@
 import static com.android.quickstep.fallback.RecentsState.DEFAULT;
 import static com.android.quickstep.fallback.RecentsState.HOME;
 import static com.android.quickstep.fallback.RecentsState.MODAL_TASK;
+import static com.android.quickstep.fallback.RecentsState.OVERVIEW_SPLIT_SELECT;
 
 import android.animation.AnimatorSet;
 import android.annotation.TargetApi;
 import android.app.ActivityManager.RunningTaskInfo;
 import android.content.Context;
-import android.content.res.Configuration;
 import android.os.Build;
 import android.util.AttributeSet;
 import android.view.MotionEvent;
@@ -35,6 +35,7 @@
 import com.android.launcher3.anim.AnimatorPlaybackController;
 import com.android.launcher3.anim.PendingAnimation;
 import com.android.launcher3.statemanager.StateManager.StateListener;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.quickstep.FallbackActivityInterface;
 import com.android.quickstep.GestureState;
 import com.android.quickstep.RecentsActivity;
@@ -207,6 +208,13 @@
     }
 
     @Override
+    public void initiateSplitSelect(TaskView taskView,
+            @SplitConfigurationOptions.StagePosition int stagePosition) {
+        super.initiateSplitSelect(taskView, stagePosition);
+        mActivity.getStateManager().goToState(OVERVIEW_SPLIT_SELECT);
+    }
+
+    @Override
     public void onStateTransitionStart(RecentsState toState) {
         setOverviewStateEnabled(true);
         setOverviewGridEnabled(toState.displayOverviewTasksAsGrid(mActivity.getDeviceProfile()));
@@ -245,12 +253,4 @@
         // Do not let touch escape to siblings below this view.
         return result || mActivity.getStateManager().getState().overviewUi();
     }
-
-    @Override
-    protected void onConfigurationChanged(Configuration newConfig) {
-        super.onConfigurationChanged(newConfig);
-
-        // Reset modal state if full configuration changes
-        setModalStateEnabled(false);
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/fallback/RecentsState.java b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
index 917b58a..15feb18 100644
--- a/quickstep/src/com/android/quickstep/fallback/RecentsState.java
+++ b/quickstep/src/com/android/quickstep/fallback/RecentsState.java
@@ -51,6 +51,8 @@
             FLAG_DISABLE_RESTORE | FLAG_NON_INTERACTIVE | FLAG_FULL_SCREEN | FLAG_OVERVIEW_UI);
     public static final RecentsState HOME = new RecentsState(3, 0);
     public static final RecentsState BG_LAUNCHER = new LauncherState(4, 0);
+    public static final RecentsState OVERVIEW_SPLIT_SELECT = new RecentsState(5,
+            FLAG_SHOW_AS_GRID | FLAG_SCRIM | FLAG_OVERVIEW_UI);
 
     public final int ordinal;
     private final int mFlags;
diff --git a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
index 0cea45e..18ab3bb 100644
--- a/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/FloatingTaskView.java
@@ -17,8 +17,9 @@
 
 import androidx.annotation.Nullable;
 
+import com.android.launcher3.BaseActivity;
+import com.android.launcher3.BaseDraggingActivity;
 import com.android.launcher3.InsettableFrameLayout;
-import com.android.launcher3.Launcher;
 import com.android.launcher3.LauncherAnimUtils;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
@@ -43,7 +44,7 @@
 
     private SplitPlaceholderView mSplitPlaceholderView;
     private RectF mStartingPosition;
-    private final Launcher mLauncher;
+    private final BaseDraggingActivity mActivity;
     private final boolean mIsRtl;
     private final Rect mOutline = new Rect();
     private PagedOrientationHandler mOrientationHandler;
@@ -59,7 +60,7 @@
 
     public FloatingTaskView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
         super(context, attrs, defStyleAttr);
-        mLauncher = Launcher.getLauncher(context);
+        mActivity = BaseActivity.fromContext(context);
         mIsRtl = Utilities.isRtl(getResources());
     }
 
@@ -114,7 +115,7 @@
     public void updateInitialPositionForView(TaskView originalView) {
         View thumbnail = originalView.getThumbnail();
         Rect viewBounds = new Rect(0, 0, thumbnail.getWidth(), thumbnail.getHeight());
-        Utilities.getBoundsForViewInDragLayer(mLauncher.getDragLayer(), thumbnail, viewBounds,
+        Utilities.getBoundsForViewInDragLayer(mActivity.getDragLayer(), thumbnail, viewBounds,
                 true /* ignoreTransform */, null /* recycle */,
                 mStartingPosition);
         mStartingPosition.offset(originalView.getTranslationX(), originalView.getTranslationY());
@@ -161,7 +162,7 @@
         // Position the floating view exactly on top of the original
         lp.topMargin = Math.round(pos.top);
         if (mIsRtl) {
-            lp.setMarginStart(mLauncher.getDeviceProfile().widthPx - Math.round(pos.right));
+            lp.setMarginStart(mActivity.getDeviceProfile().widthPx - Math.round(pos.right));
         } else {
             lp.setMarginStart(Math.round(pos.left));
         }
@@ -174,7 +175,7 @@
 
     public void addAnimation(PendingAnimation animation, RectF startingBounds, Rect endBounds,
             View viewToCover, boolean fadeWithThumbnail) {
-        final BaseDragLayer dragLayer = mLauncher.getDragLayer();
+        final BaseDragLayer dragLayer = mActivity.getDragLayer();
         int[] dragLayerBounds = new int[2];
         dragLayer.getLocationOnScreen(dragLayerBounds);
         SplitOverlayProperties prop = new SplitOverlayProperties(endBounds,
diff --git a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
index 6b7d8a5..e0395ea 100644
--- a/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/LauncherRecentsView.java
@@ -168,15 +168,4 @@
         super.initiateSplitSelect(taskView, stagePosition);
         mActivity.getStateManager().goToState(LauncherState.OVERVIEW_SPLIT_SELECT);
     }
-
-    @Override
-    protected void onOrientationChanged() {
-        super.onOrientationChanged();
-        // If overview is in modal state when rotate, reset it to overview state without running
-        // animation.
-        setModalStateEnabled(false);
-        if (mActivity.isInState(OVERVIEW_SPLIT_SELECT)) {
-            onRotateInSplitSelectionState();
-        }
-    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index ed238d8..d855d5b 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -1640,7 +1640,13 @@
         setCurrentPage(mCurrentPage);
     }
 
-    protected void onOrientationChanged() {
+    private void onOrientationChanged() {
+        // If overview is in modal state when rotate, reset it to overview state without running
+        // animation.
+        setModalStateEnabled(false);
+        if (isSplitSelectionActive()) {
+            onRotateInSplitSelectionState();
+        }
     }
 
     // Update task size and padding that are dependent on DeviceProfile and insets.
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 8dee4e7..e33d650 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -677,7 +677,7 @@
      *         second app. {@code false} otherwise
      */
     private boolean confirmSecondSplitSelectApp() {
-        boolean isSelectingSecondSplitApp = mActivity.isInState(OVERVIEW_SPLIT_SELECT);
+        boolean isSelectingSecondSplitApp = getRecentsView().isSplitSelectionActive();
         if (isSelectingSecondSplitApp) {
             getRecentsView().confirmSplitSelect(this);
         }
diff --git a/src/com/android/launcher3/anim/PropertySetter.java b/src/com/android/launcher3/anim/PropertySetter.java
index 729523f..8d77b4b 100644
--- a/src/com/android/launcher3/anim/PropertySetter.java
+++ b/src/com/android/launcher3/anim/PropertySetter.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.anim;
 
+import android.animation.Animator;
 import android.animation.TimeInterpolator;
 import android.util.FloatProperty;
 import android.util.IntProperty;
@@ -64,4 +65,9 @@
             TimeInterpolator interpolator) {
         property.setValue(target, value);
     }
+
+    default void add(Animator animatorSet) {
+        animatorSet.setDuration(0);
+        animatorSet.start();
+    }
 }