Merge "Shortcut/people icon horizontal layout polish" into tm-qpr-dev
diff --git a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
index a645e58..cf58198 100644
--- a/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
+++ b/ext_tests/src/com/android/launcher3/testing/DebugTestInformationHandler.java
@@ -221,6 +221,12 @@
                 return response;
             }
 
+            case TestProtocol.REQUEST_USE_TAPL_WORKSPACE_LAYOUT: {
+                useTestWorkspaceLayout(
+                        LauncherSettings.Settings.ARG_DEFAULT_WORKSPACE_LAYOUT_TAPL);
+                return response;
+            }
+
             case TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT: {
                 useTestWorkspaceLayout(null);
                 return response;
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index ea7eba3..da28cfa 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -52,6 +52,7 @@
 import static com.android.launcher3.config.FeatureFlags.KEYGUARD_ANIMATION;
 import static com.android.launcher3.config.FeatureFlags.SEPARATE_RECENTS_ACTIVITY;
 import static com.android.launcher3.model.data.ItemInfo.NO_MATCHING_ID;
+import static com.android.launcher3.util.DisplayController.isTransientTaskbar;
 import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
 import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
 import static com.android.launcher3.views.FloatingIconView.SHAPE_PROGRESS_DURATION;
@@ -122,7 +123,6 @@
 import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.launcher3.uioverrides.QuickstepLauncher;
 import com.android.launcher3.util.ActivityOptionsWrapper;
-import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.DynamicResource;
 import com.android.launcher3.util.ObjectWrapper;
 import com.android.launcher3.util.RunnableList;
@@ -448,7 +448,7 @@
         }
         if (mDeviceProfile.isTaskbarPresentInApps
                 && !target.willShowImeOnTarget
-                && !DisplayController.isTransientTaskbar(mLauncher)) {
+                && !isTransientTaskbar(mLauncher)) {
             // Animate to above the taskbar.
             bounds.bottom -= target.contentInsets.bottom;
         }
@@ -635,7 +635,7 @@
 
         RectF launcherIconBounds = new RectF();
         FloatingIconView floatingView = getFloatingIconView(mLauncher, v,
-                mLauncher.getTaskbarUIController() == null
+                (mLauncher.getTaskbarUIController() == null || !isTransientTaskbar(mLauncher))
                         ? null
                         : mLauncher.getTaskbarUIController().findMatchingView(v),
                 !appTargetsAreTranslucent, launcherIconBounds, true /* isOpening */);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 57e11de..62713ca 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -316,7 +316,6 @@
         return mTransientTaskbarBounds;
     }
 
-    @VisibleForTesting
     @Override
     public StatsLogManager getStatsLogManager() {
         // Used to mock, can't mock a default interface method directly
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 8c21778..e0acd3e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -25,6 +25,8 @@
 import static com.android.launcher3.config.FeatureFlags.FORCE_PERSISTENT_TASKBAR;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
 import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_HIDE;
+import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TRANSIENT_TASKBAR_SHOW;
 import static com.android.launcher3.taskbar.Utilities.appendFlag;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_BOUNCER_SHOWING;
 import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
@@ -972,6 +974,11 @@
                 mActivity.getStatsLogManager().logger().log(LAUNCHER_TASKBAR_LONGPRESS_SHOW);
             }
         }
+        if (hasAnyFlag(changedFlags, FLAG_STASHED_IN_APP_AUTO)) {
+            mActivity.getStatsLogManager().logger().log(hasAnyFlag(FLAG_STASHED_IN_APP_AUTO)
+                    ? LAUNCHER_TRANSIENT_TASKBAR_HIDE
+                    : LAUNCHER_TRANSIENT_TASKBAR_SHOW);
+        }
     }
 
     private void notifyStashChange(boolean visible, boolean stashed) {
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
index ff3a292..b318100 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepWidgetHolder.java
@@ -168,6 +168,7 @@
     @Override
     public void deleteAppWidgetId(int appWidgetId) {
         super.deleteAppWidgetId(appWidgetId);
+        mViews.remove(appWidgetId);
         sListeners.remove(appWidgetId);
     }
 
@@ -260,6 +261,7 @@
      */
     @Override
     public void clearViews() {
+        mViews.clear();
         for (int i = sListeners.size() - 1; i >= 0; i--) {
             sListeners.valueAt(i).mListeningHolders.remove(this);
         }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
index d2f9294..214679a 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/OverviewState.java
@@ -75,9 +75,17 @@
     @Override
     public ScaleAndTranslation getWorkspaceScaleAndTranslation(Launcher launcher) {
         RecentsView recentsView = launcher.getOverviewPanel();
-        float workspacePageHeight = launcher.getDeviceProfile().getCellLayoutHeight();
         recentsView.getTaskSize(sTempRect);
-        float scale = (float) sTempRect.height() / workspacePageHeight;
+        float scale;
+        DeviceProfile deviceProfile = launcher.getDeviceProfile();
+        if (deviceProfile.isTwoPanels) {
+            // In two panel layout, width does not include both panels or space between them, so
+            // use height instead. We do not use height for handheld, as cell layout can be
+            // shorter than a task and we want the workspace to scale down to task size.
+            scale = (float) sTempRect.height() / deviceProfile.getCellLayoutHeight();
+        } else {
+            scale = (float) sTempRect.width() / deviceProfile.getCellLayoutWidth();
+        }
         float parallaxFactor = 0.5f;
         return new ScaleAndTranslation(scale, 0, -getDefaultSwipeHeight(launcher) * parallaxFactor);
     }
diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
index a02f3de..c7cd39c 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java
@@ -32,6 +32,7 @@
 import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
 import static com.android.launcher3.anim.Interpolators.EMPHASIZED_ACCELERATE;
 import static com.android.launcher3.anim.Interpolators.EMPHASIZED_DECELERATE;
+import static com.android.launcher3.anim.Interpolators.FAST_OUT_SLOW_IN;
 import static com.android.launcher3.anim.Interpolators.FINAL_FRAME;
 import static com.android.launcher3.anim.Interpolators.INSTANT;
 import static com.android.launcher3.anim.Interpolators.LINEAR;
@@ -103,7 +104,10 @@
             }
 
             config.setInterpolator(ANIM_OVERVIEW_ACTIONS_FADE, clampToProgress(LINEAR, 0, 0.25f));
-            config.setInterpolator(ANIM_SCRIM_FADE, clampToProgress(LINEAR, 0.33f, 1));
+            config.setInterpolator(ANIM_SCRIM_FADE,
+                    fromState == OVERVIEW_SPLIT_SELECT
+                            ? clampToProgress(LINEAR, 0.33f, 1)
+                            : LINEAR);
             config.setInterpolator(ANIM_WORKSPACE_SCALE, DEACCEL);
             config.setInterpolator(ANIM_WORKSPACE_FADE, ACCEL);
 
@@ -112,7 +116,10 @@
                 // Overview is going offscreen, so keep it at its current scale and opacity.
                 config.setInterpolator(ANIM_OVERVIEW_SCALE, FINAL_FRAME);
                 config.setInterpolator(ANIM_OVERVIEW_FADE, FINAL_FRAME);
-                config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, EMPHASIZED_DECELERATE);
+                config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X,
+                        fromState == OVERVIEW_SPLIT_SELECT
+                                ? EMPHASIZED_DECELERATE
+                                : clampToProgress(FAST_OUT_SLOW_IN, 0, 0.75f));
                 config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, FINAL_FRAME);
 
                 // Scroll RecentsView to page 0 as it goes offscreen, if necessary.
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 3e565b3..487da92 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -244,6 +244,7 @@
             float maxScale = res.getFloat(R.dimen.overview_max_scale);
             int taskMargin = dp.overviewTaskMarginPx;
             calculateTaskSizeInternal(
+                    context,
                     dp,
                     dp.overviewTaskThumbnailTopMarginPx,
                     dp.getOverviewActionsClaimedSpace(),
@@ -259,10 +260,10 @@
         float maxScale = res.getFloat(R.dimen.overview_max_scale);
         Rect gridRect = new Rect();
         calculateGridSize(dp, gridRect);
-        calculateTaskSizeInternal(dp, gridRect, maxScale, Gravity.CENTER, outRect);
+        calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
     }
 
-    private void calculateTaskSizeInternal(DeviceProfile dp, int claimedSpaceAbove,
+    private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
             int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
             Rect outRect) {
         Rect insets = dp.getInsets();
@@ -275,12 +276,12 @@
                 minimumHorizontalPadding,
                 claimedSpaceBelow);
 
-        calculateTaskSizeInternal(dp, potentialTaskRect, maxScale, gravity, outRect);
+        calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
     }
 
-    private void calculateTaskSizeInternal(DeviceProfile dp,
+    private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
             Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
-        PointF taskDimension = getTaskDimension(dp);
+        PointF taskDimension = getTaskDimension(context, dp);
 
         float scale = Math.min(
                 potentialTaskRect.width() / taskDimension.x,
@@ -292,19 +293,19 @@
         Gravity.apply(gravity, outWidth, outHeight, potentialTaskRect, outRect);
     }
 
-    private static PointF getTaskDimension(DeviceProfile dp) {
+    private static PointF getTaskDimension(Context context, DeviceProfile dp) {
         PointF dimension = new PointF();
-        getTaskDimension(dp, dimension);
+        getTaskDimension(context, dp, dimension);
         return dimension;
     }
 
     /**
      * Gets the dimension of the task in the current system state.
      */
-    public static void getTaskDimension(DeviceProfile dp, PointF out) {
+    public static void getTaskDimension(Context context, DeviceProfile dp, PointF out) {
         out.x = dp.widthPx;
         out.y = dp.heightPx;
-        if (dp.isTablet) {
+        if (dp.isTablet && !DisplayController.isTransientTaskbar(context)) {
             out.y -= dp.taskbarSize;
         }
     }
@@ -339,7 +340,7 @@
         float rowHeight = (potentialTaskRect.height() + dp.overviewTaskThumbnailTopMarginPx
                 - dp.overviewRowSpacing) / 2f;
 
-        PointF taskDimension = getTaskDimension(dp);
+        PointF taskDimension = getTaskDimension(context, dp);
         float scale = (rowHeight - dp.overviewTaskThumbnailTopMarginPx) / taskDimension.y;
         int outWidth = Math.round(scale * taskDimension.x);
         int outHeight = Math.round(scale * taskDimension.y);
@@ -373,6 +374,7 @@
                     Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2);
         }
         calculateTaskSizeInternal(
+                context,
                 dp,
                 dp.overviewTaskMarginPx,
                 claimedSpaceBelow,
diff --git a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
index 6722f3d..c4ba39a 100644
--- a/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
+++ b/quickstep/src/com/android/quickstep/util/RecentsOrientedState.java
@@ -396,7 +396,7 @@
      * Returns the scale and pivot so that the provided taskRect can fit the provided full size
      */
     public float getFullScreenScaleAndPivot(Rect taskView, DeviceProfile dp, PointF outPivot) {
-        getTaskDimension(dp, outPivot);
+        getTaskDimension(mContext, dp, outPivot);
         float scale = Math.min(outPivot.x / taskView.width(), outPivot.y / taskView.height());
         if (scale == 1) {
             outPivot.set(taskView.centerX(), taskView.centerY());
diff --git a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
index f94d80f..dcbccc5 100644
--- a/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
+++ b/quickstep/src/com/android/quickstep/util/SwipePipToHomeAnimator.java
@@ -37,6 +37,7 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.anim.AnimationSuccessListener;
+import com.android.launcher3.icons.IconProvider;
 import com.android.quickstep.TaskAnimationManager;
 import com.android.systemui.shared.pip.PipSurfaceTransactionHelper;
 import com.android.systemui.shared.system.InteractionJankMonitorWrapper;
@@ -152,7 +153,7 @@
             if (SystemProperties.getBoolean(
                     "persist.wm.debug.enable_pip_app_icon_overlay", true)) {
                 mPipContentOverlay = new PipContentOverlay.PipAppIconOverlay(view.getContext(),
-                        mAppBounds, mActivityInfo);
+                        mAppBounds, () -> new IconProvider(context).getIcon(mActivityInfo));
             }  else {
                 mPipContentOverlay = new PipContentOverlay.PipColorOverlay(view.getContext());
             }
diff --git a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
index 0b83eaf..0d61bc8 100644
--- a/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
+++ b/quickstep/src/com/android/quickstep/util/TaskViewSimulator.java
@@ -272,9 +272,7 @@
      */
     public RectF getCurrentCropRect() {
         // Crop rect is the inverse of thumbnail matrix
-        RectF insets = mCurrentFullscreenParams.mCurrentDrawnInsets;
-        mTempRectF.set(-insets.left, -insets.top,
-                mTaskRect.width() + insets.right, mTaskRect.height() + insets.bottom);
+        mTempRectF.set(0, 0, mTaskRect.width(), mTaskRect.height());
         mInversePositionMatrix.mapRect(mTempRectF);
         return mTempRectF;
     }
@@ -351,14 +349,10 @@
                 /* taskViewScale= */1f, mTaskRect.width(), mDp, mPositionHelper);
 
         // Apply thumbnail matrix
-        RectF insets = mCurrentFullscreenParams.mCurrentDrawnInsets;
-        float scale = mCurrentFullscreenParams.mScale;
         float taskWidth = mTaskRect.width();
         float taskHeight = mTaskRect.height();
 
         mMatrix.set(mPositionHelper.getMatrix());
-        mMatrix.postTranslate(insets.left, insets.top);
-        mMatrix.postScale(scale, scale);
 
         // Apply TaskView matrix: taskRect, translate
         mMatrix.postTranslate(mTaskRect.left, mTaskRect.top);
@@ -378,8 +372,7 @@
         applyWindowToHomeRotation(mMatrix);
 
         // Crop rect is the inverse of thumbnail matrix
-        mTempRectF.set(-insets.left, -insets.top,
-                taskWidth + insets.right, taskHeight + insets.bottom);
+        mTempRectF.set(0, 0, taskWidth, taskHeight);
         mInversePositionMatrix.mapRect(mTempRectF);
         mTempRectF.roundOut(mTmpCropRect);
 
@@ -389,7 +382,6 @@
             return;
         }
         Log.d(TAG, "progress: " + fullScreenProgress
-                + " scale: " + scale
                 + " recentsViewScale: " + recentsViewScale.value
                 + " crop: " + mTmpCropRect
                 + " radius: " + getCurrentCornerRadius()
diff --git a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
index 96504af..af80d5f 100644
--- a/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
+++ b/quickstep/src/com/android/quickstep/views/DigitalWellBeingToast.java
@@ -97,11 +97,6 @@
     private View mBanner;
     private ViewOutlineProvider mOldBannerOutlineProvider;
     private float mBannerOffsetPercentage;
-    /**
-     * Clips rect provided by {@link #mOldBannerOutlineProvider} when in the model state to
-     * hide this banner as the taskView scales up and down
-     */
-    private float mModalOffset = 0f;
     @Nullable
     private SplitBounds mSplitBounds;
     private int mSplitBannerConfig = SPLIT_BANNER_FULLSCREEN;
@@ -336,17 +331,15 @@
             @Override
             public void getOutline(View view, Outline outline) {
                 mOldBannerOutlineProvider.getOutline(view, outline);
-                float verticalTranslation = -view.getTranslationY() + mModalOffset
-                        + mSplitOffsetTranslationY;
+                float verticalTranslation = -view.getTranslationY() + mSplitOffsetTranslationY;
                 outline.offset(0, Math.round(verticalTranslation));
             }
         });
         mBanner.setClipToOutline(true);
     }
 
-    void updateBannerOffset(float offsetPercentage, float verticalOffset) {
+    void updateBannerOffset(float offsetPercentage) {
         if (mBanner != null && mBannerOffsetPercentage != offsetPercentage) {
-            mModalOffset = verticalOffset;
             mBannerOffsetPercentage = offsetPercentage;
             updateTranslationY();
             mBanner.invalidateOutline();
@@ -359,10 +352,7 @@
         }
 
         mBanner.setTranslationY(
-                (mBannerOffsetPercentage * mBanner.getHeight()) +
-                        mModalOffset +
-                        mSplitOffsetTranslationY
-        );
+                (mBannerOffsetPercentage * mBanner.getHeight()) + mSplitOffsetTranslationY);
     }
 
     private void updateTranslationX() {
diff --git a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
index 0e05032..5bfd035 100644
--- a/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/GroupedTaskView.java
@@ -391,9 +391,7 @@
         // Value set by super call
         float scale = mIconView.getAlpha();
         mIconView2.setAlpha(scale);
-        mDigitalWellBeingToast2.updateBannerOffset(1f - scale,
-                mCurrentFullscreenParams.mCurrentDrawnInsets.top
-                        + mCurrentFullscreenParams.mCurrentDrawnInsets.bottom);
+        mDigitalWellBeingToast2.updateBannerOffset(1f - scale);
     }
 
     @Override
diff --git a/quickstep/src/com/android/quickstep/views/RecentsView.java b/quickstep/src/com/android/quickstep/views/RecentsView.java
index 614ef81..4ba0276 100644
--- a/quickstep/src/com/android/quickstep/views/RecentsView.java
+++ b/quickstep/src/com/android/quickstep/views/RecentsView.java
@@ -3166,6 +3166,8 @@
                 InteractionJankMonitorWrapper.cancel(
                         InteractionJankMonitorWrapper.CUJ_SPLIT_SCREEN_ENTER);
             }
+
+            updateCurrentTaskActionsVisibility();
         });
     }
 
@@ -4666,6 +4668,11 @@
             mSecondSplitHiddenView = null;
         }
 
+        // We are leaving split selection state, so it is safe to reset thumbnail translations for
+        // the next time split is invoked.
+        setTaskViewsPrimarySplitTranslation(0);
+        setTaskViewsSecondarySplitTranslation(0);
+
         if (mSplitHiddenTaskViewIndex == -1) {
             return;
         }
@@ -4680,11 +4687,6 @@
         }
         onLayout(false /*  changed */, getLeft(), getTop(), getRight(), getBottom());
 
-        // We are leaving split selection state, so it is safe to reset thumbnail translations for
-        // the next time split is invoked.
-        setTaskViewsPrimarySplitTranslation(0);
-        setTaskViewsSecondarySplitTranslation(0);
-
         resetTaskVisuals();
         mSplitHiddenTaskViewIndex = -1;
         if (mSplitHiddenTaskView != null) {
diff --git a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
index 62a58f5..899fea2 100644
--- a/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskThumbnailView.java
@@ -338,16 +338,9 @@
 
     @Override
     protected void onDraw(Canvas canvas) {
-        RectF currentDrawnInsets = mFullscreenParams.mCurrentDrawnInsets;
         canvas.save();
-        canvas.scale(mFullscreenParams.mScale, mFullscreenParams.mScale);
-        canvas.translate(currentDrawnInsets.left, currentDrawnInsets.top);
         // Draw the insets if we're being drawn fullscreen (we do this for quick switch).
-        drawOnCanvas(canvas,
-                -currentDrawnInsets.left,
-                -currentDrawnInsets.top,
-                getMeasuredWidth() + currentDrawnInsets.right,
-                getMeasuredHeight() + currentDrawnInsets.bottom,
+        drawOnCanvas(canvas, 0, 0, getMeasuredWidth(), getMeasuredHeight(),
                 mFullscreenParams.mCurrentDrawnCornerRadius);
         canvas.restore();
     }
@@ -506,9 +499,7 @@
             return false;
         }
 
-        RectF insets = mPreviewPositionHelper.getClippedInsets();
-        float thumbnailViewAspect = (getWidth() + insets.left + insets.right)
-                / (getHeight() + insets.top + insets.bottom);
+        float thumbnailViewAspect = getWidth() / (float) getHeight();
         float thumbnailDataAspect =
                 mThumbnailData.thumbnail.getWidth() / (float) mThumbnailData.thumbnail.getHeight();
 
diff --git a/quickstep/src/com/android/quickstep/views/TaskView.java b/quickstep/src/com/android/quickstep/views/TaskView.java
index a06e1f8..df90583 100644
--- a/quickstep/src/com/android/quickstep/views/TaskView.java
+++ b/quickstep/src/com/android/quickstep/views/TaskView.java
@@ -84,7 +84,6 @@
 import com.android.launcher3.touch.PagedOrientationHandler;
 import com.android.launcher3.util.ActivityOptionsWrapper;
 import com.android.launcher3.util.ComponentKey;
-import com.android.launcher3.util.DisplayController;
 import com.android.launcher3.util.RunnableList;
 import com.android.launcher3.util.SplitConfigurationOptions;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
@@ -561,9 +560,7 @@
         }
         mModalness = modalness;
         mIconView.setAlpha(1 - modalness);
-        mDigitalWellBeingToast.updateBannerOffset(modalness,
-                mCurrentFullscreenParams.mCurrentDrawnInsets.top
-                        + mCurrentFullscreenParams.mCurrentDrawnInsets.bottom);
+        mDigitalWellBeingToast.updateBannerOffset(modalness);
     }
 
     public DigitalWellBeingToast getDigitalWellBeingToast() {
@@ -1148,9 +1145,7 @@
         float scale = Interpolators.clampToProgress(FAST_OUT_SLOW_IN, lowerClamp, upperClamp)
                 .getInterpolation(progress);
         mIconView.setAlpha(scale);
-        mDigitalWellBeingToast.updateBannerOffset(1f - scale,
-                mCurrentFullscreenParams.mCurrentDrawnInsets.top
-                        + mCurrentFullscreenParams.mCurrentDrawnInsets.bottom);
+        mDigitalWellBeingToast.updateBannerOffset(1f - scale);
     }
 
     public void setIconScaleAnimStartProgress(float startProgress) {
@@ -1771,17 +1766,11 @@
         private final float mCornerRadius;
         private final float mWindowCornerRadius;
 
-        public RectF mCurrentDrawnInsets = new RectF();
         public float mCurrentDrawnCornerRadius;
-        /** The current scale we apply to the thumbnail to adjust for new left/right insets. */
-        public float mScale = 1;
-
-        private boolean mIsTaskbarTransient;
 
         public FullscreenDrawParams(Context context) {
             mCornerRadius = TaskCornerRadius.get(context);
             mWindowCornerRadius = QuickStepContract.getWindowCornerRadius(context);
-            mIsTaskbarTransient = DisplayController.isTransientTaskbar(context);
 
             mCurrentDrawnCornerRadius = mCornerRadius;
         }
@@ -1791,36 +1780,9 @@
          */
         public void setProgress(float fullscreenProgress, float parentScale, float taskViewScale,
                 int previewWidth, DeviceProfile dp, PreviewPositionHelper pph) {
-            RectF insets = getInsetsToDrawInFullscreen(pph, dp, mIsTaskbarTransient);
-
-            float currentInsetsLeft = insets.left * fullscreenProgress;
-            float currentInsetsTop = insets.top * fullscreenProgress;
-            float currentInsetsRight = insets.right * fullscreenProgress;
-            float currentInsetsBottom = insets.bottom * fullscreenProgress;
-            mCurrentDrawnInsets.set(
-                    currentInsetsLeft, currentInsetsTop, currentInsetsRight, currentInsetsBottom);
-
             mCurrentDrawnCornerRadius =
                     Utilities.mapRange(fullscreenProgress, mCornerRadius, mWindowCornerRadius)
                             / parentScale / taskViewScale;
-
-            // We scaled the thumbnail to fit the content (excluding insets) within task view width.
-            // Now that we are drawing left/right insets again, we need to scale down to fit them.
-            if (previewWidth > 0) {
-                mScale = previewWidth / (previewWidth + currentInsetsLeft + currentInsetsRight);
-            }
-        }
-
-        /**
-         * Insets to used for clipping the thumbnail (in case it is drawing outside its own space)
-         */
-        private static RectF getInsetsToDrawInFullscreen(PreviewPositionHelper pph,
-                DeviceProfile dp, boolean isTaskbarTransient) {
-            if (dp.isTaskbarPresent && isTaskbarTransient) {
-                return pph.getClippedInsets();
-            }
-            return dp.isTaskbarPresent && !dp.isTaskbarPresentInApps
-                    ? pph.getClippedInsets() : EMPTY_RECT_F;
         }
     }
 
diff --git a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
index bc1b87d..6c0e7dc 100644
--- a/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
+++ b/quickstep/tests/src/com/android/quickstep/FullscreenDrawParamsTest.kt
@@ -16,16 +16,14 @@
 package com.android.quickstep
 
 import android.graphics.Rect
-import android.graphics.RectF
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.launcher3.FakeInvariantDeviceProfileTest
-import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_BOTTOM_OR_RIGHT
-import com.android.launcher3.util.SplitConfigurationOptions.STAGE_POSITION_TOP_OR_LEFT
+import com.android.quickstep.util.TaskCornerRadius
 import com.android.quickstep.views.TaskView.FullscreenDrawParams
 import com.android.systemui.shared.recents.model.ThumbnailData
 import com.android.systemui.shared.recents.utilities.PreviewPositionHelper
-import com.android.wm.shell.util.SplitBounds
+import com.android.systemui.shared.system.QuickStepContract
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.roundToInt
 import org.junit.Before
@@ -50,7 +48,42 @@
     }
 
     @Test
-    fun setFullProgress_currentDrawnInsets_clipTaskbarSizeFromBottomForTablets() {
+    fun setStartProgress_correctCornerRadiusForTablet() {
+        initializeVarsForTablet()
+        val dp = newDP()
+        val previewRect = Rect(0, 0, 100, 100)
+        val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
+        val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
+        val currentRotation = 0
+        val isRtl = false
+
+        mPreviewPositionHelper.updateThumbnailMatrix(
+            previewRect,
+            mThumbnailData,
+            canvasWidth,
+            canvasHeight,
+            dp.widthPx,
+            dp.heightPx,
+            dp.taskbarSize,
+            dp.isTablet,
+            currentRotation,
+            isRtl
+        )
+        params.setProgress(
+            /* fullscreenProgress= */ 0f,
+            /* parentScale= */ 1.0f,
+            /* taskViewScale= */ 1.0f,
+            /* previewWidth= */ 0,
+            dp,
+            mPreviewPositionHelper
+        )
+
+        val expectedRadius = TaskCornerRadius.get(context)
+        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
+    }
+
+    @Test
+    fun setFullProgress_correctCornerRadiusForTablet() {
         initializeVarsForTablet()
         val dp = newDP()
         val previewRect = Rect(0, 0, 100, 100)
@@ -80,122 +113,19 @@
             mPreviewPositionHelper
         )
 
-        val expectedClippedInsets = RectF(0f, 0f, 0f, dp.taskbarSize * TASK_SCALE)
-        assertThat(params.mCurrentDrawnInsets).isEqualTo(expectedClippedInsets)
+        val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
+        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
     }
 
     @Test
-    fun setFullProgress_currentDrawnInsets_clipTaskbarSizeFromBottomForTablets_splitPortrait() {
-        initializeVarsForTablet()
+    fun setStartProgress_correctCornerRadiusForPhone() {
+        initializeVarsForPhone()
         val dp = newDP()
         val previewRect = Rect(0, 0, 100, 100)
         val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
-        val canvasHeight = (dp.heightPx * TASK_SCALE / 2).roundToInt()
-        val currentRotation = 0
-        val isRtl = false
-        // portrait/vertical split apps
-        val dividerSize = 10
-        val splitBounds =
-            SplitBounds(
-                Rect(0, 0, dp.widthPx, (dp.heightPx - dividerSize) / 2),
-                Rect(0, (dp.heightPx + dividerSize) / 2, dp.widthPx, dp.heightPx),
-                0 /*lefTopTaskId*/,
-                0 /*rightBottomTaskId*/
-            )
-        mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
-
-        mPreviewPositionHelper.updateThumbnailMatrix(
-            previewRect,
-            mThumbnailData,
-            canvasWidth,
-            canvasHeight,
-            dp.widthPx,
-            dp.heightPx,
-            dp.taskbarSize,
-            dp.isTablet,
-            currentRotation,
-            isRtl
-        )
-        params.setProgress(
-            /* fullscreenProgress= */ 1.0f,
-            /* parentScale= */ 1.0f,
-            /* taskViewScale= */ 1.0f,
-            /* previewWidth= */ 0,
-            dp,
-            mPreviewPositionHelper
-        )
-
-        // Probably unhelpful, but also unclear how to test otherwise ¯\_(ツ)_/¯
-        val fullscreenTaskHeight =
-            dp.heightPx * (1 - (splitBounds.topTaskPercent + splitBounds.dividerHeightPercent))
-        val canvasScreenRatio = canvasHeight / fullscreenTaskHeight
-        val expectedBottomHint = dp.taskbarSize * canvasScreenRatio
-        assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of(expectedBottomHint)
-    }
-
-    @Test
-    fun setFullProgress_currentDrawnInsets_clipTaskbarSizeFromTopForTablets_splitPortrait() {
-        initializeVarsForTablet()
-        val dp = newDP()
-        val previewRect = Rect(0, 0, 100, 100)
-        val canvasWidth = (dp.widthPx * TASK_SCALE).roundToInt()
-        val canvasHeight = (dp.heightPx * TASK_SCALE / 2).roundToInt()
-        val currentRotation = 0
-        val isRtl = false
-        // portrait/vertical split apps
-        val dividerSize = 10
-        val splitBounds =
-            SplitBounds(
-                Rect(0, 0, dp.widthPx, (dp.heightPx - dividerSize) / 2),
-                Rect(0, (dp.heightPx + dividerSize) / 2, dp.widthPx, dp.heightPx),
-                0 /*lefTopTaskId*/,
-                0 /*rightBottomTaskId*/
-            )
-        mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_TOP_OR_LEFT)
-
-        mPreviewPositionHelper.updateThumbnailMatrix(
-            previewRect,
-            mThumbnailData,
-            canvasWidth,
-            canvasHeight,
-            dp.widthPx,
-            dp.heightPx,
-            dp.taskbarSize,
-            dp.isTablet,
-            currentRotation,
-            isRtl
-        )
-        params.setProgress(
-            /* fullscreenProgress= */ 1.0f,
-            /* parentScale= */ 1.0f,
-            /* taskViewScale= */ 1.0f,
-            /* previewWidth= */ 0,
-            dp,
-            mPreviewPositionHelper
-        )
-
-        assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of((0f))
-    }
-
-    @Test
-    fun setFullProgress_currentDrawnInsets_clipTaskbarSizeFromBottomForTablets_splitLandscape() {
-        initializeVarsForTablet(isLandscape = true)
-        val dp = newDP()
-        val previewRect = Rect(0, 0, 100, 100)
-        val canvasWidth = (dp.widthPx * TASK_SCALE / 2).roundToInt()
         val canvasHeight = (dp.heightPx * TASK_SCALE).roundToInt()
         val currentRotation = 0
         val isRtl = false
-        // portrait/vertical split apps
-        val dividerSize = 10
-        val splitBounds =
-            SplitBounds(
-                Rect(0, 0, (dp.widthPx - dividerSize) / 2, dp.heightPx),
-                Rect((dp.widthPx + dividerSize) / 2, 0, dp.widthPx, dp.heightPx),
-                0 /*lefTopTaskId*/,
-                0 /*rightBottomTaskId*/
-            )
-        mPreviewPositionHelper.setSplitBounds(splitBounds, STAGE_POSITION_BOTTOM_OR_RIGHT)
 
         mPreviewPositionHelper.updateThumbnailMatrix(
             previewRect,
@@ -210,7 +140,7 @@
             isRtl
         )
         params.setProgress(
-            /* fullscreenProgress= */ 1.0f,
+            /* fullscreenProgress= */ 0f,
             /* parentScale= */ 1.0f,
             /* taskViewScale= */ 1.0f,
             /* previewWidth= */ 0,
@@ -218,11 +148,12 @@
             mPreviewPositionHelper
         )
 
-        assertThat(params.mCurrentDrawnInsets.bottom).isWithin(1f).of((dp.taskbarSize * TASK_SCALE))
+        val expectedRadius = TaskCornerRadius.get(context)
+        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
     }
 
     @Test
-    fun setFullProgress_currentDrawnInsets_doNotClipTaskbarSizeFromBottomForPhones() {
+    fun setFullProgress_correctCornerRadiusForPhone() {
         initializeVarsForPhone()
         val dp = newDP()
         val previewRect = Rect(0, 0, 100, 100)
@@ -252,7 +183,7 @@
             mPreviewPositionHelper
         )
 
-        val expectedClippedInsets = RectF(0f, 0f, 0f, 0f)
-        assertThat(params.mCurrentDrawnInsets).isEqualTo(expectedClippedInsets)
+        val expectedRadius = QuickStepContract.getWindowCornerRadius(context)
+        assertThat(params.mCurrentDrawnCornerRadius).isEqualTo(expectedRadius)
     }
 }
diff --git a/res/xml/default_tapl_test_workspace.xml b/res/xml/default_tapl_test_workspace.xml
new file mode 100644
index 0000000..24d76f3
--- /dev/null
+++ b/res/xml/default_tapl_test_workspace.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<!-- Split display specific version of Launcher3/res/xml/default_workspace_4x4.xml -->
+<favorites xmlns:launcher="http://schemas.android.com/apk/res-auto/com.android.launcher3" >
+
+    <!-- Hotseat (We use the screen as the position of the item in the hotseat) -->
+    <favorite
+        launcher:container="-101"
+        launcher:screen="0"
+        launcher:x="0"
+        launcher:y="0"
+        launcher:className="com.google.android.apps.chrome.Main"
+        launcher:packageName="com.android.chrome" />
+
+</favorites>
diff --git a/src/com/android/launcher3/LauncherProvider.java b/src/com/android/launcher3/LauncherProvider.java
index bccb894..e688709 100644
--- a/src/com/android/launcher3/LauncherProvider.java
+++ b/src/com/android/launcher3/LauncherProvider.java
@@ -107,6 +107,7 @@
 
     private static final int TEST_WORKSPACE_LAYOUT_RES_XML = R.xml.default_test_workspace;
     private static final int TEST2_WORKSPACE_LAYOUT_RES_XML = R.xml.default_test2_workspace;
+    private static final int TAPL_WORKSPACE_LAYOUT_RES_XML = R.xml.default_tapl_test_workspace;
 
     static final String EMPTY_DATABASE_CREATED = "EMPTY_DATABASE_CREATED";
 
@@ -410,6 +411,9 @@
                     case LauncherSettings.Settings.ARG_DEFAULT_WORKSPACE_LAYOUT_TEST2:
                         mDefaultWorkspaceLayoutOverride = TEST2_WORKSPACE_LAYOUT_RES_XML;
                         break;
+                    case LauncherSettings.Settings.ARG_DEFAULT_WORKSPACE_LAYOUT_TAPL:
+                        mDefaultWorkspaceLayoutOverride = TAPL_WORKSPACE_LAYOUT_RES_XML;
+                        break;
                     default:
                         mDefaultWorkspaceLayoutOverride = 0;
                         break;
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 66ea616..cef00d9 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -389,6 +389,7 @@
                 "set_use_test_workspace_layout_flag";
         public static final String ARG_DEFAULT_WORKSPACE_LAYOUT_TEST = "default_test_workspace";
         public static final String ARG_DEFAULT_WORKSPACE_LAYOUT_TEST2 = "default_test2_workspace";
+        public static final String ARG_DEFAULT_WORKSPACE_LAYOUT_TAPL = "default_tapl_workspace";
 
         public static final String METHOD_CLEAR_USE_TEST_WORKSPACE_LAYOUT_FLAG =
                 "clear_use_test_workspace_layout_flag";
diff --git a/src/com/android/launcher3/anim/AnimatedFloat.java b/src/com/android/launcher3/anim/AnimatedFloat.java
index b73621d..2380af4 100644
--- a/src/com/android/launcher3/anim/AnimatedFloat.java
+++ b/src/com/android/launcher3/anim/AnimatedFloat.java
@@ -55,6 +55,11 @@
         mUpdateCallback = updateCallback;
     }
 
+    public AnimatedFloat(Runnable updateCallback, float initialValue) {
+        this(updateCallback);
+        value = initialValue;
+    }
+
     /**
      * Returns an animation from the current value to the given value.
      */
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index d1aaef1..b7e6378 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -378,6 +378,11 @@
             "Enables taskbar pinning to allow user to switch between transient and persistent "
                     + "taskbar flavors");
 
+    public static final BooleanFlag ENABLE_WORKSPACE_LOADING_OPTIMIZATION = getDebugFlag(251502424,
+            "ENABLE_WORKSPACE_LOADING_OPTIMIZATION", false, "load the current workspace screen "
+                    + "visible to the user before the rest rather than loading all of them at once."
+    );
+
     public static final BooleanFlag ENABLE_GRID_ONLY_OVERVIEW = getDebugFlag(270397206,
             "ENABLE_GRID_ONLY_OVERVIEW", false,
             "Enable a grid-only overview without a focused task.");
diff --git a/src/com/android/launcher3/logging/StatsLogManager.java b/src/com/android/launcher3/logging/StatsLogManager.java
index 5f6df27..cf710da 100644
--- a/src/com/android/launcher3/logging/StatsLogManager.java
+++ b/src/com/android/launcher3/logging/StatsLogManager.java
@@ -636,6 +636,12 @@
 
         @UiEvent(doc = "User scrolled up on the search result page.")
         LAUNCHER_ALLAPPS_SEARCH_SCROLLED_UP(1286),
+
+        @UiEvent(doc = "User or automatic timeout has hidden transient taskbar.")
+        LAUNCHER_TRANSIENT_TASKBAR_HIDE(1330),
+
+        @UiEvent(doc = "User has swiped upwards from the gesture handle to show transient taskbar.")
+        LAUNCHER_TRANSIENT_TASKBAR_SHOW(1331),
         ;
 
         // ADD MORE
diff --git a/src/com/android/launcher3/model/BaseLauncherBinder.java b/src/com/android/launcher3/model/BaseLauncherBinder.java
index 8519a3e..91ace27 100644
--- a/src/com/android/launcher3/model/BaseLauncherBinder.java
+++ b/src/com/android/launcher3/model/BaseLauncherBinder.java
@@ -27,6 +27,7 @@
 import com.android.launcher3.LauncherAppState;
 import com.android.launcher3.LauncherModel.CallbackTask;
 import com.android.launcher3.LauncherSettings;
+import com.android.launcher3.Workspace;
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.model.BgDataModel.Callbacks;
 import com.android.launcher3.model.BgDataModel.FixedContainerItems;
@@ -42,8 +43,10 @@
 
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.Executor;
 
 /**
@@ -77,6 +80,36 @@
      * Binds all loaded data to actual views on the main thread.
      */
     public void bindWorkspace(boolean incrementBindId) {
+        if (FeatureFlags.ENABLE_WORKSPACE_LOADING_OPTIMIZATION.get()) {
+            DisjointWorkspaceBinder workspaceBinder =
+                    initWorkspaceBinder(incrementBindId, mBgDataModel.collectWorkspaceScreens());
+            workspaceBinder.bindCurrentWorkspacePages();
+            workspaceBinder.bindOtherWorkspacePages();
+        } else {
+            bindWorkspaceAllAtOnce(incrementBindId);
+        }
+    }
+
+    /**
+     * Initializes the WorkspaceBinder for binding.
+     *
+     * @param incrementBindId this is used to stop previously started binding tasks that are
+     *                        obsolete but still queued.
+     * @param workspacePages this allows the Launcher to add the correct workspace screens.
+     */
+    public DisjointWorkspaceBinder initWorkspaceBinder(boolean incrementBindId,
+            IntArray workspacePages) {
+
+        synchronized (mBgDataModel) {
+            if (incrementBindId) {
+                mBgDataModel.lastBindId++;
+            }
+            mMyBindingId = mBgDataModel.lastBindId;
+            return new DisjointWorkspaceBinder(workspacePages);
+        }
+    }
+
+    private void bindWorkspaceAllAtOnce(boolean incrementBindId) {
         // Save a copy of all the bg-thread collections
         ArrayList<ItemInfo> workspaceItems = new ArrayList<>();
         ArrayList<LauncherAppWidgetInfo> appWidgets = new ArrayList<>();
@@ -95,7 +128,7 @@
         }
 
         for (Callbacks cb : mCallbacksList) {
-            new WorkspaceBinder(cb, mUiExecutor, mApp, mBgDataModel, mMyBindingId,
+            new UnifiedWorkspaceBinder(cb, mUiExecutor, mApp, mBgDataModel, mMyBindingId,
                     workspaceItems, appWidgets, extraItems, orderedScreenIds).bind();
         }
     }
@@ -180,7 +213,7 @@
         return idleLock;
     }
 
-    private class WorkspaceBinder {
+    private class UnifiedWorkspaceBinder {
 
         private final Executor mUiExecutor;
         private final Callbacks mCallbacks;
@@ -194,7 +227,7 @@
         private final IntArray mOrderedScreenIds;
         private final ArrayList<FixedContainerItems> mExtraItems;
 
-        WorkspaceBinder(Callbacks callbacks,
+        UnifiedWorkspaceBinder(Callbacks callbacks,
                 Executor uiExecutor,
                 LauncherAppState app,
                 BgDataModel bgDataModel,
@@ -320,4 +353,115 @@
             });
         }
     }
+
+    private class DisjointWorkspaceBinder {
+        private final IntArray mOrderedScreenIds;
+        private final IntSet mCurrentScreenIds = new IntSet();
+        private final Set<Integer> mBoundItemIds = new HashSet<>();
+
+        protected DisjointWorkspaceBinder(IntArray orderedScreenIds) {
+            mOrderedScreenIds = orderedScreenIds;
+
+            for (Callbacks cb : mCallbacksList) {
+                mCurrentScreenIds.addAll(cb.getPagesToBindSynchronously(orderedScreenIds));
+            }
+            if (mCurrentScreenIds.size() == 0) {
+                mCurrentScreenIds.add(Workspace.FIRST_SCREEN_ID);
+            }
+        }
+
+        /**
+         * Binds the currently loaded items in the Data Model. Also signals to the Callbacks[]
+         * that these items have been bound and their respective screens are ready to be shown.
+         *
+         * If this method is called after all the items on the workspace screen have already been
+         * loaded, it will bind all workspace items immediately, and bindOtherWorkspacePages() will
+         * not bind any items.
+         */
+        protected void bindCurrentWorkspacePages() {
+            // Save a copy of all the bg-thread collections
+            ArrayList<ItemInfo> workspaceItems;
+            ArrayList<LauncherAppWidgetInfo> appWidgets;
+
+            synchronized (mBgDataModel) {
+                workspaceItems = new ArrayList<>(mBgDataModel.workspaceItems);
+                appWidgets = new ArrayList<>(mBgDataModel.appWidgets);
+            }
+
+            workspaceItems.forEach(it -> mBoundItemIds.add(it.id));
+            appWidgets.forEach(it -> mBoundItemIds.add(it.id));
+
+            sortWorkspaceItemsSpatially(mApp.getInvariantDeviceProfile(), workspaceItems);
+
+            // Tell the workspace that we're about to start binding items
+            executeCallbacksTask(c -> {
+                c.clearPendingBinds();
+                c.startBinding();
+            }, mUiExecutor);
+
+            // Bind workspace screens
+            executeCallbacksTask(c -> c.bindScreens(mOrderedScreenIds), mUiExecutor);
+
+            bindWorkspaceItems(workspaceItems);
+            bindAppWidgets(appWidgets);
+
+            executeCallbacksTask(c -> {
+                MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+                c.onInitialBindComplete(mCurrentScreenIds, new RunnableList());
+            }, mUiExecutor);
+        }
+
+        protected void bindOtherWorkspacePages() {
+            // Save a copy of all the bg-thread collections
+            ArrayList<ItemInfo> workspaceItems;
+            ArrayList<LauncherAppWidgetInfo> appWidgets;
+
+            synchronized (mBgDataModel) {
+                workspaceItems = new ArrayList<>(mBgDataModel.workspaceItems);
+                appWidgets = new ArrayList<>(mBgDataModel.appWidgets);
+            }
+
+            workspaceItems.removeIf(it -> mBoundItemIds.contains(it.id));
+            appWidgets.removeIf(it -> mBoundItemIds.contains(it.id));
+
+            sortWorkspaceItemsSpatially(mApp.getInvariantDeviceProfile(), workspaceItems);
+
+            bindWorkspaceItems(workspaceItems);
+            bindAppWidgets(appWidgets);
+
+            executeCallbacksTask(c -> c.finishBindingItems(mCurrentScreenIds), mUiExecutor);
+            mUiExecutor.execute(() -> {
+                MODEL_EXECUTOR.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
+                ItemInstallQueue.INSTANCE.get(mApp.getContext())
+                        .resumeModelPush(FLAG_LOADER_RUNNING);
+            });
+
+            for (Callbacks cb : mCallbacksList) {
+                cb.bindStringCache(mBgDataModel.stringCache.clone());
+            }
+        }
+
+        private void bindWorkspaceItems(final ArrayList<ItemInfo> workspaceItems) {
+            // Bind the workspace items
+            int count = workspaceItems.size();
+            for (int i = 0; i < count; i += ITEMS_CHUNK) {
+                final int start = i;
+                final int chunkSize = (i + ITEMS_CHUNK <= count) ? ITEMS_CHUNK : (count - i);
+                executeCallbacksTask(
+                        c -> c.bindItems(workspaceItems.subList(start, start + chunkSize), false),
+                        mUiExecutor);
+            }
+        }
+
+        private void bindAppWidgets(List<LauncherAppWidgetInfo> appWidgets) {
+            // Bind the widgets, one at a time
+            int count = appWidgets.size();
+            for (int i = 0; i < count; i++) {
+                final ItemInfo widget = appWidgets.get(i);
+                executeCallbacksTask(
+                        c -> c.bindItems(Collections.singletonList(widget), false),
+                        mUiExecutor);
+            }
+        }
+    }
 }
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index c20ac17..43ca2a6 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -463,6 +463,7 @@
             return;
         }
         mSystemShortcutContainer = inflateAndAdd(systemShortcutContainerLayout, this);
+        mWidgetContainer = mSystemShortcutContainer;
         for (int i = 0; i < systemShortcuts.size(); i++) {
             initializeSystemShortcut(
                     systemShortcutLayout,
diff --git a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
index 295baa3..050e88f 100644
--- a/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
+++ b/src/com/android/launcher3/touch/PortraitPagedViewHandler.java
@@ -582,8 +582,7 @@
                 ? splitInfo.dividerHeightPercent
                 : splitInfo.dividerWidthPercent;
 
-        int deviceHeightWithoutTaskbar = dp.availableHeightPx - dp.taskbarSize;
-        float scale = (float) outRect.height() / deviceHeightWithoutTaskbar;
+        float scale = (float) outRect.height() / dp.availableHeightPx;
         float topTaskHeight = dp.availableHeightPx * topLeftTaskPercent;
         float scaledTopTaskHeight = topTaskHeight * scale;
         float dividerHeight = dp.availableHeightPx * dividerBarPercent;
@@ -639,8 +638,7 @@
             // Reset unused translations
             primarySnapshot.setTranslationY(0);
         } else {
-            int deviceHeightWithoutTaskbar = dp.availableHeightPx - dp.taskbarSize;
-            float scale = (float) totalThumbnailHeight / deviceHeightWithoutTaskbar;
+            float scale = (float) totalThumbnailHeight / dp.availableHeightPx;
             float topTaskHeight = dp.availableHeightPx * taskPercent;
             float finalDividerHeight = dividerBar * scale;
             float scaledTopTaskHeight = topTaskHeight * scale;
diff --git a/src/com/android/launcher3/views/AbstractSlideInView.java b/src/com/android/launcher3/views/AbstractSlideInView.java
index ebae00d..cb6a46c 100644
--- a/src/com/android/launcher3/views/AbstractSlideInView.java
+++ b/src/com/android/launcher3/views/AbstractSlideInView.java
@@ -76,6 +76,7 @@
             };
     protected static final float TRANSLATION_SHIFT_CLOSED = 1f;
     protected static final float TRANSLATION_SHIFT_OPENED = 0f;
+    private static final float VIEW_NO_SCALE = 1f;
 
     protected final T mActivityContext;
 
@@ -93,7 +94,8 @@
     protected @Nullable OnCloseListener mOnCloseBeginListener;
     protected List<OnCloseListener> mOnCloseListeners = new ArrayList<>();
 
-    private final AnimatedFloat mSlidInViewScale = new AnimatedFloat(this::onScaleProgressChanged);
+    private final AnimatedFloat mSlideInViewScale =
+            new AnimatedFloat(this::onScaleProgressChanged, VIEW_NO_SCALE);
     private boolean mIsBackProgressing;
     @Nullable private Drawable mContentBackground;
 
@@ -184,12 +186,12 @@
         float deceleratedProgress =
                 Interpolators.PREDICTIVE_BACK_DECELERATED_EASE.getInterpolation(progress);
         mIsBackProgressing = progress > 0f;
-        mSlidInViewScale.updateValue(PREDICTIVE_BACK_MIN_SCALE
+        mSlideInViewScale.updateValue(PREDICTIVE_BACK_MIN_SCALE
                 + (1 - PREDICTIVE_BACK_MIN_SCALE) * (1 - deceleratedProgress));
     }
 
     private void onScaleProgressChanged() {
-        float scaleProgress = mSlidInViewScale.value;
+        float scaleProgress = mSlideInViewScale.value;
         SCALE_PROPERTY.set(this, scaleProgress);
         setClipChildren(!mIsBackProgressing);
         mContent.setClipChildren(!mIsBackProgressing);
@@ -209,7 +211,7 @@
     }
 
     protected void animateSlideInViewToNoScale() {
-        mSlidInViewScale.animateToValue(1f)
+        mSlideInViewScale.animateToValue(1f)
                 .setDuration(REVERT_SWIPE_ALL_APPS_TO_HOME_ANIMATION_DURATION_MS)
                 .start();
     }
diff --git a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
index c69ec2c..f036b3e 100644
--- a/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
+++ b/tests/shared/com/android/launcher3/testing/shared/TestProtocol.java
@@ -107,6 +107,7 @@
     public static final String REQUEST_CLEAR_DATA = "clear-data";
     public static final String REQUEST_USE_TEST_WORKSPACE_LAYOUT = "use-test-workspace-layout";
     public static final String REQUEST_USE_TEST2_WORKSPACE_LAYOUT = "use-test2-workspace-layout";
+    public static final String REQUEST_USE_TAPL_WORKSPACE_LAYOUT = "use-tapl-workspace-layout";
     public static final String REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT =
             "use-default-workspace-layout";
     public static final String REQUEST_HOTSEAT_ICON_NAMES = "get-hotseat-icon-names";
diff --git a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
index 528f7ac..d07c6c2 100644
--- a/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
+++ b/tests/src/com/android/launcher3/ui/BubbleTextViewTest.java
@@ -102,120 +102,150 @@
 
     @Test
     public void testEmptyString_flagOn() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true);
-        mItemInfoWithIcon.title = EMPTY_STRING;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(ONE_LINE, mBubbleTextView.getMaxLines());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            mItemInfoWithIcon.title = EMPTY_STRING;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(ONE_LINE, mBubbleTextView.getMaxLines());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testEmptyString_flagOff() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false);
-        mItemInfoWithIcon.title = EMPTY_STRING;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            mItemInfoWithIcon.title = EMPTY_STRING;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testStringWithSpaceLongerThanCharLimit_flagOn() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true);
-        // test string: "Battery Stats"
-        mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "Battery Stats"
+            mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testStringWithSpaceLongerThanCharLimit_flagOff() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false);
-        // test string: "Battery Stats"
-        mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "Battery Stats"
+            mItemInfoWithIcon.title = TEST_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringNoSpaceLongerThanCharLimit_flagOn() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true);
-        // test string: "flutterappflorafy"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "flutterappflorafy"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringNoSpaceLongerThanCharLimit_flagOff() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false);
-        // test string: "flutterappflorafy"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "flutterappflorafy"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_NO_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw  new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringWithSpaceLongerThanCharLimit_flagOn() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true);
-        // test string: "System UWB Field Test"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "System UWB Field Test"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw  new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringWithSpaceLongerThanCharLimit_flagOff() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false);
-        // test string: "System UWB Field Test"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "System UWB Field Test"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_WITH_SPACE_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw  new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringSymbolLongerThanCharLimit_flagOn() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true);
-        // test string: "LEGO®Builder"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, true)) {
+            // test string: "LEGO®Builder"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(TWO_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw  new RuntimeException(e);
+        }
     }
 
     @Test
     public void testLongStringSymbolLongerThanCharLimit_flagOff() {
-        TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false);
-        // test string: "LEGO®Builder"
-        mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
-        mBubbleTextView.applyLabel(mItemInfoWithIcon);
-        mBubbleTextView.setTypeface(Typeface.MONOSPACE);
-        mBubbleTextView.measure(mLimitedWidth, 0);
-        mBubbleTextView.onPreDraw();
-        assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        try (AutoCloseable flag = TestUtil.overrideFlag(ENABLE_TWOLINE_ALLAPPS, false)) {
+            // test string: "LEGO®Builder"
+            mItemInfoWithIcon.title = TEST_LONG_STRING_SYMBOL_LONGER_THAN_CHAR_LIMIT;
+            mBubbleTextView.applyLabel(mItemInfoWithIcon);
+            mBubbleTextView.setTypeface(Typeface.MONOSPACE);
+            mBubbleTextView.measure(mLimitedWidth, 0);
+            mBubbleTextView.onPreDraw();
+            assertEquals(ONE_LINE, mBubbleTextView.getLineCount());
+        } catch (Exception e) {
+            throw  new RuntimeException(e);
+        }
     }
 
     @Test
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 5f516eb..f910a92 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -225,6 +225,10 @@
     @Test
     @ScreenRecord // b/202433017
     public void testWorkspace() throws Exception {
+        // Make sure there is an instance of chrome on the hotseat
+        mLauncher.useTaplWorkspaceLayoutOnReload();
+        clearLauncherData();
+
         final Workspace workspace = mLauncher.getWorkspace();
 
         // Test that ensureWorkspaceIsScrollable adds a page by dragging an icon there.
@@ -506,7 +510,6 @@
 
     @Test
     @PortraitLandscape
-    @ScreenRecord // (b/256659409)
     public void testUninstallFromAllApps() throws Exception {
         installDummyAppAndWaitForUIUpdate();
         try {
@@ -515,6 +518,8 @@
             allApps.freeze();
             try {
                 workspace = allApps.getAppIcon(DUMMY_APP_NAME).uninstall();
+                // After the toast clears, then the model tries to commit the uninstall transaction
+                mLauncher.waitForModelQueueCleared();
             } finally {
                 allApps.unfreeze();
             }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 52994a5..5c4b707 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1860,6 +1860,15 @@
         getTestInfo(TestProtocol.REQUEST_USE_TEST2_WORKSPACE_LAYOUT);
     }
 
+
+    /**
+     * Reloads the workspace with a test layout that includes the chrome Activity app icon on the
+     * hotseat.
+     */
+    public void useTaplWorkspaceLayoutOnReload() {
+        getTestInfo(TestProtocol.REQUEST_USE_TAPL_WORKSPACE_LAYOUT);
+    }
+
     /** Reloads the workspace with the default layout defined by the user's grid size selection. */
     public void useDefaultWorkspaceLayoutOnReload() {
         getTestInfo(TestProtocol.REQUEST_USE_DEFAULT_WORKSPACE_LAYOUT);