Merge "Fix paired icon placement in landscape/seascape" into tm-dev
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index d9f668d..b9615ab 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -271,7 +271,8 @@
 
         getPagedOrientationHandler().setSplitIconParams(mIconView, mIconView2,
                 taskIconHeight, mSnapshotView.getMeasuredWidth(), mSnapshotView.getMeasuredHeight(),
-                isRtl, deviceProfile, mSplitBoundsConfig);
+                getMeasuredHeight(), getMeasuredWidth(), isRtl, deviceProfile,
+                mSplitBoundsConfig);
     }
 
     private void updateSecondaryDwbPlacement() {
diff --git a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
index 2609e54..d1f54ce 100644
--- a/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/LandscapePagedViewHandler.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3.touch;
 
+import static android.view.Gravity.BOTTOM;
 import static android.view.Gravity.CENTER_VERTICAL;
 import static android.view.Gravity.END;
 import static android.view.Gravity.START;
@@ -468,18 +469,42 @@
     @Override
     public void setSplitIconParams(View primaryIconView, View secondaryIconView,
             int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
-            boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+            DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
         FrameLayout.LayoutParams primaryIconParams =
                 (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
         FrameLayout.LayoutParams secondaryIconParams =
                 new FrameLayout.LayoutParams(primaryIconParams);
 
-        primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
+        // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+        // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+        // It is usually not exactly 50/50, due to insets/screen cutouts.
+        int fullscreenInsetThickness = deviceProfile.getInsets().top;
+        int fullscreenMidpointFromBottom = ((deviceProfile.heightPx - fullscreenInsetThickness)
+                / 2);
+        float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
+        float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
+        int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
+        int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
+        int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
+        int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+        primaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
+        secondaryIconParams.gravity = BOTTOM | (isRtl ? START : END);
         primaryIconView.setTranslationX(0);
-        primaryIconView.setTranslationY(-(taskIconHeight / 2f));
-        secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? START : END);
         secondaryIconView.setTranslationX(0);
-        secondaryIconView.setTranslationY(taskIconHeight / 2f);
+        if (splitConfig.initiatedFromSeascape) {
+            // if the split was initiated from seascape,
+            // the task on the right (secondary) is slightly larger
+            primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
+            secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
+                    + taskIconHeight);
+        } else {
+            // if not,
+            // the task on the left (primary) is slightly larger
+            primaryIconView.setTranslationY(-bottomToMidpointOffset);
+            secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
+        }
 
         primaryIconView.setLayoutParams(primaryIconParams);
         secondaryIconView.setLayoutParams(secondaryIconParams);
diff --git a/src/com/android/launcher3/touch/PagedOrientationHandler.java b/src/com/android/launcher3/touch/PagedOrientationHandler.java
index 6e594e9..1b17126 100644
--- a/src/com/android/launcher3/touch/PagedOrientationHandler.java
+++ b/src/com/android/launcher3/touch/PagedOrientationHandler.java
@@ -146,7 +146,8 @@
             int taskIconMargin, int taskIconHeight, int thumbnailTopMargin, boolean isRtl);
     void setSplitIconParams(View primaryIconView, View secondaryIconView,
             int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
-            boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
+            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+            DeviceProfile deviceProfile, StagedSplitBounds splitConfig);
 
     /*
      * The following two methods try to center the TaskMenuView in landscape by finding the center
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 926946b..88c3bfe 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -18,6 +18,7 @@
 
 import static android.view.Gravity.BOTTOM;
 import static android.view.Gravity.CENTER_HORIZONTAL;
+import static android.view.Gravity.END;
 import static android.view.Gravity.START;
 import static android.view.Gravity.TOP;
 import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
@@ -565,18 +566,70 @@
     @Override
     public void setSplitIconParams(View primaryIconView, View secondaryIconView,
             int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
-            boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+            DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
         FrameLayout.LayoutParams primaryIconParams =
                 (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
         FrameLayout.LayoutParams secondaryIconParams =
                 new FrameLayout.LayoutParams(primaryIconParams);
 
-        primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
-        // shifts icon half a width left (height is used conveniently here since icons are square)
-        primaryIconView.setTranslationX(-(taskIconHeight / 2f));
+        if (deviceProfile.isLandscape) {
+            // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+            // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+            // It is usually not exactly 50/50, due to insets/screen cutouts.
+            int fullscreenInsetThickness = deviceProfile.isSeascape()
+                    ? deviceProfile.getInsets().right
+                    : deviceProfile.getInsets().left;
+            int fullscreenMidpointFromBottom = ((deviceProfile.widthPx
+                    - fullscreenInsetThickness) / 2);
+            float midpointFromBottomPct = (float) fullscreenMidpointFromBottom
+                    / deviceProfile.widthPx;
+            float insetPct = (float) fullscreenInsetThickness / deviceProfile.widthPx;
+            int spaceAboveSnapshots = 0;
+            int overviewThumbnailAreaThickness = groupedTaskViewWidth - spaceAboveSnapshots;
+            int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness
+                    * midpointFromBottomPct);
+            int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+            if (deviceProfile.isSeascape()) {
+                primaryIconParams.gravity = TOP | (isRtl ? END : START);
+                secondaryIconParams.gravity = TOP | (isRtl ? END : START);
+                if (splitConfig.initiatedFromSeascape) {
+                    // if the split was initiated from seascape,
+                    // the task on the right (secondary) is slightly larger
+                    primaryIconView.setTranslationX(bottomToMidpointOffset - taskIconHeight);
+                    secondaryIconView.setTranslationX(bottomToMidpointOffset);
+                } else {
+                    // if not,
+                    // the task on the left (primary) is slightly larger
+                    primaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset
+                            - taskIconHeight);
+                    secondaryIconView.setTranslationX(bottomToMidpointOffset + insetOffset);
+                }
+            } else {
+                primaryIconParams.gravity = TOP | (isRtl ? START : END);
+                secondaryIconParams.gravity = TOP | (isRtl ? START : END);
+                if (!splitConfig.initiatedFromSeascape) {
+                    // if the split was initiated from landscape,
+                    // the task on the left (primary) is slightly larger
+                    primaryIconView.setTranslationX(-bottomToMidpointOffset);
+                    secondaryIconView.setTranslationX(-bottomToMidpointOffset + taskIconHeight);
+                } else {
+                    // if not,
+                    // the task on the right (secondary) is slightly larger
+                    primaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset);
+                    secondaryIconView.setTranslationX(-bottomToMidpointOffset - insetOffset
+                            + taskIconHeight);
+                }
+            }
+        } else {
+            primaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
+            // shifts icon half a width left (height is used here since icons are square)
+            primaryIconView.setTranslationX(-(taskIconHeight / 2f));
+            secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
+            secondaryIconView.setTranslationX(taskIconHeight / 2f);
+        }
         primaryIconView.setTranslationY(0);
-        secondaryIconParams.gravity = TOP | CENTER_HORIZONTAL;
-        secondaryIconView.setTranslationX(taskIconHeight / 2f);
         secondaryIconView.setTranslationY(0);
 
         primaryIconView.setLayoutParams(primaryIconParams);
diff --git a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
index 9151796..74b6a5b 100644
--- a/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
+++ b/src/com/android/launcher3/touch/SeascapePagedViewHandler.java
@@ -178,16 +178,46 @@
     @Override
     public void setSplitIconParams(View primaryIconView, View secondaryIconView,
             int taskIconHeight, int primarySnapshotWidth, int primarySnapshotHeight,
-            boolean isRtl, DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
+            int groupedTaskViewHeight, int groupedTaskViewWidth, boolean isRtl,
+            DeviceProfile deviceProfile, StagedSplitBounds splitConfig) {
         super.setSplitIconParams(primaryIconView, secondaryIconView, taskIconHeight,
-                primarySnapshotWidth, primarySnapshotHeight, isRtl, deviceProfile, splitConfig);
+                primarySnapshotWidth, primarySnapshotHeight, groupedTaskViewHeight,
+                groupedTaskViewWidth, isRtl, deviceProfile, splitConfig);
         FrameLayout.LayoutParams primaryIconParams =
                 (FrameLayout.LayoutParams) primaryIconView.getLayoutParams();
         FrameLayout.LayoutParams secondaryIconParams =
                 (FrameLayout.LayoutParams) secondaryIconView.getLayoutParams();
 
-        primaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
-        secondaryIconParams.gravity = CENTER_VERTICAL | (isRtl ? END : START);
+        // We calculate the "midpoint" of the thumbnail area, and place the icons there.
+        // This is the place where the thumbnail area splits by default, in a near-50/50 split.
+        // It is usually not exactly 50/50, due to insets/screen cutouts.
+        int fullscreenInsetThickness = deviceProfile.getInsets().top;
+        int fullscreenMidpointFromBottom = ((deviceProfile.heightPx
+                - fullscreenInsetThickness) / 2);
+        float midpointFromBottomPct = (float) fullscreenMidpointFromBottom / deviceProfile.heightPx;
+        float insetPct = (float) fullscreenInsetThickness / deviceProfile.heightPx;
+        int spaceAboveSnapshots = deviceProfile.overviewTaskThumbnailTopMarginPx;
+        int overviewThumbnailAreaThickness = groupedTaskViewHeight - spaceAboveSnapshots;
+        int bottomToMidpointOffset = (int) (overviewThumbnailAreaThickness * midpointFromBottomPct);
+        int insetOffset = (int) (overviewThumbnailAreaThickness * insetPct);
+
+        primaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
+        secondaryIconParams.gravity = BOTTOM | (isRtl ? END : START);
+        primaryIconView.setTranslationX(0);
+        secondaryIconView.setTranslationX(0);
+        if (splitConfig.initiatedFromSeascape) {
+            // if the split was initiated from seascape,
+            // the task on the right (secondary) is slightly larger
+            primaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset);
+            secondaryIconView.setTranslationY(-bottomToMidpointOffset - insetOffset
+                    + taskIconHeight);
+        } else {
+            // if not,
+            // the task on the left (primary) is slightly larger
+            primaryIconView.setTranslationY(-bottomToMidpointOffset);
+            secondaryIconView.setTranslationY(-bottomToMidpointOffset + taskIconHeight);
+        }
+
         primaryIconView.setLayoutParams(primaryIconParams);
         secondaryIconView.setLayoutParams(secondaryIconParams);
     }
diff --git a/src/com/android/launcher3/util/SplitConfigurationOptions.java b/src/com/android/launcher3/util/SplitConfigurationOptions.java
index cb714b2..b40493a 100644
--- a/src/com/android/launcher3/util/SplitConfigurationOptions.java
+++ b/src/com/android/launcher3/util/SplitConfigurationOptions.java
@@ -113,6 +113,14 @@
          * the bounds were originally in
          */
         public final boolean appsStackedVertically;
+        /**
+         * If {@code true}, that means at the time of creation of this object, the phone was in
+         * seascape orientation. This is important on devices with insets, because they do not split
+         * evenly -- one of the insets must be slightly larger to account for the inset.
+         * From landscape, it is the leftTop task that expands slightly.
+         * From seascape, it is the rightBottom task that expands slightly.
+         */
+        public final boolean initiatedFromSeascape;
         public final int leftTopTaskId;
         public final int rightBottomTaskId;
 
@@ -128,11 +136,22 @@
                 this.visualDividerBounds = new Rect(leftTopBounds.left, leftTopBounds.bottom,
                         leftTopBounds.right, rightBottomBounds.top);
                 appsStackedVertically = true;
+                initiatedFromSeascape = false;
             } else {
                 // horizontal apps, vertical divider
                 this.visualDividerBounds = new Rect(leftTopBounds.right, leftTopBounds.top,
                         rightBottomBounds.left, leftTopBounds.bottom);
                 appsStackedVertically = false;
+                // The following check is unreliable on devices without insets
+                // (initiatedFromSeascape will always be set to false.) This happens to be OK for
+                // all our current uses, but should be refactored.
+                // TODO: Create a more reliable check, or refactor how splitting works on devices
+                //  with insets.
+                if (rightBottomBounds.width() > leftTopBounds.width()) {
+                    initiatedFromSeascape = true;
+                } else {
+                    initiatedFromSeascape = false;
+                }
             }
 
             leftTaskPercent = this.leftTopBounds.width() / (float) rightBottomBounds.right;