Make hotseat fit one line on tablets

When running on tablets in landscape, the QSB should inline with the hotseat icons. This does that and fixes small bugs that didn't account for the new hotseatBorderSpace.

Bug: 210118169
Test: atest Launcher3Tests:DeviceProfileTest
Test: visual, using HSV and Window
Change-Id: I5a89c5449bf59fde736618151eceaacca443ef67
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 8a5b888..157ed04 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -61,6 +61,7 @@
     public final boolean isPhone;
     public final boolean transposeLayoutWithOrientation;
     public final boolean isTwoPanels;
+    public final boolean isQsbInline;
 
     // Device properties in current orientation
     public final boolean isLandscape;
@@ -165,6 +166,7 @@
 
     public final float qsbBottomMarginOriginalPx;
     public int qsbBottomMarginPx;
+    public int qsbWidth; // only used when isQsbInline
 
     // All apps
     public Point allAppsBorderSpacePx;
@@ -246,6 +248,7 @@
         isPhone = !isTablet;
         isTwoPanels = isTablet && useTwoPanels;
 
+
         aspectRatio = ((float) Math.max(widthPx, heightPx)) / Math.min(widthPx, heightPx);
         boolean isTallDevice = Float.compare(aspectRatio, TALL_DEVICE_ASPECT_RATIO_THRESHOLD) >= 0;
         mQsbCenterFactor = context.getResources().getFloat(R.dimen.qsb_center_factor);
@@ -270,7 +273,6 @@
             }
         }
 
-        hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
         isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
                 && FeatureFlags.ENABLE_TASKBAR.get();
         if (isTaskbarPresent) {
@@ -333,6 +335,8 @@
 
         workspaceCellPaddingXPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_cell_padding_x);
 
+        hotseatQsbHeight = res.getDimensionPixelSize(R.dimen.qsb_widget_height);
+        isQsbInline = isTablet && isLandscape && !isTwoPanels && hotseatQsbHeight > 0;
         numShownHotseatIcons =
                 isTwoPanels ? inv.numDatabaseHotseatIcons : inv.numShownHotseatIcons;
         numShownAllAppsColumns =
@@ -340,10 +344,17 @@
         hotseatBarSizeExtraSpacePx = 0;
         hotseatBarTopPaddingPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_top_padding);
-        hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
-                R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
-                : res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
-                + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+        if (isQsbInline) {
+            hotseatBarBottomPaddingPx = res.getDimensionPixelSize(R.dimen.inline_qsb_bottom_margin);
+            qsbWidth = calculateQsbWidth();
+        } else {
+            hotseatBarBottomPaddingPx = (isTallDevice ? res.getDimensionPixelSize(
+                    R.dimen.dynamic_grid_hotseat_bottom_tall_padding)
+                    : res.getDimensionPixelSize(
+                            R.dimen.dynamic_grid_hotseat_bottom_non_tall_padding))
+                    + res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_bottom_padding);
+            qsbWidth = 0;
+        }
         hotseatBarSidePaddingEndPx =
                 res.getDimensionPixelSize(R.dimen.dynamic_grid_hotseat_side_padding);
         // Add a bit of space between nav bar and hotseat in vertical bar layout.
@@ -472,6 +483,14 @@
                 new DotRenderer(allAppsIconSizePx, dotPath, DEFAULT_DOT_SIZE);
     }
 
+    private int calculateQsbWidth() {
+        return cellWidthPx * inv.numColumns
+                + cellLayoutBorderSpacePx.x * (inv.numColumns - 1)
+                - (cellWidthPx - iconSizePx) // left and right cell space
+                - iconSizePx * numShownHotseatIcons
+                - hotseatBorderSpace * numShownHotseatIcons;
+    }
+
     private int getHorizontalMarginPx(InvariantDeviceProfile idp, Resources res) {
         if (isVerticalBarLayout()) {
             return 0;
@@ -717,6 +736,11 @@
 
         // Hotseat
         hotseatBorderSpace = pxFromDp(inv.hotseatBorderSpaces[mTypeIndex], mMetrics, scale);
+        if (isQsbInline) {
+            qsbWidth = calculateQsbWidth();
+        } else {
+            qsbWidth = 0;
+        }
         updateHotseatIconSize(iconSizePx);
 
         if (!isVerticalLayout) {
@@ -895,15 +919,24 @@
         } else if (isTaskbarPresent) {
             int hotseatHeight = workspacePadding.bottom;
             int taskbarOffset = getTaskbarOffsetY();
+            int additionalLeftSpace = 0;
+
+            // Center the QSB with hotseat and push icons to the right
+            if (isQsbInline) {
+                additionalLeftSpace = qsbWidth + hotseatBorderSpace;
+            }
+
             int hotseatTopDiff = hotseatHeight - taskbarOffset;
 
             int endOffset = ApiWrapper.getHotseatEndOffset(context);
             int requiredWidth = iconSizePx * numShownHotseatIcons
-                    + hotseatBorderSpace * (numShownHotseatIcons - 1);
+                    + hotseatBorderSpace * (numShownHotseatIcons - 1)
+                    + additionalLeftSpace;
 
             int hotseatSize = Math.min(requiredWidth, availableWidthPx - endOffset);
             int sideSpacing = (availableWidthPx - hotseatSize) / 2;
-            mHotseatPadding.set(sideSpacing, hotseatTopDiff, sideSpacing, taskbarOffset);
+            mHotseatPadding.set(sideSpacing + additionalLeftSpace, hotseatTopDiff, sideSpacing,
+                    taskbarOffset);
 
             if (endOffset > sideSpacing) {
                 int diff = Utilities.isRtl(context.getResources())
@@ -936,6 +969,10 @@
      * Returns the number of pixels the QSB is translated from the bottom of the screen.
      */
     public int getQsbOffsetY() {
+        if (isQsbInline) {
+            return hotseatBarBottomPaddingPx;
+        }
+
         int freeSpace = isTaskbarPresent
                 ? workspacePadding.bottom
                 : hotseatBarSizePx - hotseatCellHeightPx - hotseatQsbHeight;
@@ -953,7 +990,11 @@
      * Returns the number of pixels the taskbar is translated from the bottom of the screen.
      */
     public int getTaskbarOffsetY() {
-        return (getQsbOffsetY() - taskbarSize) / 2;
+        if (isQsbInline) {
+            return getQsbOffsetY() + (Math.abs(hotseatQsbHeight - iconSizePx) / 2);
+        } else {
+            return (getQsbOffsetY() - taskbarSize) / 2;
+        }
     }
 
     /**
@@ -1113,6 +1154,8 @@
         writer.println(prefix + pxToDpStr("hotseatBarSidePaddingEndPx",
                 hotseatBarSidePaddingEndPx));
         writer.println(prefix + "\tnumShownHotseatIcons: " + numShownHotseatIcons);
+        writer.println(prefix + "\tisQsbInline: " + isQsbInline);
+        writer.println(prefix + pxToDpStr("qsbWidth", qsbWidth));
 
         writer.println(prefix + "\tisTaskbarPresent:" + isTaskbarPresent);
         writer.println(prefix + "\tisTaskbarPresentInApps:" + isTaskbarPresentInApps);