2D Recents: Always use grid layout even in split view

Simplify the logic a bit, and polish the algorithm to accommodate the
various layout possibilities.

Bug: 32101881
Test: Checked layout in all orientations, with and without split view
Change-Id: I4a6dd3f7f34664908294ddaf5ea516d8e258edbf
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
index 6cf5d10..86f61e9 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsImpl.java
@@ -201,8 +201,6 @@
         Resources res = mContext.getResources();
         reloadResources();
         mDummyStackView.reloadOnConfigurationChange();
-        mDummyStackView.getStackAlgorithm().getGridState().setHasDockedTasks(
-            Recents.getSystemServices().hasDockedTask());
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
index f46de5f..3fa6d75 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackLayoutAlgorithm.java
@@ -214,38 +214,10 @@
     }
 
     /**
-     * The state telling the algorithm whether to use grid layout or not.
+     * @return True if we should use the grid layout.
      */
-    public static class GridState {
-        private boolean mDraggingOverDockedState;
-        private boolean mHasDockedTask;
-
-        private GridState() {
-            mDraggingOverDockedState = false;
-            mHasDockedTask = false;
-        }
-
-        /**
-         * Check whether we should use the grid layout.
-         * We use the grid layout for Recents iff all the following is true:
-         *  1. Grid-mode is enabled.
-         *  2. The activity is not in split screen mode (there's no docked task).
-         *  3. The user is not dragging a task view over the dock state.
-         * @return True if we should use the grid layout.
-         */
-        boolean useGridLayout() {
-            return Recents.getConfiguration().isGridEnabled &&
-                !mDraggingOverDockedState &&
-                !mHasDockedTask;
-        }
-
-        public void setDragging(boolean draggingOverDockedState) {
-            mDraggingOverDockedState = draggingOverDockedState;
-        }
-
-        public void setHasDockedTasks(boolean hasDockedTask) {
-            mHasDockedTask = hasDockedTask;
-        }
+    boolean useGridLayout() {
+        return Recents.getConfiguration().isGridEnabled;
     }
 
     // A report of the visibility state of the stack
@@ -262,7 +234,6 @@
 
     Context mContext;
     private StackState mState = StackState.SPLIT;
-    private GridState mGridState = new GridState();
     private TaskStackLayoutAlgorithmCallbacks mCb;
 
     // The task bounds (untransformed) for layout.  This rect is anchored at mTaskRoot.
@@ -517,7 +488,7 @@
         }
 
         // Initialize the grid layout
-        mTaskGridLayoutAlgorithm.initialize(displayRect, windowRect);
+        mTaskGridLayoutAlgorithm.initialize(windowRect);
     }
 
     /**
@@ -770,7 +741,7 @@
     }
 
     public Rect getStackActionButtonRect() {
-        return mGridState.useGridLayout()
+        return useGridLayout()
                 ? mTaskGridLayoutAlgorithm.getStackActionButtonRect() : mStackActionButtonRect;
     }
 
@@ -796,13 +767,6 @@
     }
 
     /**
-     * Returns the current grid layout state.
-     */
-    public GridState getGridState() {
-        return mGridState;
-    }
-
-    /**
      * Returns whether this stack layout has been initialized.
      */
     public boolean isInitialized() {
@@ -903,7 +867,7 @@
         if (mFreeformLayoutAlgorithm.isTransformAvailable(task, this)) {
             mFreeformLayoutAlgorithm.getTransform(task, transformOut, this);
             return transformOut;
-        } else if (mGridState.useGridLayout()) {
+        } else if (useGridLayout()) {
             int taskIndex = mTaskIndexMap.get(task.key.id);
             int taskCount = mTaskIndexMap.size();
             mTaskGridLayoutAlgorithm.getTransform(taskIndex, taskCount, transformOut, this);
@@ -1324,7 +1288,7 @@
      * Returns the proper task rectangle according to the current grid state.
      */
     public Rect getTaskRect() {
-        return mGridState.useGridLayout() ? mTaskGridLayoutAlgorithm.getTaskGridRect() : mTaskRect;
+        return useGridLayout() ? mTaskGridLayoutAlgorithm.getTaskGridRect() : mTaskRect;
     }
 
     public void dump(String prefix, PrintWriter writer) {
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 0bfdb2b3..87a6846 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -1858,7 +1858,6 @@
                 Interpolators.FAST_OUT_SLOW_IN);
         boolean ignoreTaskOverrides = false;
         if (event.dropTarget instanceof TaskStack.DockState) {
-            mLayoutAlgorithm.getGridState().setDragging(true);
             // Calculate the new task stack bounds that matches the window size that Recents will
             // have after the drop
             final TaskStack.DockState dockState = (TaskStack.DockState) event.dropTarget;
@@ -1878,7 +1877,6 @@
             updateLayoutAlgorithm(true /* boundScroll */);
             ignoreTaskOverrides = true;
         } else {
-            mLayoutAlgorithm.getGridState().setDragging(false);
             // Restore the pre-drag task stack bounds, but ensure that we don't layout the dragging
             // task view, so add it back to the ignore set after updating the layout
             removeIgnoreTask(event.task);
@@ -1889,7 +1887,6 @@
     }
 
     public final void onBusEvent(final DragEndEvent event) {
-        mLayoutAlgorithm.getGridState().setDragging(false);
         // We don't handle drops on the dock regions
         if (event.dropTarget instanceof TaskStack.DockState) {
             // However, we do need to reset the overrides, since the last state of this task stack
@@ -2081,8 +2078,6 @@
         mLayoutAlgorithm.reloadOnConfigurationChange(getContext());
 
         boolean hasDockedTask = Recents.getSystemServices().hasDockedTask();
-        mStableLayoutAlgorithm.getGridState().setHasDockedTasks(hasDockedTask);
-        mLayoutAlgorithm.getGridState().setHasDockedTasks(hasDockedTask);
     }
 
     /**
@@ -2139,7 +2134,7 @@
      * Check whether we should use the grid layout.
      */
     public boolean useGridLayout() {
-        return mLayoutAlgorithm.getGridState().useGridLayout();
+        return mLayoutAlgorithm.useGridLayout();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
index 5d969f9..6fc4ad7 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/grid/TaskGridLayoutAlgorithm.java
@@ -39,7 +39,6 @@
     /** The padding between task views. */
     private int mPaddingTaskView;
 
-    private Rect mDisplayRect;
     private Rect mWindowRect;
     private Point mScreenSize = new Point();
 
@@ -62,7 +61,7 @@
         int[] xOffsets;
         int[] yOffsets;
 
-        public TaskGridRectInfo(int taskCount) {
+        TaskGridRectInfo(int taskCount) {
             size = new Rect();
             xOffsets = new int[taskCount];
             yOffsets = new int[taskCount];
@@ -74,10 +73,26 @@
                     layoutTaskCount < 7 ? 3 : 4));
             int lines = layoutTaskCount < 3 ? 1 : 2;
 
+            // A couple of special cases.
+            boolean landscapeWindow = mWindowRect.width() > mWindowRect.height();
+            boolean landscapeTaskView = mAppAspectRatio > 1;
+            // If we're in portrait but task views are landscape, show more lines of fewer tasks.
+            if (!landscapeWindow && landscapeTaskView) {
+                tasksPerLine = layoutTaskCount < 2 ? 1 : 2;
+                lines = layoutTaskCount < 3 ? 1 : (
+                        layoutTaskCount < 5 ? 2 : (
+                                layoutTaskCount < 7 ? 3 : 4));
+            }
+            // If we're in landscape but task views are portrait, show fewer lines of more tasks.
+            if (landscapeWindow && !landscapeTaskView) {
+                tasksPerLine = layoutTaskCount < 7 ? layoutTaskCount : 6;
+                lines = layoutTaskCount < 7 ? 1 : 2;
+            }
+
             int taskWidth, taskHeight;
-            int maxTaskWidth = (mDisplayRect.width() - 2 * mPaddingLeftRight
+            int maxTaskWidth = (mWindowRect.width() - 2 * mPaddingLeftRight
                 - (tasksPerLine - 1) * mPaddingTaskView) / tasksPerLine;
-            int maxTaskHeight = (mDisplayRect.height() - 2 * mPaddingTopBottom
+            int maxTaskHeight = (mWindowRect.height() - 2 * mPaddingTopBottom
                 - (lines - 1) * mPaddingTaskView) / lines;
 
             if (maxTaskHeight >= maxTaskWidth / mAppAspectRatio + mTitleBarHeight) {
@@ -91,9 +106,9 @@
             }
             size.set(0, 0, taskWidth, taskHeight);
 
-            int emptySpaceX = mDisplayRect.width() - 2 * mPaddingLeftRight
+            int emptySpaceX = mWindowRect.width() - 2 * mPaddingLeftRight
                 - (tasksPerLine * taskWidth) - (tasksPerLine - 1) * mPaddingTaskView;
-            int emptySpaceY = mDisplayRect.height() - 2 * mPaddingTopBottom
+            int emptySpaceY = mWindowRect.height() - 2 * mPaddingTopBottom
                 - (lines * taskHeight) - (lines - 1) * mPaddingTaskView;
             for (int taskIndex = 0; taskIndex < taskCount; taskIndex++) {
                 // We also need to invert the index in order to display the most recent tasks first.
@@ -101,9 +116,9 @@
 
                 int xIndex = taskLayoutIndex % tasksPerLine;
                 int yIndex = taskLayoutIndex / tasksPerLine;
-                xOffsets[taskIndex] =
+                xOffsets[taskIndex] = mWindowRect.left +
                     emptySpaceX / 2 + mPaddingLeftRight + (taskWidth + mPaddingTaskView) * xIndex;
-                yOffsets[taskIndex] =
+                yOffsets[taskIndex] = mWindowRect.top +
                     emptySpaceY / 2 + mPaddingTopBottom + (taskHeight + mPaddingTaskView) * yIndex;
             }
         }
@@ -113,7 +128,7 @@
      * We can find task view sizes and positions from mTaskGridRectInfoList[k - 1] when there
      * are k tasks.
      */
-    TaskGridRectInfo[] mTaskGridRectInfoList;
+    private TaskGridRectInfo[] mTaskGridRectInfoList;
 
     public TaskGridLayoutAlgorithm(Context context) {
         reloadOnConfigurationChange(context);
@@ -121,10 +136,7 @@
 
     public void reloadOnConfigurationChange(Context context) {
         Resources res = context.getResources();
-        mPaddingLeftRight = res.getDimensionPixelSize(R.dimen.recents_grid_padding_left_right);
-        mPaddingTopBottom = res.getDimensionPixelSize(R.dimen.recents_grid_padding_top_bottom);
         mPaddingTaskView = res.getDimensionPixelSize(R.dimen.recents_grid_padding_task_view);
-
         mTaskGridRect = new Rect();
         mTitleBarHeight = res.getDimensionPixelSize(R.dimen.recents_grid_task_view_header_height);
 
@@ -178,9 +190,11 @@
         return transformOut;
     }
 
-    public void initialize(Rect displayRect, Rect windowRect) {
-        mDisplayRect = displayRect;
+    public void initialize(Rect windowRect) {
         mWindowRect = windowRect;
+        // Define paddings in terms of percentage of the total area.
+        mPaddingLeftRight = (int) (0.025f * Math.min(mWindowRect.width(), mWindowRect.height()));
+        mPaddingTopBottom = (int) (0.1 * mWindowRect.height());
 
         // Pre-calculate the positions and offsets of task views so that we can reuse them directly
         // in the future.
@@ -202,7 +216,7 @@
     }
 
     public Rect getStackActionButtonRect() {
-        Rect buttonRect = new Rect(mDisplayRect);
+        Rect buttonRect = new Rect(mWindowRect);
         buttonRect.right -= mPaddingLeftRight;
         buttonRect.left += mPaddingLeftRight;
         buttonRect.bottom = buttonRect.top + mPaddingTopBottom;