Merge "Fix taskbar folder leave-behind not being drawn" into sc-v2-dev
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
index 5777fb9..68159fa 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DepthController.java
@@ -26,6 +26,7 @@
 import android.os.IBinder;
 import android.os.SystemProperties;
 import android.util.FloatProperty;
+import android.view.AttachedSurfaceControl;
 import android.view.CrossWindowBlurListeners;
 import android.view.SurfaceControl;
 import android.view.View;
@@ -316,7 +317,12 @@
                 transaction.setEarlyWakeupEnd();
                 mInEarlyWakeUp = false;
             }
-            transaction.apply();
+
+            AttachedSurfaceControl rootSurfaceControl =
+                    mLauncher.getRootView().getRootSurfaceControl();
+            if (rootSurfaceControl != null) {
+                rootSurfaceControl.applyTransactionOnDraw(transaction);
+            }
         }
         return true;
     }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
index 1882a0c..cbb4081 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/SplitScreenSelectState.java
@@ -44,7 +44,7 @@
     public float getSplitSelectTranslation(Launcher launcher) {
         RecentsView recentsView = launcher.getOverviewPanel();
         int splitPosition = recentsView.getSplitPlaceholder()
-                .getActiveSplitPositionOption().mStagePosition;
+                .getActiveSplitPositionOption().stagePosition;
         if (!recentsView.shouldShiftThumbnailsForSplitSelect(splitPosition)) {
             return 0f;
         }
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index 46d5857..6e90a3a 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1194,9 +1194,6 @@
     @UiThread
     private void animateToProgressInternal(float start, float end, long duration,
             Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
-        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
-            Log.d(TestProtocol.L3_SWIPE_TO_HOME, "7");
-        }
         maybeUpdateRecentsAttachedState();
 
         // If we are transitioning to launcher, then listen for the activity to be restarted while
@@ -1219,6 +1216,9 @@
             }
         }
 
+        if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+            Log.d(TestProtocol.L3_SWIPE_TO_HOME, "7, end target=" + mGestureState.getEndTarget());
+        }
         if (mGestureState.getEndTarget() == HOME) {
             getOrientationHandler().adjustFloatingIconStartVelocity(velocityPxPerMs);
             final RemoteAnimationTargetCompat runningTaskTarget = mRecentsAnimationTargets != null
@@ -1233,6 +1233,9 @@
                     && runningTaskTarget.allowEnterPip
                     && runningTaskTarget.taskInfo.pictureInPictureParams != null
                     && runningTaskTarget.taskInfo.pictureInPictureParams.isAutoEnterEnabled();
+            if (Utilities.IS_RUNNING_IN_TEST_HARNESS) {
+                Log.d(TestProtocol.L3_SWIPE_TO_HOME, "8, class=" + getClass().getSimpleName());
+            }
             HomeAnimationFactory homeAnimFactory =
                     createHomeAnimationFactory(cookies, duration, isTranslucent, appCanEnterPip,
                             runningTaskTarget);
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index e2ef3bc..6298bb8 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -53,7 +53,6 @@
 import com.android.launcher3.statemanager.BaseState;
 import com.android.launcher3.statemanager.StatefulActivity;
 import com.android.launcher3.touch.PagedOrientationHandler;
-import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.WindowBounds;
 import com.android.launcher3.views.ScrimView;
 import com.android.quickstep.SysUINavigationMode.Mode;
@@ -203,33 +202,6 @@
     }
 
     /**
-     * Sets the task size in {@param outRect} taking split screened windows into account.
-     * We assume combined height of both tasks will be same as one normal task, then we'll modify
-     * the task height/width based on the ratio of task screen space bounds from
-     * {@param splitInfo}
-     *
-     * @param desiredStageBounds whether task size for top/left or bottom/right needs to be computed
-     */
-    public final void calculateStagedSplitTaskSize(Context context, DeviceProfile dp, Rect outRect,
-            SplitConfigurationOptions.StagedSplitBounds splitInfo,
-            @SplitConfigurationOptions.StagePosition int desiredStageBounds) {
-        calculateTaskSize(context, dp, outRect);
-
-        // TODO(b/181705607) Change for landscape vs portrait
-        float totalHeight = splitInfo.mLeftTopBounds.height()
-                + splitInfo.mRightBottomBounds.height()
-                + splitInfo.mDividerBounds.height() / 2f;
-        float topTaskPercent = splitInfo.mLeftTopBounds.height() / totalHeight;
-        if (desiredStageBounds == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
-            float diff = outRect.height() * (1f - topTaskPercent);
-            outRect.bottom -= diff;
-        } else {
-            float diff = outRect.height() * topTaskPercent;
-            outRect.top += diff;
-        }
-    }
-
-    /**
      * Calculates the taskView size for the provided device configuration.
      */
     public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
diff --git a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
index 35a851a..81e6917 100644
--- a/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
+++ b/quickstep/src/com/android/quickstep/OrientationTouchTransformer.java
@@ -462,7 +462,7 @@
                             + "mRotation: " + mRotation
                             + " this: " + this);
                 }
-                event.transform(mTmpMatrix);
+                event.applyTransform(mTmpMatrix);
                 return true;
             }
             mTmpPoint[0] = event.getX();
@@ -478,7 +478,7 @@
             }
 
             if (contains(mTmpPoint[0], mTmpPoint[1])) {
-                event.transform(mTmpMatrix);
+                event.applyTransform(mTmpMatrix);
                 return true;
             }
             return false;
diff --git a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
index a078bf3..559125e 100644
--- a/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
+++ b/quickstep/src/com/android/quickstep/TaskShortcutFactory.java
@@ -100,7 +100,7 @@
         private SplitPositionOption mSplitPositionOption;
         public SplitSelectSystemShortcut(BaseDraggingActivity target, TaskView taskView,
                 SplitPositionOption option) {
-            super(option.mIconResId, option.mTextResId, target, taskView.getItemInfo());
+            super(option.iconResId, option.textResId, target, taskView.getItemInfo());
             mTaskView = taskView;
             mSplitPositionOption = option;
             setEnabled(taskView.getRecentsView().getTaskViewCount() > 1);
diff --git a/quickstep/src/com/android/quickstep/TouchInteractionService.java b/quickstep/src/com/android/quickstep/TouchInteractionService.java
index 20eff34..2e42392 100644
--- a/quickstep/src/com/android/quickstep/TouchInteractionService.java
+++ b/quickstep/src/com/android/quickstep/TouchInteractionService.java
@@ -146,7 +146,7 @@
     private static final int SYSTEM_ACTION_ID_ALL_APPS = 14;
 
     public static final boolean ENABLE_PER_WINDOW_INPUT_ROTATION =
-            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", false);
+            SystemProperties.getBoolean("persist.debug.per_window_input_rotation", true);
 
     private int mBackGestureNotificationCounter = -1;
     @Nullable
diff --git a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
index 16c925a..6dff857 100644
--- a/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
+++ b/quickstep/src/com/android/quickstep/util/SplitSelectStateController.java
@@ -83,7 +83,7 @@
         mSecondTaskView = taskView;
         // Assume initial task is for top/left part of screen
 
-        final int[] taskIds = mInitialPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT
+        final int[] taskIds = mInitialPosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT
                 ? new int[]{mInitialTaskView.getTask().key.id, taskView.getTask().key.id}
                 : new int[]{taskView.getTask().key.id, mInitialTaskView.getTask().key.id};
         if (TaskAnimationManager.ENABLE_SHELL_TRANSITIONS) {
@@ -113,7 +113,7 @@
             DeviceProfile deviceProfile) {
         InsettableFrameLayout.LayoutParams params =
                 new InsettableFrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT);
-        boolean topLeftPosition = mInitialPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT;
+        boolean topLeftPosition = mInitialPosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT;
         if (deviceProfile.isLandscape) {
             params.width = (int) resources.getDimension(R.dimen.split_placeholder_size);
             params.gravity = topLeftPosition ? Gravity.START : Gravity.END;
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 7b1c62e..9960fd3 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -145,8 +145,9 @@
             // The task rect changes according to the staged split task sizes, but recents
             // fullscreen scale and pivot remains the same since the task fits into the existing
             // sized task space bounds
-            mSizeStrategy.calculateStagedSplitTaskSize(mContext, mDp, mTaskRect, mStagedSplitBounds,
-                    mStagePosition);
+            mSizeStrategy.calculateTaskSize(mContext, mDp, mTaskRect);
+            mOrientationState.getOrientationHandler()
+                    .setSplitTaskSwipeRect(mDp, mTaskRect, mStagedSplitBounds, mStagePosition);
         } else {
             mTaskRect.set(fullTaskSize);
         }
@@ -175,7 +176,7 @@
             mStagePosition = STAGE_POSITION_UNDEFINED;
             return;
         }
-        mStagePosition = mThumbnailPosition.equals(splitInfo.mLeftTopBounds) ?
+        mStagePosition = mThumbnailPosition.equals(splitInfo.leftTopBounds) ?
                 STAGE_POSITION_TOP_OR_LEFT :
                 STAGE_POSITION_BOTTOM_OR_RIGHT;
     }
@@ -277,13 +278,9 @@
             getFullScreenScale();
             mThumbnailData.rotation = mOrientationState.getDisplayRotation();
 
-            // TODO(b/195145340) handle non 50-50 split scenarios
             if (mStagedSplitBounds != null) {
-                if (mStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
-                    // The preview set is for the bottom/right, inset by top/left task
-                    mSplitOffset.y = mStagedSplitBounds.mLeftTopBounds.height() +
-                        mStagedSplitBounds.mDividerBounds.height() / 2;
-                }
+                mOrientationState.getOrientationHandler().setLeashSplitOffset(mSplitOffset, mDp,
+                        mStagedSplitBounds, mStagePosition);
             }
 
             // mIsRecentsRtl is the inverse of TaskView RTL.
@@ -331,7 +328,7 @@
         applyWindowToHomeRotation(mMatrix);
 
         // Move lower/right split window into correct position
-        mMatrix.postTranslate(0, mSplitOffset.y);
+        mMatrix.postTranslate(mSplitOffset.x, mSplitOffset.y);
 
         // Crop rect is the inverse of thumbnail matrix
         mTempRectF.set(-insets.left, -insets.top,
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index cd20f4b..1bc7c75 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -1,13 +1,10 @@
 package com.android.quickstep.views;
 
-import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
-
 import android.content.Context;
 import android.util.AttributeSet;
-import android.view.ViewGroup;
 
-import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.quickstep.RecentsModel;
 import com.android.quickstep.TaskThumbnailCache;
 import com.android.quickstep.util.CancellableTask;
@@ -48,13 +45,14 @@
         mSnapshotView2 = findViewById(R.id.bottomright_snapshot);
     }
 
-    public void bind(Task primary, Task secondary, RecentsOrientedState orientedState) {
+    public void bind(Task primary, Task secondary, RecentsOrientedState orientedState,
+            SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig) {
         super.bind(primary, orientedState);
         mSecondaryTask = secondary;
         mTaskIdContainer[1] = secondary.key.id;
         mTaskIdAttributeContainer[1] = new TaskIdAttributeContainer(secondary, mSnapshotView2);
         mSnapshotView2.bind(secondary);
-        adjustThumbnailBoundsForSplit();
+        adjustThumbnailBoundsForSplit(splitBoundsConfig, orientedState);
     }
 
     @Override
@@ -108,30 +106,15 @@
         mSnapshotView2.setOverlayEnabled(overlayEnabled);
     }
 
-    private void adjustThumbnailBoundsForSplit() {
-        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
-        ViewGroup.LayoutParams primaryLp = mSnapshotView.getLayoutParams();
-        primaryLp.width = mSecondaryTask == null ?
-                MATCH_PARENT :
-                getWidth();
-        int spaceAboveSnapshot = deviceProfile.overviewTaskThumbnailTopMarginPx;
-        // TODO get divider height
-        int dividerBar = 20;
-        primaryLp.height = mSecondaryTask == null ?
-                MATCH_PARENT :
-                (getHeight() - spaceAboveSnapshot - dividerBar) / 2;
-        mSnapshotView.setLayoutParams(primaryLp);
-
-        if (mSecondaryTask == null) {
-            mSnapshotView2.setVisibility(GONE);
+    private void adjustThumbnailBoundsForSplit(
+            SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig,
+            RecentsOrientedState orientedState) {
+        if (splitBoundsConfig == null) {
             return;
         }
 
-        mSnapshotView2.setVisibility(VISIBLE);
-        ViewGroup.LayoutParams secondaryLp = mSnapshotView2.getLayoutParams();
-        secondaryLp.width = getWidth();
-        secondaryLp.height = primaryLp.height;
-        mSnapshotView2.setLayoutParams(secondaryLp);
-        mSnapshotView2.setTranslationY(primaryLp.height + spaceAboveSnapshot + dividerBar);
+        orientedState.getOrientationHandler().setGroupedTaskViewThumbnailBounds(
+                mSnapshotView, mSnapshotView2, this, splitBoundsConfig,
+                mActivity.getDeviceProfile());
     }
 }
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 2a19ca2..5974677 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -575,6 +575,7 @@
      */
     private TaskView mSplitHiddenTaskView;
     private TaskView mSecondSplitHiddenTaskView;
+    private SplitConfigurationOptions.StagedSplitBounds mSplitBoundsConfig;
 
     /**
      * Keeps track of the index of the TaskView that split screen was initialized with so we know
@@ -1314,7 +1315,8 @@
                     taskDataIndex--;
                     leftTop = tasks.get(taskDataIndex);
                 }
-                ((GroupedTaskView) taskView).bind(leftTop, rightBottom, mOrientationState);
+                ((GroupedTaskView) taskView).bind(leftTop, rightBottom, mOrientationState,
+                        mSplitBoundsConfig);
             } else {
                 taskView.bind(task, mOrientationState);
             }
@@ -2087,8 +2089,11 @@
                         Task.from(new TaskKey(secondaryTaskInfo), secondaryTaskInfo, false)
                 };
                 addView(taskView, mTaskViewStartIndex);
+                // When we create a placeholder task view mSplitBoundsConfig will be null, but with
+                // the actual app running we won't need to show the thumbnail until all the tasks
+                // load later anyways
                 ((GroupedTaskView)taskView).bind(mTmpRunningTasks[0], mTmpRunningTasks[1],
-                        mOrientationState);
+                        mOrientationState, mSplitBoundsConfig);
             } else {
                 taskView = getTaskViewFromPool(false);
                 addView(taskView, mTaskViewStartIndex);
@@ -4038,12 +4043,13 @@
             mRemoteTargetHandles[1] = new RemoteTargetHandle(secondaryTvs, new TransformParams());
             RemoteAnimationTargetCompat primaryTaskTarget = recentsAnimationTargets.apps[0];
             RemoteAnimationTargetCompat secondaryTaskTarget = recentsAnimationTargets.apps[1];
-            SplitConfigurationOptions.StagedSplitBounds
-                    info = new SplitConfigurationOptions.StagedSplitBounds(
+            mSplitBoundsConfig = new SplitConfigurationOptions.StagedSplitBounds(
                     primaryTaskTarget.screenSpaceBounds,
                     secondaryTaskTarget.screenSpaceBounds, dividerTarget.screenSpaceBounds);
-            mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget, info);
-            mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(secondaryTaskTarget, info);
+            mRemoteTargetHandles[0].mTaskViewSimulator.setPreview(primaryTaskTarget,
+                    mSplitBoundsConfig);
+            mRemoteTargetHandles[1].mTaskViewSimulator.setPreview(secondaryTaskTarget,
+                    mSplitBoundsConfig);
             RemoteAnimationTargets rats = new RemoteAnimationTargets(
                     new RemoteAnimationTargetCompat[]{primaryTaskTarget},
                     recentsAnimationTargets.wallpapers, recentsAnimationTargets.nonApps,
@@ -4084,6 +4090,8 @@
 
     public void finishRecentsAnimation(boolean toRecents, boolean shouldPip,
             Runnable onFinishComplete) {
+        // TODO(b/197232424#comment#10) Move this back into onRecentsAnimationComplete(). Maybe?
+        mRemoteTargetHandles = null;
         if (!toRecents && ENABLE_QUICKSTEP_LIVE_TILE.get()) {
             // Reset the minimized state since we force-toggled the minimized state when entering
             // overview, but never actually finished the recents animation.  This is a catch all for
@@ -4131,7 +4139,6 @@
         setCurrentTask(-1);
         mRecentsAnimationController = null;
         executeSideTaskLaunchCallback();
-        mRemoteTargetHandles = null;
     }
 
     public void setDisallowScrollToClearAll(boolean disallowScrollToClearAll) {
diff --git a/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
similarity index 98%
rename from quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
rename to quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
index 2b1b57c..159a51f 100644
--- a/quickstep/robolectric_tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
+++ b/quickstep/tests/src/com/android/quickstep/OrientationTouchTransformerTest.java
@@ -19,6 +19,8 @@
 
 import static android.view.Display.DEFAULT_DISPLAY;
 
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+
 import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
 
 import static org.junit.Assert.assertFalse;
@@ -40,6 +42,9 @@
 import android.view.MotionEvent;
 import android.view.Surface;
 
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
 import com.android.launcher3.ResourceUtils;
 import com.android.launcher3.util.DisplayController;
 
@@ -47,10 +52,9 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
 
-@RunWith(RobolectricTestRunner.class)
+@SmallTest
+@RunWith(AndroidJUnit4.class)
 public class OrientationTouchTransformerTest {
     static class ScreenSize {
         int mHeight;
@@ -293,7 +297,7 @@
     }
 
     private DisplayController.Info createDisplayInfo(ScreenSize screenSize, int rotation) {
-        Context context = RuntimeEnvironment.application;
+        Context context = getApplicationContext();
         Display display = spy(context.getSystemService(DisplayManager.class)
                 .getDisplay(DEFAULT_DISPLAY));
 
diff --git a/res/color-v31/overview_scrim_dark.xml b/res/color-v31/overview_scrim_dark.xml
index b8ed774..85ede9a 100644
--- a/res/color-v31/overview_scrim_dark.xml
+++ b/res/color-v31/overview_scrim_dark.xml
@@ -14,5 +14,5 @@
      limitations under the License.
 -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-  <item android:color="@android:color/system_neutral1_800" />
+  <item android:color="@android:color/system_neutral2_500" android:lStar="35" />
 </selector>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 3010be1..b7d0481 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -248,7 +248,8 @@
         // Tablet UI does not support emulated landscape.
         isTablet = allowRotation && info.isTablet(windowBounds);
         isPhone = !isTablet;
-        isTwoPanels = isTablet && useTwoPanels;
+        isTwoPanels = isTablet && useTwoPanels
+                && (isLandscape || FeatureFlags.ENABLE_TWO_PANEL_HOME_IN_PORTRAIT.get());
 
         aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
         boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 4d5cc5e..6ea7b17 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2186,6 +2186,24 @@
     }
 
     private void bindAddScreens(IntArray orderedScreenIds) {
+        if (mDeviceProfile.isTwoPanels) {
+            // Some empty pages might have been removed while the phone was in a single panel
+            // mode, so we want to add those empty pages back.
+            IntSet screenIds = IntSet.wrap(orderedScreenIds);
+            for (int i = 0; i < orderedScreenIds.size(); i++) {
+                int screenId = orderedScreenIds.get(i);
+                // Don't add the page pair if the page is the last one and if the pair is on the
+                // right, because that would cause a bug when adding new pages.
+                // TODO: (b/196376162) remove this when the new screen id logic is fixed for two
+                //  panel in Workspace::commitExtraEmptyScreen
+                if (i == orderedScreenIds.size() - 1 && screenId % 2 == 0) {
+                    continue;
+                }
+                screenIds.add(mWorkspace.getPagePair(screenId));
+            }
+            orderedScreenIds = screenIds.getArray();
+        }
+
         int count = orderedScreenIds.size();
         for (int i = 0; i < count; i++) {
             int screenId = orderedScreenIds.get(i);
@@ -2193,7 +2211,6 @@
                 // No need to bind the first screen, as its always bound.
                 continue;
             }
-
             mWorkspace.insertNewWorkspaceScreenBeforeEmptyScreen(screenId);
         }
     }
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 38beeea..94ec903 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -123,6 +123,7 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Iterator;
 import java.util.List;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
@@ -333,7 +334,8 @@
         int paddingBottom = grid.cellLayoutBottomPaddingPx;
 
         int panelCount = getPanelCount();
-        for (int i = mWorkspaceScreens.size() - 1; i >= 0; i--) {
+        int numberOfScreens = mScreenOrder.size();
+        for (int i = 0; i < numberOfScreens; i++) {
             int paddingLeft = paddingLeftRight;
             int paddingRight = paddingLeftRight;
             if (panelCount > 1) {
@@ -348,7 +350,9 @@
                     paddingRight = 0;
                 }
             }
-            mWorkspaceScreens.valueAt(i).setPadding(paddingLeft, 0, paddingRight, paddingBottom);
+            // SparseArrayMap doesn't keep the order
+            mWorkspaceScreens.get(mScreenOrder.get(i))
+                    .setPadding(paddingLeft, 0, paddingRight, paddingBottom);
         }
     }
 
@@ -797,6 +801,21 @@
         return mScreenOrder;
     }
 
+    /**
+     * Returns the page that is shown together with the given page when two panel is enabled.
+     * @throws IllegalStateException if called while two panel home isn't enabled.
+     */
+    public int getPagePair(int page) {
+        if (!isTwoPanelEnabled()) {
+            throw new IllegalStateException("Two panel home isn't enabled.");
+        }
+        if (page % 2 == 0) {
+            return page + 1;
+        } else {
+            return page - 1;
+        }
+    }
+
     public void stripEmptyScreens() {
         if (mLauncher.isWorkspaceLoading()) {
             // Don't strip empty screens if the workspace is still loading.
@@ -822,6 +841,22 @@
             }
         }
 
+        // When two panel home is enabled we only remove an empty page if both visible pages are
+        // empty.
+        if (isTwoPanelEnabled()) {
+            // We go through all the pages that were marked as removable and check their page pair
+            Iterator<Integer> removeScreensIterator = removeScreens.iterator();
+            while (removeScreensIterator.hasNext()) {
+                int pageToRemove = removeScreensIterator.next();
+                int pagePair = getPagePair(pageToRemove);
+                if (!removeScreens.contains(pagePair)) {
+                    // The page pair isn't empty so we want to remove the current page from the
+                    // removable pages' collection
+                    removeScreensIterator.remove();
+                }
+            }
+        }
+
         // We enforce at least one page to add new items to. In the case that we remove the last
         // such screen, we convert the last screen to the empty screen
         int minScreens = 1;
diff --git a/src/com/android/launcher3/WorkspaceLayoutManager.java b/src/com/android/launcher3/WorkspaceLayoutManager.java
index d6302ce..44a5536 100644
--- a/src/com/android/launcher3/WorkspaceLayoutManager.java
+++ b/src/com/android/launcher3/WorkspaceLayoutManager.java
@@ -32,6 +32,8 @@
     int EXTRA_EMPTY_SCREEN_ID = -201;
     // The is the first screen. It is always present, even if its empty.
     int FIRST_SCREEN_ID = 0;
+    // This is the second page. On two panel home it is always present, even if its empty.
+    int SECOND_SCREEN_ID = 1;
 
     /**
      * At bind time, we use the rank (screenId) to compute x and y for hotseat items.
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 38a957d..74c7310 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -230,6 +230,10 @@
             "ENABLE_TWO_PANEL_HOME", true,
             "Uses two panel on home screen. Only applicable on large screen devices.");
 
+    public static final BooleanFlag ENABLE_TWO_PANEL_HOME_IN_PORTRAIT = getDebugFlag(
+            "ENABLE_TWO_PANEL_HOME_IN_PORTRAIT", true,
+            "Uses two panel on home screen in portrait if ENABLE_TWO_PANEL_HOME is enabled.");
+
     public static final BooleanFlag ENABLE_SCRIM_FOR_APP_LAUNCH = getDebugFlag(
             "ENABLE_SCRIM_FOR_APP_LAUNCH", false,
             "Enables scrim during app launch animation.");
diff --git a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
index a96de31..94c578e 100644
--- a/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
+++ b/src/com/android/launcher3/graphics/LauncherPreviewRenderer.java
@@ -65,6 +65,7 @@
 import com.android.launcher3.LauncherSettings.Favorites;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.Workspace;
 import com.android.launcher3.WorkspaceLayoutManager;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.folder.FolderIcon;
@@ -279,7 +280,7 @@
                     mDp.workspacePadding.top,
                     mDp.workspacePadding.right + mDp.cellLayoutPaddingLeftRightPx,
                     mDp.workspacePadding.bottom);
-            mWorkspaceScreens.put(PreviewSurfaceRenderer.SECOND_SCREEN_ID, rightPanel);
+            mWorkspaceScreens.put(Workspace.SECOND_SCREEN_ID, rightPanel);
         }
 
         if (Utilities.ATLEAST_S) {
diff --git a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
index af006d6..f4d1e61 100644
--- a/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
+++ b/src/com/android/launcher3/graphics/PreviewSurfaceRenderer.java
@@ -66,9 +66,6 @@
 
     private static final int FADE_IN_ANIMATION_DURATION = 200;
 
-    // The is the second screen. It is always present in two panel, even if its empty.
-    static final int SECOND_SCREEN_ID = 1;
-
     private static final String KEY_HOST_TOKEN = "host_token";
     private static final String KEY_VIEW_WIDTH = "width";
     private static final String KEY_VIEW_HEIGHT = "height";
@@ -172,7 +169,7 @@
                             + LauncherSettings.Favorites.CONTAINER_HOTSEAT;
                     if (deviceProfile.isTwoPanels) {
                         query += " or " + LauncherSettings.Favorites.SCREEN + " = "
-                                + SECOND_SCREEN_ID;
+                                + Workspace.SECOND_SCREEN_ID;
                     }
                     loadWorkspace(new ArrayList<>(), LauncherSettings.Favorites.PREVIEW_CONTENT_URI,
                             query);
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index a13fa55..fea15c4 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -16,6 +16,7 @@
 package com.android.launcher3.model;
 
 import static com.android.launcher3.WorkspaceLayoutManager.FIRST_SCREEN_ID;
+import static com.android.launcher3.WorkspaceLayoutManager.SECOND_SCREEN_ID;
 
 import android.content.Intent;
 import android.content.pm.LauncherActivityInfo;
@@ -299,6 +300,11 @@
         IntSet screensToExclude = new IntSet();
         if (FeatureFlags.QSB_ON_FIRST_SCREEN) {
             screensToExclude.add(FIRST_SCREEN_ID);
+
+            // On split display we don't want to add the new items onto the second screen.
+            if (app.getInvariantDeviceProfile().isSplitDisplay) {
+                screensToExclude.add(SECOND_SCREEN_ID);
+            }
         }
 
         for (int screen = 0; screen < screenCount; screen++) {
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 816e5dc..29e5446 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -26,6 +26,7 @@
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_TYPE_MAIN;
 
 import android.content.res.Resources;
+import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -35,12 +36,14 @@
 import android.view.Surface;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.LinearLayout;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.views.BaseDragLayer;
 
@@ -166,12 +169,12 @@
             DeviceProfile dp) {
         // Don't use device profile here because we know we're in fake landscape, only split option
         // available is top/left
-        if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+        if (splitPosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
             // Top (visually left) side
             return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
         }
         throw new IllegalStateException("Invalid split stage position: " +
-                splitPosition.mStagePosition);
+                splitPosition.stagePosition);
     }
 
     @Override
@@ -382,6 +385,47 @@
     }
 
     @Override
+    public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
+            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+        float diff;
+        if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
+            diff = outRect.height() * (1f - splitInfo.leftTaskPercent);
+            outRect.bottom -= diff;
+        } else {
+            diff = outRect.height() * splitInfo.leftTaskPercent;
+            outRect.top += diff;
+        }
+    }
+
+    @Override
+    public void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
+            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+        if (desiredStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
+            // The preview set is for the bottom/right, inset by top/left task
+            splitOffset.x = splitInfo.leftTopBounds.width() + splitInfo.dividerBounds.width() / 2;
+        }
+    }
+
+    @Override
+    public void setGroupedTaskViewThumbnailBounds(View mSnapshotView, View mSnapshotView2,
+            View taskParent, SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig,
+            DeviceProfile dp) {
+        int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
+        int totalThumbnailHeight = taskParent.getHeight() - spaceAboveSnapshot;
+        int totalThumbnailWidth = taskParent.getWidth();
+        int dividerBar = splitBoundsConfig.dividerBounds.width() / 2;
+        ViewGroup.LayoutParams primaryLp = mSnapshotView.getLayoutParams();
+        ViewGroup.LayoutParams secondaryLp = mSnapshotView2.getLayoutParams();
+
+        primaryLp.width = totalThumbnailWidth;
+        primaryLp.height = (int)(totalThumbnailHeight * splitBoundsConfig.leftTaskPercent);
+
+        secondaryLp.width = totalThumbnailWidth;
+        secondaryLp.height = totalThumbnailHeight - primaryLp.height - dividerBar;
+        mSnapshotView2.setTranslationY(primaryLp.height + spaceAboveSnapshot + dividerBar);
+    }
+
+    @Override
     public FloatProperty getSplitSelectTaskOffset(FloatProperty primary, FloatProperty secondary,
             DeviceProfile deviceProfile) {
         return primary;
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index dae2dde..5ef6950 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -19,6 +19,7 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
+import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -31,6 +32,7 @@
 import android.widget.LinearLayout;
 
 import com.android.launcher3.DeviceProfile;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
 
@@ -133,6 +135,34 @@
     void getFinalSplitPlaceholderBounds(int splitDividerSize, DeviceProfile dp,
             SplitPositionOption initialSplitOption, Rect out1, Rect out2);
 
+    /**
+     * @param outRect This is expected to be the rect that has the dimensions for a non-split,
+     *                fullscreen task in overview. This will directly be modified.
+     * @param desiredStagePosition Which stage position (topLeft/rightBottom) we want to resize
+     *                           outRect for
+     */
+    void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
+            SplitConfigurationOptions.StagedSplitBounds splitInfo,
+            @SplitConfigurationOptions.StagePosition int desiredStagePosition);
+
+    /**
+     * It's important to note that {@link #setSplitTaskSwipeRect(DeviceProfile, Rect,
+     * SplitConfigurationOptions.StagedSplitBounds, int)} above operates on the outRect based on
+     * launcher's coordinate system, meaning it will treat the outRect as portrait if home rotation
+     * is not allowed.
+     *
+     * However, here the splitOffset is from perspective of TaskViewSimulator, which is in display
+     * orientation coordinates. So, for example, for the fake landscape scenario, even though
+     * launcher is portrait, we inset the bottom/right task by an X coordinate instead of the
+     * usual Y
+     */
+    void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
+            SplitConfigurationOptions.StagedSplitBounds splitInfo,
+            @SplitConfigurationOptions.StagePosition int desiredStagePosition);
+
+    void setGroupedTaskViewThumbnailBounds(View mSnapshot1, View mSnapshot2, View taskParent,
+            SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, DeviceProfile dp);
+
     // Overview TaskMenuView methods
     float getTaskMenuX(float x, View thumbnailView, int overScroll);
     float getTaskMenuY(float y, View thumbnailView, int overScroll);
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 1253589..737162f 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -25,6 +25,7 @@
 
 import android.content.res.Resources;
 import android.graphics.Matrix;
+import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.graphics.RectF;
@@ -34,12 +35,14 @@
 import android.view.Surface;
 import android.view.VelocityTracker;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.LinearLayout;
 
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
+import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.views.BaseDragLayer;
 
@@ -164,7 +167,7 @@
     @Override
     public int getSplitTaskViewDismissDirection(SplitPositionOption splitPosition,
             DeviceProfile dp) {
-        if (splitPosition.mStagePosition == STAGE_POSITION_TOP_OR_LEFT) {
+        if (splitPosition.stagePosition == STAGE_POSITION_TOP_OR_LEFT) {
             if (dp.isLandscape) {
                 // Left side
                 return SPLIT_TRANSLATE_PRIMARY_NEGATIVE;
@@ -172,12 +175,12 @@
                 // Top side
                 return SPLIT_TRANSLATE_SECONDARY_NEGATIVE;
             }
-        } else if (splitPosition.mStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
+        } else if (splitPosition.stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
             // We don't have a bottom option, so should be right
             return SPLIT_TRANSLATE_PRIMARY_POSITIVE;
         }
         throw new IllegalStateException("Invalid split stage position: " +
-                splitPosition.mStagePosition);
+                splitPosition.stagePosition);
     }
 
     @Override
@@ -422,7 +425,7 @@
         }
 
         // Now we rotate the portrait rect depending on what side we want pinned
-        boolean pinToRight = splitPositionOption.mStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
+        boolean pinToRight = splitPositionOption.stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
 
         int screenHeight = dp.heightPx;
         float postRotateScale = (float) screenHeight / width;
@@ -450,7 +453,7 @@
         }
 
         // Now we rotate the portrait rect depending on what side we want pinned
-        boolean pinToRight = initialSplitOption.mStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
+        boolean pinToRight = initialSplitOption.stagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT;
         float postRotateScale = (float) screenHeight / screenWidth;
 
         mTmpMatrix.reset();
@@ -468,6 +471,77 @@
     }
 
     @Override
+    public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
+            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+        boolean isLandscape = dp.isLandscape;
+        float diff;
+        if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
+            if (isLandscape) {
+                diff = outRect.width() * (1f - splitInfo.leftTaskPercent);
+                outRect.right -= diff;
+            } else {
+                diff = outRect.height() * (1f - splitInfo.topTaskPercent);
+                outRect.bottom -= diff;
+            }
+        } else {
+            if (isLandscape) {
+                diff = outRect.width() * splitInfo.leftTaskPercent;
+                outRect.left += diff;
+            } else {
+                diff = outRect.height() * splitInfo.topTaskPercent;
+                outRect.top += diff;
+            }
+        }
+    }
+
+    @Override
+    public void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
+            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+        if (desiredStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
+            if (dp.isLandscape) {
+                splitOffset.x = splitInfo.leftTopBounds.width() +
+                        splitInfo.dividerBounds.width() / 2;
+            } else {
+                splitOffset.y = splitInfo.leftTopBounds.height() +
+                        splitInfo.dividerBounds.height() / 2;
+            }
+        }
+    }
+
+    @Override
+    public void setGroupedTaskViewThumbnailBounds(View mSnapshotView, View mSnapshotView2,
+            View taskParent, SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig,
+            DeviceProfile dp) {
+        int spaceAboveSnapshot = dp.overviewTaskThumbnailTopMarginPx;
+        int totalThumbnailHeight = taskParent.getHeight() - spaceAboveSnapshot;
+        int totalThumbnailWidth = taskParent.getWidth();
+        int dividerBar = (dp.isLandscape ?
+                splitBoundsConfig.dividerBounds.width() :
+                splitBoundsConfig.dividerBounds.height())
+                / 2;
+        ViewGroup.LayoutParams primaryLp = mSnapshotView.getLayoutParams();
+        ViewGroup.LayoutParams secondaryLp = mSnapshotView2.getLayoutParams();
+
+        if (dp.isLandscape) {
+            primaryLp.height = totalThumbnailHeight;
+            primaryLp.width = (int)(totalThumbnailWidth * splitBoundsConfig.leftTaskPercent);
+
+            secondaryLp.height = totalThumbnailHeight;
+            secondaryLp.width = totalThumbnailWidth - primaryLp.width - dividerBar;
+            mSnapshotView2.setTranslationX(primaryLp.width + dividerBar);
+            mSnapshotView2.setTranslationY(spaceAboveSnapshot);
+        } else {
+            primaryLp.width = totalThumbnailWidth;
+            primaryLp.height = (int)(totalThumbnailHeight * splitBoundsConfig.topTaskPercent);
+
+            secondaryLp.width = totalThumbnailWidth;
+            secondaryLp.height = totalThumbnailHeight - primaryLp.height - dividerBar;
+            mSnapshotView2.setTranslationY(primaryLp.height + spaceAboveSnapshot + dividerBar);
+            mSnapshotView2.setTranslationX(0);
+        }
+    }
+
+    @Override
     public FloatProperty getSplitSelectTaskOffset(FloatProperty primary, FloatProperty secondary,
             DeviceProfile dp) {
         if (dp.isLandscape) { // or seascape
diff --git a/src/com/android/launcher3/util/IntArray.java b/src/com/android/launcher3/util/IntArray.java
index e7235e7..1c78795 100644
--- a/src/com/android/launcher3/util/IntArray.java
+++ b/src/com/android/launcher3/util/IntArray.java
@@ -296,7 +296,7 @@
 
         @Override
         public void remove() {
-            throw new UnsupportedOperationException();
+            removeIndex(--mNextIndex);
         }
     }
 }
\ No newline at end of file
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index 1f1db9d..41693de 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -69,32 +69,44 @@
     ///////////////////////////////////
 
     public static class SplitPositionOption {
-        public final int mIconResId;
-        public final int mTextResId;
+        public final int iconResId;
+        public final int textResId;
         @StagePosition
-        public final int mStagePosition;
+        public final int stagePosition;
 
         @StageType
         public final int mStageType;
 
         public SplitPositionOption(int iconResId, int textResId, int stagePosition, int stageType) {
-            mIconResId = iconResId;
-            mTextResId = textResId;
-            mStagePosition = stagePosition;
+            this.iconResId = iconResId;
+            this.textResId = textResId;
+            this.stagePosition = stagePosition;
             mStageType = stageType;
         }
     }
 
     public static class StagedSplitBounds {
-        public final Rect mLeftTopBounds;
-        public final Rect mRightBottomBounds;
-        public final Rect mDividerBounds;
+        public final Rect leftTopBounds;
+        public final Rect rightBottomBounds;
+        public final Rect dividerBounds;
+        // This class is orientation-agnostic, so we compute both for later use
+        public final float topTaskPercent;
+        public final float leftTaskPercent;
 
 
         public StagedSplitBounds(Rect leftTopBounds, Rect rightBottomBounds, Rect dividerBounds) {
-            mLeftTopBounds = leftTopBounds;
-            mRightBottomBounds = rightBottomBounds;
-            mDividerBounds = dividerBounds;
+            this.leftTopBounds = leftTopBounds;
+            this.rightBottomBounds = rightBottomBounds;
+            this.dividerBounds = dividerBounds;
+            float totalHeight = this.leftTopBounds.height()
+                    + this.rightBottomBounds.height()
+                    + this.dividerBounds.height();
+            float totalWidth = this.leftTopBounds.width()
+                    + this.rightBottomBounds.width()
+                    + this.dividerBounds.width();
+
+            leftTaskPercent = this.leftTopBounds.width() / totalWidth;
+            topTaskPercent = this.leftTopBounds.height() / totalHeight;
         }
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 7c73f2b..f1fe508 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -248,6 +248,8 @@
         if (pm.getComponentEnabledSetting(cn) != COMPONENT_ENABLED_STATE_ENABLED) {
             if (TestHelpers.isInLauncherProcess()) {
                 pm.setComponentEnabledSetting(cn, COMPONENT_ENABLED_STATE_ENABLED, DONT_KILL_APP);
+                // b/195031154
+                SystemClock.sleep(5000);
             } else {
                 try {
                     final int userId = ContextUtils.getUserId(getContext());