Merge "Show multiple icons for GroupedTaskView" into sc-v2-dev
diff --git a/quickstep/res/layout/task_grouped.xml b/quickstep/res/layout/task_grouped.xml
index 069ff86..cd5bcbd 100644
--- a/quickstep/res/layout/task_grouped.xml
+++ b/quickstep/res/layout/task_grouped.xml
@@ -44,4 +44,11 @@
         android:layout_height="@dimen/task_thumbnail_icon_size"
         android:focusable="false"
         android:importantForAccessibility="no"/>
+
+    <com.android.quickstep.views.IconView
+        android:id="@+id/bottomRight_icon"
+        android:layout_width="@dimen/task_thumbnail_icon_size"
+        android:layout_height="@dimen/task_thumbnail_icon_size"
+        android:focusable="false"
+        android:importantForAccessibility="no"/>
 </com.android.quickstep.views.GroupedTaskView>
\ No newline at end of file
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 16303f3..b1b4b54 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -1,18 +1,26 @@
 package com.android.quickstep.views;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.util.AttributeSet;
+import android.view.MotionEvent;
 
 import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
+import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.R;
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SplitConfigurationOptions;
+import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
+import com.android.launcher3.util.TransformingTouchDelegate;
 import com.android.quickstep.RecentsModel;
+import com.android.quickstep.TaskIconCache;
 import com.android.quickstep.TaskThumbnailCache;
 import com.android.quickstep.util.CancellableTask;
 import com.android.quickstep.util.RecentsOrientedState;
 import com.android.systemui.shared.recents.model.Task;
+import com.android.systemui.shared.recents.model.ThumbnailData;
 
 import java.util.function.Consumer;
 
@@ -30,8 +38,14 @@
 
     private Task mSecondaryTask;
     private TaskThumbnailView mSnapshotView2;
-    private CancellableTask mThumbnailLoadRequest2;
-    private SplitConfigurationOptions.StagedSplitBounds mSplitBoundsConfig;
+    private IconView mIconView2;
+    private CancellableTask<ThumbnailData> mThumbnailLoadRequest2;
+    private CancellableTask mIconLoadRequest2;
+    private final float[] mIcon2CenterCoords = new float[2];
+    private TransformingTouchDelegate mIcon2TouchDelegate;
+    @Nullable private StagedSplitBounds mSplitBoundsConfig;
+    private final Rect mPrimaryTempRect = new Rect();
+    private final Rect mSecondaryTempRect = new Rect();
 
     public GroupedTaskView(Context context) {
         super(context);
@@ -49,10 +63,12 @@
     protected void onFinishInflate() {
         super.onFinishInflate();
         mSnapshotView2 = findViewById(R.id.bottomright_snapshot);
+        mIconView2 = findViewById(R.id.bottomRight_icon);
+        mIcon2TouchDelegate = new TransformingTouchDelegate(mIconView2);
     }
 
     public void bind(Task primary, Task secondary, RecentsOrientedState orientedState,
-            SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig) {
+            StagedSplitBounds splitBoundsConfig) {
         super.bind(primary, orientedState);
         mSecondaryTask = secondary;
         mTaskIdContainer[1] = secondary.key.id;
@@ -67,6 +83,7 @@
         if (visible) {
             RecentsModel model = RecentsModel.INSTANCE.get(getContext());
             TaskThumbnailCache thumbnailCache = model.getThumbnailCache();
+            TaskIconCache iconCache = model.getIconCache();
 
             if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
                 mThumbnailLoadRequest2 = thumbnailCache.updateThumbnailInBackground(mSecondaryTask,
@@ -76,7 +93,11 @@
             }
 
             if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
-                // TODO What's the Icon for this going to look like? :o
+                mIconLoadRequest2 = iconCache.updateIconInBackground(mSecondaryTask,
+                        (task) -> {
+                            setIcon(mIconView2, task.icon);
+                            // TODO(199936292) Digital Wellbeing for individual tasks?
+                        });
             }
         } else {
             if (needsUpdate(changes, FLAG_UPDATE_THUMBNAIL)) {
@@ -86,11 +107,26 @@
                 mSecondaryTask.thumbnail = null;
             }
             if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
-                // TODO
+                setIcon(mIconView2, null);
             }
         }
     }
 
+    public void updateSplitBoundsConfig(StagedSplitBounds stagedSplitBounds) {
+        mSplitBoundsConfig = stagedSplitBounds;
+        invalidate();
+    }
+
+    @Override
+    public boolean offerTouchToChildren(MotionEvent event) {
+        computeAndSetIconTouchDelegate(mIconView2, mIcon2CenterCoords, mIcon2TouchDelegate);
+        if (mIcon2TouchDelegate.onTouchEvent(event)) {
+            return true;
+        }
+
+        return super.offerTouchToChildren(event);
+    }
+
     @Override
     protected void cancelPendingLoadTasks() {
         super.cancelPendingLoadTasks();
@@ -98,6 +134,10 @@
             mThumbnailLoadRequest2.cancel();
             mThumbnailLoadRequest2 = null;
         }
+        if (mIconLoadRequest2 != null) {
+            mIconLoadRequest2.cancel();
+            mIconLoadRequest2 = null;
+        }
     }
 
     @Override
@@ -137,6 +177,7 @@
         getPagedOrientationHandler().measureGroupedTaskViewThumbnailBounds(mSnapshotView,
                 mSnapshotView2, widthSize, heightSize, mSplitBoundsConfig,
                 mActivity.getDeviceProfile());
+        updateIconPlacement();
     }
 
     @Override
@@ -144,4 +185,32 @@
         super.setOverlayEnabled(overlayEnabled);
         mSnapshotView2.setOverlayEnabled(overlayEnabled);
     }
+
+    @Override
+    public void setOrientationState(RecentsOrientedState orientationState) {
+        super.setOrientationState(orientationState);
+        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        boolean isGridTask = deviceProfile.overviewShowAsGrid && !isFocusedTask();
+        int iconDrawableSize = isGridTask ? deviceProfile.overviewTaskIconDrawableSizeGridPx
+                : deviceProfile.overviewTaskIconDrawableSizePx;
+        mIconView2.setDrawableSize(iconDrawableSize, iconDrawableSize);
+        mIconView2.setRotation(getPagedOrientationHandler().getDegreesRotated());
+        updateIconPlacement();
+    }
+
+    private void updateIconPlacement() {
+        if (mSplitBoundsConfig == null) {
+            return;
+        }
+
+        DeviceProfile deviceProfile = mActivity.getDeviceProfile();
+        int taskIconHeight = deviceProfile.overviewTaskIconSizePx;
+        boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
+
+        mSnapshotView.getBoundsOnScreen(mPrimaryTempRect);
+        mSnapshotView2.getBoundsOnScreen(mSecondaryTempRect);
+        getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2,
+                taskIconHeight, mPrimaryTempRect, mSecondaryTempRect,
+                isRtl, deviceProfile, mSplitBoundsConfig);
+    }
 }
diff --git a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
index ac779b1..da3fa2a 100644
--- a/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
+++ b/quickstep/src/com/android/quickstep/views/OverviewActionsView.java
@@ -54,7 +54,8 @@
             HIDDEN_NON_ZERO_ROTATION,
             HIDDEN_NO_TASKS,
             HIDDEN_NO_RECENTS,
-            HIDDEN_FOCUSED_SCROLL})
+            HIDDEN_FOCUSED_SCROLL,
+            HIDDEN_SPLIT_SCREEN})
     @Retention(RetentionPolicy.SOURCE)
     public @interface ActionsHiddenFlags { }
 
@@ -62,6 +63,7 @@
     public static final int HIDDEN_NO_TASKS = 1 << 1;
     public static final int HIDDEN_NO_RECENTS = 1 << 2;
     public static final int HIDDEN_FOCUSED_SCROLL = 1 << 3;
+    public static final int HIDDEN_SPLIT_SCREEN = 1 << 4;
 
     @IntDef(flag = true, value = {
             DISABLED_SCROLLING,
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 5fa95f4..e25a8bc 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -53,6 +53,7 @@
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NON_ZERO_ROTATION;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_RECENTS;
 import static com.android.quickstep.views.OverviewActionsView.HIDDEN_NO_TASKS;
+import static com.android.quickstep.views.OverviewActionsView.HIDDEN_SPLIT_SCREEN;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
@@ -1109,6 +1110,7 @@
                 gtv.onTaskListVisibilityChanged(false);
                 removeView(gtv);
             }
+            mSplitBoundsConfig = null;
         }
         updateLocusId();
     }
@@ -2161,7 +2163,7 @@
      * All subsequent calls to reload will keep the task as the first item until {@link #reset()}
      * is called.  Also scrolls the view to this task.
      */
-    public void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
+    private void showCurrentTask(RunningTaskInfo[] runningTaskInfo) {
         int runningTaskViewId = -1;
         boolean needGroupTaskView = runningTaskInfo.length > 1;
         RunningTaskInfo taskInfo = runningTaskInfo[0];
@@ -3134,7 +3136,7 @@
                         }
                     }
                 }
-                updateFocusedSplitButtonVisibility();
+                updateCurrentTaskActionsVisibility();
                 onDismissAnimationEnds();
                 mPendingAnimation = null;
             }
@@ -3143,16 +3145,19 @@
     }
 
     /**
-     * Shows split button if
-     * * We're in large screen
-     * * We're not already in split
+     * Hides all overview actions if current page is for split apps, shows otherwise
+     * If actions are showing, we only show split option if
+     * * Device is large screen
      * * There are at least 2 tasks to invoke split
      */
-    private void updateFocusedSplitButtonVisibility() {
-        mActionsView.setSplitButtonVisible(mActivity.getDeviceProfile().isTablet &&
-                !(getFocusedTaskView() instanceof GroupedTaskView) &&
-                getTaskViewCount() > 1
-        );
+    private void updateCurrentTaskActionsVisibility() {
+        boolean isCurrentSplit = getCurrentPageTaskView() instanceof GroupedTaskView;
+        mActionsView.updateHiddenFlags(HIDDEN_SPLIT_SCREEN, isCurrentSplit);
+        if (isCurrentSplit) {
+            return;
+        }
+        mActionsView.setSplitButtonVisible(
+                mActivity.getDeviceProfile().isTablet && getTaskViewCount() > 1);
     }
 
     /**
@@ -4174,7 +4179,7 @@
     @Override
     protected void notifyPageSwitchListener(int prevPage) {
         super.notifyPageSwitchListener(prevPage);
-        updateFocusedSplitButtonVisibility();
+        updateCurrentTaskActionsVisibility();
         loadVisibleTaskData(TaskView.FLAG_UPDATE_ALL);
         updateEnabledOverlays();
     }
@@ -4260,6 +4265,14 @@
         RemoteTargetGluer gluer = new RemoteTargetGluer(getContext(), getSizeStrategy());
         mRemoteTargetHandles = gluer.assignTargetsForSplitScreen(recentsAnimationTargets);
         mSplitBoundsConfig = gluer.getStagedSplitBounds();
+        TaskView runningTaskView = getRunningTaskView();
+        if (runningTaskView instanceof GroupedTaskView) {
+            // We initially create a GroupedTaskView in showCurrentTask() before launcher even
+            // receives the leashes for the remote apps, so the mSplitBoundsConfig that gets passed
+            // in there is either null or outdated, so we need to update here as soon as we're
+            // notified.
+            ((GroupedTaskView) runningTaskView).updateSplitBoundsConfig(mSplitBoundsConfig);
+        }
         for (RemoteTargetHandle remoteTargetHandle : mRemoteTargetHandles) {
             TaskViewSimulator tvs = remoteTargetHandle.getTaskViewSimulator();
             tvs.setOrientationState(mOrientationState);
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index 7c558c2..461a89b 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -374,7 +374,7 @@
 
     protected Task mTask;
     protected TaskThumbnailView mSnapshotView;
-    private IconView mIconView;
+    protected IconView mIconView;
     private final DigitalWellBeingToast mDigitalWellBeingToast;
     private float mFullscreenProgress;
     private float mGridProgress;
@@ -492,7 +492,7 @@
      */
     public boolean offerTouchToChildren(MotionEvent event) {
         if (event.getAction() == MotionEvent.ACTION_DOWN) {
-            computeAndSetIconTouchDelegate();
+            computeAndSetIconTouchDelegate(mIconView, mIconCenterCoords, mIconTouchDelegate);
             computeAndSetChipTouchDelegate();
         }
         if (mIconTouchDelegate != null && mIconTouchDelegate.onTouchEvent(event)) {
@@ -504,16 +504,17 @@
         return false;
     }
 
-    private void computeAndSetIconTouchDelegate() {
-        float iconHalfSize = mIconView.getWidth() / 2f;
-        mIconCenterCoords[0] = mIconCenterCoords[1] = iconHalfSize;
-        getDescendantCoordRelativeToAncestor(mIconView, mActivity.getDragLayer(), mIconCenterCoords,
+    protected void computeAndSetIconTouchDelegate(IconView iconView, float[] tempCenterCoords,
+            TransformingTouchDelegate transformingTouchDelegate) {
+        float iconHalfSize = iconView.getWidth() / 2f;
+        tempCenterCoords[0] = tempCenterCoords[1] = iconHalfSize;
+        getDescendantCoordRelativeToAncestor(iconView, mActivity.getDragLayer(), tempCenterCoords,
                 false);
-        mIconTouchDelegate.setBounds(
-                (int) (mIconCenterCoords[0] - iconHalfSize),
-                (int) (mIconCenterCoords[1] - iconHalfSize),
-                (int) (mIconCenterCoords[0] + iconHalfSize),
-                (int) (mIconCenterCoords[1] + iconHalfSize));
+        transformingTouchDelegate.setBounds(
+                (int) (tempCenterCoords[0] - iconHalfSize),
+                (int) (tempCenterCoords[1] - iconHalfSize),
+                (int) (tempCenterCoords[0] + iconHalfSize),
+                (int) (tempCenterCoords[1] + iconHalfSize));
     }
 
     private void computeAndSetChipTouchDelegate() {
@@ -792,7 +793,7 @@
             if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
                 mIconLoadRequest = iconCache.updateIconInBackground(mTask,
                         (task) -> {
-                            setIcon(task.icon);
+                            setIcon(mIconView, task.icon);
                             mDigitalWellBeingToast.initialize(mTask);
                         });
             }
@@ -804,7 +805,7 @@
                 mTask.thumbnail = null;
             }
             if (needsUpdate(changes, FLAG_UPDATE_ICON)) {
-                setIcon(null);
+                setIcon(mIconView, null);
             }
         }
     }
@@ -840,10 +841,10 @@
         }
     }
 
-    private void setIcon(Drawable icon) {
+    protected void setIcon(IconView iconView, Drawable icon) {
         if (icon != null) {
-            mIconView.setDrawable(icon);
-            mIconView.setOnClickListener(v -> {
+            iconView.setDrawable(icon);
+            iconView.setOnClickListener(v -> {
                 if (ENABLE_QUICKSTEP_LIVE_TILE.get() && isRunningTask()) {
                     RecentsView recentsView = getRecentsView();
                     recentsView.switchToScreenshot(
@@ -854,14 +855,14 @@
                     showTaskMenu();
                 }
             });
-            mIconView.setOnLongClickListener(v -> {
+            iconView.setOnLongClickListener(v -> {
                 requestDisallowInterceptTouchEvent(true);
                 return showTaskMenu();
             });
         } else {
-            mIconView.setDrawable(null);
-            mIconView.setOnClickListener(null);
-            mIconView.setOnLongClickListener(null);
+            iconView.setDrawable(null);
+            iconView.setOnClickListener(null);
+            iconView.setOnLongClickListener(null);
         }
     }
 
@@ -877,32 +878,8 @@
                 : deviceProfile.overviewTaskMarginPx;
         int taskIconMargin = snapshotParams.topMargin - taskIconHeight - taskMargin;
         LayoutParams iconParams = (LayoutParams) mIconView.getLayoutParams();
-        switch (orientationHandler.getRotation()) {
-            case ROTATION_90:
-                iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
-                iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2;
-                iconParams.leftMargin = 0;
-                iconParams.topMargin = snapshotParams.topMargin / 2;
-                break;
-            case ROTATION_180:
-                iconParams.gravity = BOTTOM | CENTER_HORIZONTAL;
-                iconParams.bottomMargin = -snapshotParams.topMargin;
-                iconParams.leftMargin = iconParams.rightMargin = 0;
-                iconParams.topMargin = taskIconMargin;
-                break;
-            case ROTATION_270:
-                iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
-                iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2;
-                iconParams.rightMargin = 0;
-                iconParams.topMargin = snapshotParams.topMargin / 2;
-                break;
-            case Surface.ROTATION_0:
-            default:
-                iconParams.gravity = TOP | CENTER_HORIZONTAL;
-                iconParams.leftMargin = iconParams.rightMargin = 0;
-                iconParams.topMargin = taskIconMargin;
-                break;
-        }
+        orientationHandler.setIconAndSnapshotParams(mIconView, taskIconMargin, taskIconHeight,
+                snapshotParams, isRtl);
         mSnapshotView.setLayoutParams(snapshotParams);
         iconParams.width = iconParams.height = taskIconHeight;
         mIconView.setLayoutParams(iconParams);
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 2ac6cea..0c3ad1d 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -16,6 +16,10 @@
 
 package com.android.launcher3.touch;
 
+import static android.view.Gravity.CENTER_VERTICAL;
+import static android.view.Gravity.END;
+import static android.view.Gravity.START;
+import static android.view.Gravity.TOP;
 import static android.widget.ListPopupWindow.WRAP_CONTENT;
 
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
@@ -36,8 +40,8 @@
 import android.view.Surface;
 import android.view.VelocityTracker;
 import android.view.View;
-import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
+import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
 import com.android.launcher3.DeviceProfile;
@@ -46,6 +50,7 @@
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
+import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
 import com.android.launcher3.views.BaseDragLayer;
 
 import java.util.Collections;
@@ -223,11 +228,6 @@
     }
 
     @Override
-    public float getChildStartWithTranslation(View view) {
-        return view.getTop() + view.getTranslationY();
-    }
-
-    @Override
     public int getCenterForPage(View view, Rect insets) {
         return (view.getPaddingLeft() + view.getMeasuredWidth() + insets.left
             - insets.right - view.getPaddingRight()) / 2;
@@ -243,11 +243,6 @@
         return view.getHeight() - view.getPaddingBottom() - insets.bottom;
     }
 
-    @Override
-    public int getPrimaryTranslationDirectionFactor() {
-        return -1;
-    }
-
     public int getSecondaryTranslationDirectionFactor() {
         return 1;
     }
@@ -262,11 +257,6 @@
     }
 
     @Override
-    public int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp) {
-        return translationOffset;
-    }
-
-    @Override
     public float getTaskMenuX(float x, View thumbnailView, int overScroll) {
         return thumbnailView.getMeasuredWidth() + x;
     }
@@ -386,7 +376,7 @@
 
     @Override
     public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
-            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+            StagedSplitBounds splitInfo, int desiredStagePosition) {
         float diff;
         float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f;
         if (desiredStagePosition == SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT) {
@@ -400,7 +390,7 @@
 
     @Override
     public void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
-            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+            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.visualDividerBounds.width();
@@ -419,8 +409,10 @@
         int secondarySnapshotHeight;
         int secondarySnapshotWidth;
 
+        float taskPercent = splitBoundsConfig.appsStackedVertically ?
+                splitBoundsConfig.topTaskPercent : splitBoundsConfig.leftTaskPercent;
         primarySnapshotWidth = parentWidth;
-        primarySnapshotHeight = (int) (totalThumbnailHeight * splitBoundsConfig.leftTaskPercent);
+        primarySnapshotHeight = (int) (totalThumbnailHeight * taskPercent);
 
         secondarySnapshotWidth = parentWidth;
         secondarySnapshotHeight = totalThumbnailHeight - primarySnapshotHeight - dividerBar;
@@ -435,6 +427,38 @@
     }
 
     @Override
+    public void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
+            FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
+        FrameLayout.LayoutParams iconParams =
+                (FrameLayout.LayoutParams) iconView.getLayoutParams();
+        iconParams.gravity = (isRtl ? START : END) | CENTER_VERTICAL;
+        iconParams.rightMargin = -taskIconHeight - taskIconMargin / 2;
+        iconParams.leftMargin = 0;
+        iconParams.topMargin = snapshotParams.topMargin / 2;
+    }
+
+    @Override
+    public void setSplitIconParams(View primaryIconView, View secondaryIconView,
+            int taskIconHeight, Rect primarySnapshotBounds, Rect secondarySnapshotBounds,
+            boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+        FrameLayout.LayoutParams primaryIconParams =
+                (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
+        FrameLayout.LayoutParams secondaryIconParams =
+                new FrameLayout.LayoutParams(primaryIconParams);
+
+        int primaryHeight = primarySnapshotBounds.height();
+        int secondaryHeight = secondarySnapshotBounds.height();
+        primaryIconParams.gravity = (isRtl ? START : END) | TOP;
+        primaryIconView.setTranslationY((primaryHeight + taskIconHeight) / 2f );
+
+        secondaryIconParams.gravity = (isRtl ? START : END) | TOP;
+        secondaryIconView.setTranslationY(primaryHeight
+                + ((secondaryHeight + taskIconHeight) / 2f));
+        primaryIconView.setLayoutParams(primaryIconParams);
+        secondaryIconView.setLayoutParams(secondaryIconParams);
+    }
+
+    @Override
     public int getDefaultSplitPosition(DeviceProfile deviceProfile) {
         throw new IllegalStateException("Default position not available in fake landscape");
     }
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index b119e2c..494fe22 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -29,12 +29,14 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
+import android.widget.FrameLayout;
 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;
+import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
 
 import java.util.List;
 
@@ -88,14 +90,11 @@
     int getPrimaryScroll(View view);
     float getPrimaryScale(View view);
     int getChildStart(View view);
-    float getChildStartWithTranslation(View view);
     int getCenterForPage(View view, Rect insets);
     int getScrollOffsetStart(View view, Rect insets);
     int getScrollOffsetEnd(View view, Rect insets);
-    int getPrimaryTranslationDirectionFactor();
     int getSecondaryTranslationDirectionFactor();
     int getSplitTranslationDirectionFactor(@StagePosition int stagePosition);
-    int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp);
     ChildBounds getChildBounds(View child, int childStart, int pageCenter, boolean layoutChild);
     void setMaxScroll(AccessibilityEvent event, int maxScroll);
     boolean getRecentsRtlSetting(Resources resources);
@@ -144,12 +143,12 @@
      *                           outRect for
      */
     void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
-            SplitConfigurationOptions.StagedSplitBounds splitInfo,
+            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
+     * 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.
      *
@@ -159,7 +158,7 @@
      * usual Y
      */
     void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
-            SplitConfigurationOptions.StagedSplitBounds splitInfo,
+            StagedSplitBounds splitInfo,
             @SplitConfigurationOptions.StagePosition int desiredStagePosition);
 
     void measureGroupedTaskViewThumbnailBounds(View primarySnapshot, View secondarySnapshot,
@@ -167,6 +166,11 @@
             SplitConfigurationOptions.StagedSplitBounds splitBoundsConfig, DeviceProfile dp);
 
     // Overview TaskMenuView methods
+    void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
+            FrameLayout.LayoutParams snapshotParams, boolean isRtl);
+    void setSplitIconParams(View primaryIconView, View secondaryIconView,
+            int taskIconHeight, Rect primarySnapshotBounds, Rect secondarySnapshotBounds,
+            boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
     float getTaskMenuX(float x, View thumbnailView, int overScroll);
     float getTaskMenuY(float y, View thumbnailView, int overScroll);
     int getTaskMenuWidth(View view);
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 99ad050..a453cae 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -16,6 +16,11 @@
 
 package com.android.launcher3.touch;
 
+import static android.view.Gravity.BOTTOM;
+import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.Gravity.START;
+import static android.view.Gravity.TOP;
+
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
 import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
@@ -36,6 +41,7 @@
 import android.view.VelocityTracker;
 import android.view.View;
 import android.view.accessibility.AccessibilityEvent;
+import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
 import com.android.launcher3.DeviceProfile;
@@ -44,6 +50,7 @@
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.util.SplitConfigurationOptions.StagePosition;
+import com.android.launcher3.util.SplitConfigurationOptions.StagedSplitBounds;
 import com.android.launcher3.views.BaseDragLayer;
 
 import java.util.ArrayList;
@@ -228,11 +235,6 @@
     }
 
     @Override
-    public float getChildStartWithTranslation(View view) {
-        return view.getLeft() + view.getTranslationX();
-    }
-
-    @Override
     public int getCenterForPage(View view, Rect insets) {
         return (view.getPaddingTop() + view.getMeasuredHeight() + insets.top
             - insets.bottom - view.getPaddingBottom()) / 2;
@@ -248,11 +250,6 @@
         return view.getWidth() - view.getPaddingRight() - insets.right;
     }
 
-    @Override
-    public int getPrimaryTranslationDirectionFactor() {
-        return 1;
-    }
-
     public int getSecondaryTranslationDirectionFactor() {
         return -1;
     }
@@ -267,14 +264,6 @@
     }
 
     @Override
-    public int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp) {
-        if (dp.isLandscape) {
-            return translationOffset;
-        }
-        return 0;
-    }
-
-    @Override
     public float getTaskMenuX(float x, View thumbnailView, int overScroll) {
         return x + overScroll;
     }
@@ -471,7 +460,7 @@
 
     @Override
     public void setSplitTaskSwipeRect(DeviceProfile dp, Rect outRect,
-            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+            StagedSplitBounds splitInfo, int desiredStagePosition) {
         boolean isLandscape = dp.isLandscape;
         float verticalDividerDiff = splitInfo.visualDividerBounds.height() / 2f;
         float horizontalDividerDiff = splitInfo.visualDividerBounds.width() / 2f;
@@ -497,7 +486,7 @@
 
     @Override
     public void setLeashSplitOffset(Point splitOffset, DeviceProfile dp,
-            SplitConfigurationOptions.StagedSplitBounds splitInfo, int desiredStagePosition) {
+            StagedSplitBounds splitInfo, int desiredStagePosition) {
         if (desiredStagePosition == STAGE_POSITION_BOTTOM_OR_RIGHT) {
             if (dp.isLandscape) {
                 splitOffset.x = splitInfo.leftTopBounds.width() +
@@ -555,6 +544,46 @@
     }
 
     @Override
+    public void setIconAndSnapshotParams(View iconView, int taskIconMargin, int taskIconHeight,
+            FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
+        FrameLayout.LayoutParams iconParams =
+                (FrameLayout.LayoutParams) iconView.getLayoutParams();
+        iconParams.gravity = TOP | CENTER_HORIZONTAL;
+        iconParams.leftMargin = iconParams.rightMargin = 0;
+        iconParams.topMargin = taskIconMargin;
+    }
+
+    @Override
+    public void setSplitIconParams(View primaryIconView, View secondaryIconView,
+            int taskIconHeight, Rect primarySnapshotBounds, Rect secondarySnapshotBounds,
+            boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+        FrameLayout.LayoutParams primaryIconParams =
+                (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
+        FrameLayout.LayoutParams secondaryIconParams =
+                new FrameLayout.LayoutParams(primaryIconParams);
+
+        if (deviceProfile.isLandscape) {
+            int primaryWidth = primarySnapshotBounds.width();
+            int secondaryWidth = secondarySnapshotBounds.width();
+            primaryIconParams.gravity = TOP | START;
+            primaryIconView.setTranslationX((primaryWidth - taskIconHeight) / 2f );
+
+            secondaryIconParams.gravity = TOP | START;
+            secondaryIconView.setTranslationX(primaryWidth
+                    + ((secondaryWidth - taskIconHeight) / 2f));
+        } else {
+            primaryIconView.setTranslationX(0);
+            secondaryIconView.setTranslationX(0);
+            primaryIconView.setTranslationY(0);
+            secondaryIconView.setTranslationY(0);
+            secondaryIconParams.gravity = BOTTOM | CENTER_HORIZONTAL;
+            secondaryIconParams.bottomMargin = -(secondaryIconParams.topMargin + taskIconHeight);
+        }
+        primaryIconView.setLayoutParams(primaryIconParams);
+        secondaryIconView.setLayoutParams(secondaryIconParams);
+    }
+
+    @Override
     public int getDefaultSplitPosition(DeviceProfile deviceProfile) {
         if (!deviceProfile.isTablet) {
             throw new IllegalStateException("Default position available only for large screens");
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index 91d44bd..4f33ff0 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -16,6 +16,10 @@
 
 package com.android.launcher3.touch;
 
+import static android.view.Gravity.CENTER_VERTICAL;
+import static android.view.Gravity.END;
+import static android.view.Gravity.START;
+
 import static com.android.launcher3.touch.SingleAxisSwipeDetector.HORIZONTAL;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT;
 import static com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT;
@@ -26,6 +30,7 @@
 import android.graphics.Rect;
 import android.view.Surface;
 import android.view.View;
+import android.widget.FrameLayout;
 import android.widget.LinearLayout;
 
 import com.android.launcher3.DeviceProfile;
@@ -54,11 +59,6 @@
     }
 
     @Override
-    public int getSplitAnimationTranslation(int translationOffset, DeviceProfile dp) {
-        return translationOffset;
-    }
-
-    @Override
     public boolean getRecentsRtlSetting(Resources resources) {
         return Utilities.isRtl(resources);
     }
@@ -114,6 +114,17 @@
                 STAGE_POSITION_TOP_OR_LEFT, STAGE_TYPE_MAIN));
     }
 
+    @Override
+    public void setIconAndSnapshotParams(View mIconView, int taskIconMargin, int taskIconHeight,
+            FrameLayout.LayoutParams snapshotParams, boolean isRtl) {
+        FrameLayout.LayoutParams iconParams =
+                (FrameLayout.LayoutParams) mIconView.getLayoutParams();
+        iconParams.gravity = (isRtl ? END : START) | CENTER_VERTICAL;
+        iconParams.leftMargin = -taskIconHeight - taskIconMargin / 2;
+        iconParams.rightMargin = 0;
+        iconParams.topMargin = snapshotParams.topMargin / 2;
+    }
+
     /* ---------- The following are only used by TaskViewTouchHandler. ---------- */
 
     @Override