Merge "Shorten and center TaskMenuView for landscape" into sc-v2-dev
diff --git a/go/quickstep/res/layout/overview_actions_container.xml b/go/quickstep/res/layout/overview_actions_container.xml
index cc65cbf..710e2e0 100644
--- a/go/quickstep/res/layout/overview_actions_container.xml
+++ b/go/quickstep/res/layout/overview_actions_container.xml
@@ -105,6 +105,23 @@
 
         <!-- Unused. Included only for compatibility with parent class. -->
         <Button
+            android:id="@+id/action_split"
+            style="@style/GoOverviewActionButton"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:drawableStart="@drawable/ic_split_screen"
+            android:text="@string/action_split"
+            android:theme="@style/ThemeControlHighlightWorkspaceColor"
+            android:visibility="gone" />
+
+        <Space
+            android:id="@+id/action_split_space"
+            android:layout_width="0dp"
+            android:layout_height="1dp"
+            android:layout_weight="1"
+            android:visibility="gone" />
+
+        <Button
             android:id="@+id/action_share"
             style="@style/GoOverviewActionButton"
             android:layout_width="wrap_content"
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index a9ff03b..02170ab 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -107,7 +107,7 @@
     // Evaluate whether the handle should be stashed
     private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
             flags -> {
-                if (!supportsStashing()) {
+                if (!supportsVisualStashing()) {
                     return false;
                 }
                 boolean inApp = (flags & FLAG_IN_APP) != 0;
@@ -141,7 +141,7 @@
         mTaskbarStashedHandleAlpha = stashedHandleController.getStashedHandleAlpha();
         mTaskbarStashedHandleHintScale = stashedHandleController.getStashedHandleHintScale();
 
-        mIsStashedInApp = supportsStashing()
+        mIsStashedInApp = supportsManualStashing()
                 && mPrefs.getBoolean(SHARED_PREFS_STASHED_KEY, DEFAULT_STASHED_PREF);
         updateStateForFlag(FLAG_STASHED_IN_APP, mIsStashedInApp);
 
@@ -150,10 +150,18 @@
     }
 
     /**
+     * Returns whether the taskbar can visually stash into a handle based on the current device
+     * state.
+     */
+    private boolean supportsVisualStashing() {
+        return !mActivity.isThreeButtonNav();
+    }
+
+    /**
      * Returns whether the user can manually stash the taskbar based on the current device state.
      */
-    private boolean supportsStashing() {
-        return !mActivity.isThreeButtonNav()
+    private boolean supportsManualStashing() {
+        return supportsVisualStashing()
                 && (!Utilities.IS_RUNNING_IN_TEST_HARNESS || supportsStashingForTests());
     }
 
@@ -206,7 +214,7 @@
      * @return Whether we started an animation to either be newly stashed or unstashed.
      */
     public boolean updateAndAnimateIsStashedInApp(boolean isStashedInApp) {
-        if (!supportsStashing()) {
+        if (!supportsManualStashing()) {
             return false;
         }
         if (mIsStashedInApp != isStashedInApp) {
@@ -307,7 +315,7 @@
      *                       unstashed state.
      */
     public void startStashHint(boolean animateForward) {
-        if (isStashed() || !supportsStashing()) {
+        if (isStashed() || !supportsManualStashing()) {
             // Already stashed, no need to hint in that direction.
             return;
         }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index 3121bfc..ce8cf3c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -33,7 +33,6 @@
 import android.graphics.PointF;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
-import android.util.Pair;
 import android.view.Surface;
 
 import com.android.launcher3.CellLayout.ContainerType;
@@ -215,8 +214,6 @@
     // Whether Taskbar will inset the bottom of apps by taskbarSize.
     public boolean isTaskbarPresentInApps;
     public int taskbarSize;
-    // How much of the bottom inset is due to Taskbar rather than other system elements.
-    public int nonOverlappingTaskbarInset;
 
     // DragController
     public int flingToDeleteThresholdVelocity;
@@ -239,7 +236,7 @@
         widthPx = windowBounds.bounds.width();
         heightPx = windowBounds.bounds.height();
         availableWidthPx = windowBounds.availableSize.x;
-        int nonFinalAvailableHeightPx = windowBounds.availableSize.y;
+        availableHeightPx = windowBounds.availableSize.y;
 
         mInfo = info;
         // If the device's pixel density was scaled (usually via settings for A11y), use the
@@ -266,15 +263,8 @@
         isTaskbarPresent = isTablet && ApiWrapper.TASKBAR_DRAWN_IN_PROCESS
                 && FeatureFlags.ENABLE_TASKBAR.get();
         if (isTaskbarPresent) {
-            // Taskbar will be added later, but provides bottom insets that we should subtract
-            // from availableHeightPx.
             taskbarSize = res.getDimensionPixelSize(R.dimen.taskbar_size);
-            nonOverlappingTaskbarInset = taskbarSize - windowBounds.insets.bottom;
-            if (nonOverlappingTaskbarInset > 0) {
-                nonFinalAvailableHeightPx -= nonOverlappingTaskbarInset;
-            }
         }
-        availableHeightPx = nonFinalAvailableHeightPx;
 
         edgeMarginPx = res.getDimensionPixelSize(R.dimen.dynamic_grid_edge_margin);
 
@@ -842,7 +832,7 @@
                 padding.right = hotseatBarSizePx;
             }
         } else {
-            int hotseatTop = isTaskbarPresent ? taskbarSize : hotseatBarSizePx;
+            int hotseatTop = hotseatBarSizePx;
             int paddingBottom = hotseatTop + workspacePageIndicatorHeight
                     + workspaceBottomPadding - mWorkspacePageIndicatorOverlapWorkspace;
             if (isTablet) {
@@ -853,8 +843,7 @@
                         ((inv.numColumns - 1) * cellWidthPx)));
                 availablePaddingX = (int) Math.min(availablePaddingX,
                         widthPx * MAX_HORIZONTAL_PADDING_PERCENT);
-                int hotseatVerticalPadding = isTaskbarPresent ? 0
-                        : hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx;
+                int hotseatVerticalPadding = hotseatBarTopPaddingPx + hotseatBarBottomPaddingPx;
                 int availablePaddingY = Math.max(0, heightPx - edgeMarginPx - paddingBottom
                         - (2 * inv.numRows * cellHeightPx) - hotseatVerticalPadding);
                 padding.set(availablePaddingX / 2, edgeMarginPx + availablePaddingY / 2,
@@ -886,9 +875,9 @@
                         mInsets.right + hotseatBarSidePaddingStartPx, mInsets.bottom);
             }
         } else if (isTaskbarPresent) {
-            int hotseatHeight = workspacePadding.bottom + taskbarSize;
+            int hotseatHeight = workspacePadding.bottom;
             int taskbarOffset = getTaskbarOffsetY();
-            int hotseatTopDiff = hotseatHeight - taskbarSize - taskbarOffset;
+            int hotseatTopDiff = hotseatHeight - taskbarOffset;
 
             int endOffset = ApiWrapper.getHotseatEndOffset(context);
             int requiredWidth = iconSizePx * numShownHotseatIcons;
@@ -938,7 +927,8 @@
                 : hotseatBarSizePx - hotseatCellHeightPx - hotseatQsbHeight;
 
         if (isScalableGrid && qsbBottomMarginPx > mInsets.bottom) {
-            return Math.min(qsbBottomMarginPx, freeSpace);
+            // Note that taskbarSize = 0 unless isTaskbarPresent.
+            return Math.min(qsbBottomMarginPx + taskbarSize, freeSpace);
         } else {
             return (int) (freeSpace * QSB_CENTER_FACTOR)
                 + (isTaskbarPresent ? taskbarSize : mInsets.bottom);
@@ -1116,10 +1106,7 @@
 
         writer.println(prefix + "\tisTaskbarPresent:" + isTaskbarPresent);
         writer.println(prefix + "\tisTaskbarPresentInApps:" + isTaskbarPresentInApps);
-
         writer.println(prefix + pxToDpStr("taskbarSize", taskbarSize));
-        writer.println(prefix + pxToDpStr("nonOverlappingTaskbarInset",
-                nonOverlappingTaskbarInset));
 
         writer.println(prefix + pxToDpStr("workspacePadding.left", workspacePadding.left));
         writer.println(prefix + pxToDpStr("workspacePadding.top", workspacePadding.top));
diff --git a/src/com/android/launcher3/LauncherRootView.java b/src/com/android/launcher3/LauncherRootView.java
index 28afc57..7de2ee4 100644
--- a/src/com/android/launcher3/LauncherRootView.java
+++ b/src/com/android/launcher3/LauncherRootView.java
@@ -47,15 +47,8 @@
     }
 
     private void handleSystemWindowInsets(Rect insets) {
-        DeviceProfile dp = mActivity.getDeviceProfile();
-
-        // Taskbar provides insets, but we don't want that for most Launcher elements so remove it.
-        mTempRect.set(insets);
-        insets = mTempRect;
-        insets.bottom = Math.max(0, insets.bottom - dp.nonOverlappingTaskbarInset);
-
         // Update device profile before notifying the children.
-        dp.updateInsets(insets);
+        mActivity.getDeviceProfile().updateInsets(insets);
         boolean resetState = !insets.equals(mInsets);
         setInsets(insets);
 
@@ -86,10 +79,6 @@
      * get its insets, we calculate them ourselves so they are stable regardless of whether taskbar
      * is currently attached.
      *
-     * TODO(b/198798034): Currently we always calculate nav insets as taskbarSize, but then we
-     * subtract nonOverlappingTaskbarInset in handleSystemWindowInsets(). Instead, we should just
-     * calculate the normal nav bar height here, and remove nonOverlappingTaskbarInset altogether.
-     *
      * @param oldInsets The system-provided insets, which we are modifying.
      * @return The updated insets.
      */
@@ -108,10 +97,8 @@
         Insets oldNavInsets = oldInsets.getInsets(WindowInsets.Type.navigationBars());
         Rect newNavInsets = new Rect(oldNavInsets.left, oldNavInsets.top, oldNavInsets.right,
                 oldNavInsets.bottom);
-        if (dp.isTaskbarPresent) {
-            // TODO (see javadoc): Remove this block and fall into the next one instead.
-            newNavInsets.bottom = dp.taskbarSize;
-        } else if (dp.isLandscape) {
+
+        if (dp.isLandscape) {
             if (dp.isTablet) {
                 newNavInsets.bottom = ResourceUtils.getNavbarSize(
                         "navigation_bar_height_landscape", resources);
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index 3faa3d0..c5e9dd2 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -314,8 +314,6 @@
         Rect padding = grid.workspacePadding;
         setPadding(padding.left, padding.top, padding.right, padding.bottom);
         mInsets.set(insets);
-        // Increase our bottom insets so we don't overlap with the taskbar.
-        mInsets.bottom += grid.nonOverlappingTaskbarInset;
 
         if (mWorkspaceFadeInAdjacentScreens) {
             // In landscape mode the page spacing is set to the default.
diff --git a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
index 9889a80..b74d0fc 100644
--- a/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
+++ b/src/com/android/launcher3/model/PackageInstallStateChangedTask.java
@@ -21,7 +21,6 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.pm.PackageInstallInfo;
 import com.android.launcher3.util.InstantAppResolver;
@@ -73,13 +72,7 @@
             dataModel.forAllWorkspaceItemInfos(mInstallInfo.user, si -> {
                 if (si.hasPromiseIconUi()
                         && mInstallInfo.packageName.equals(si.getTargetPackage())) {
-                    int installProgress = mInstallInfo.progress;
-
-                    si.setProgressLevel(installProgress, PackageInstallInfo.STATUS_INSTALLING);
-                    if (mInstallInfo.state == PackageInstallInfo.STATUS_FAILED) {
-                        // Mark this info as broken.
-                        si.runtimeStatusFlags &= ~ItemInfoWithIcon.FLAG_INSTALL_SESSION_ACTIVE;
-                    }
+                    si.setProgressLevel(mInstallInfo);
                     updates.add(si);
                 }
             });
diff --git a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
index 6813b97..a74c02f 100644
--- a/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
+++ b/src/com/android/launcher3/model/data/ItemInfoWithIcon.java
@@ -24,6 +24,7 @@
 
 import com.android.launcher3.icons.BitmapInfo;
 import com.android.launcher3.icons.FastBitmapDrawable;
+import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.pm.PackageInstallInfo;
 import com.android.launcher3.util.PackageManagerHelper;
 
@@ -179,6 +180,12 @@
      */
     public void setProgressLevel(PackageInstallInfo installInfo) {
         setProgressLevel(installInfo.progress, installInfo.state);
+
+        if (installInfo.state == PackageInstallInfo.STATUS_FAILED) {
+            FileLog.d(TAG,
+                    "Icon info: " + this + " marked broken with install info: " + installInfo,
+                    new Exception());
+        }
     }
 
     /**
diff --git a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
index f73d782..c685891 100644
--- a/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
+++ b/src/com/android/launcher3/pageindicators/WorkspacePageIndicator.java
@@ -268,9 +268,7 @@
         } else {
             lp.leftMargin = lp.rightMargin = 0;
             lp.gravity = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;
-            lp.bottomMargin = grid.isTaskbarPresent
-                    ? grid.workspacePadding.bottom + grid.taskbarSize
-                    : grid.hotseatBarSizePx + insets.bottom;
+            lp.bottomMargin = grid.hotseatBarSizePx + insets.bottom;
         }
         setLayoutParams(lp);
     }
diff --git a/src/com/android/launcher3/pm/PackageInstallInfo.java b/src/com/android/launcher3/pm/PackageInstallInfo.java
index fad904f..1797c1f 100644
--- a/src/com/android/launcher3/pm/PackageInstallInfo.java
+++ b/src/com/android/launcher3/pm/PackageInstallInfo.java
@@ -57,4 +57,28 @@
     public static PackageInstallInfo fromState(int state, String packageName, UserHandle user) {
         return new PackageInstallInfo(packageName, state, 0 /* progress */, user);
     }
+
+
+    @Override
+    public String toString() {
+        return getClass().getSimpleName() + "(" + dumpProperties() + ")";
+    }
+
+    private String dumpProperties() {
+        return "componentName=" + componentName
+                + "packageName=" + packageName
+                + " state=" + stateToString()
+                + " progress=" + progress
+                + " user=" + user;
+    }
+
+    private String stateToString() {
+        switch (state) {
+            case STATUS_INSTALLED : return "STATUS_INSTALLED";
+            case STATUS_INSTALLING : return "STATUS_INSTALLING";
+            case STATUS_INSTALLED_DOWNLOADING : return "STATUS_INSTALLED_DOWNLOADING";
+            case STATUS_FAILED : return "STATUS_FAILED";
+            default : return "INVALID STATE";
+        }
+    }
 }
diff --git a/src/com/android/launcher3/states/SpringLoadedState.java b/src/com/android/launcher3/states/SpringLoadedState.java
index 8db1dbe..5fe5450 100644
--- a/src/com/android/launcher3/states/SpringLoadedState.java
+++ b/src/com/android/launcher3/states/SpringLoadedState.java
@@ -59,11 +59,10 @@
 
         float scale = grid.workspaceSpringLoadShrinkFactor;
         Rect insets = launcher.getDragLayer().getInsets();
-        int insetsBottom = grid.isTaskbarPresent ? grid.taskbarSize : insets.bottom;
 
         float scaledHeight = scale * ws.getNormalChildHeight();
         float shrunkTop = insets.top + grid.dropTargetBarSizePx;
-        float shrunkBottom = ws.getMeasuredHeight() - insetsBottom
+        float shrunkBottom = ws.getMeasuredHeight() - insets.bottom
                 - grid.workspacePadding.bottom
                 - grid.workspaceSpringLoadedBottomSpace;
         float totalShrunkSpace = shrunkBottom - shrunkTop;
diff --git a/src/com/android/launcher3/testing/TestInformationHandler.java b/src/com/android/launcher3/testing/TestInformationHandler.java
index 86acff7..5a9c074 100644
--- a/src/com/android/launcher3/testing/TestInformationHandler.java
+++ b/src/com/android/launcher3/testing/TestInformationHandler.java
@@ -116,9 +116,7 @@
                 return getUIProperty(Bundle::putParcelable, activity -> {
                     WindowInsets insets = activity.getWindow()
                             .getDecorView().getRootWindowInsets();
-                    return Insets.subtract(
-                            insets.getSystemWindowInsets(),
-                            Insets.of(0, 0, 0, mDeviceProfile.nonOverlappingTaskbarInset));
+                    return insets.getSystemWindowInsets();
                 }, this::getCurrentActivity);
             }
 
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index cd0c7f2..1a6ce8c 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -153,6 +153,8 @@
     public static String dumpHprofData() {
         String result;
         if (sDumpWasGenerated) {
+            Log.d("b/195319692", "dump has already been generated by another test",
+                    new Exception());
             result = "dump has already been generated by another test";
         } else {
             try {
@@ -167,6 +169,7 @@
                             "am dumpheap " + device.getLauncherPackageName() + " " + fileName);
                 }
                 sDumpWasGenerated = true;
+                Log.d("b/195319692", "sDumpWasGenerated := true", new Exception());
                 result = "memory dump filename: " + fileName;
             } catch (Throwable e) {
                 Log.e(TAG, "dumpHprofData failed", e);