Merge "Extend/shrink work button when scrolling" into tm-qpr-dev
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index 585f01e..28f7c5d 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -37,4 +37,7 @@
     <!-- All Set page-->
     <dimen name="allset_page_allset_text_size">42sp</dimen>
     <dimen name="allset_page_swipe_up_text_size">16sp</dimen>
+
+    <!-- Transient taskbar -->
+    <dimen name="transient_taskbar_size">76dp</dimen>
 </resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 7a3c35f..ad77768 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -281,8 +281,7 @@
     <dimen name="taskbar_icon_size_kids">32dp</dimen>
 
     <!-- Transient taskbar -->
-    <dimen name="transient_taskbar_size">76dp</dimen>
-    <dimen name="transient_taskbar_two_panels_size">72dp</dimen>
+    <dimen name="transient_taskbar_size">72dp</dimen>
     <dimen name="transient_taskbar_margin">24dp</dimen>
     <dimen name="transient_taskbar_shadow_blur">40dp</dimen>
     <dimen name="transient_taskbar_key_shadow_distance">10dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
index a205d19..bbc0627 100644
--- a/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
+++ b/quickstep/src/com/android/launcher3/statehandlers/DesktopVisibilityController.java
@@ -43,7 +43,7 @@
      */
     private boolean isDesktopModeSupported() {
         return SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false)
-            || SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
+                || SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
     }
 
     /**
@@ -81,7 +81,9 @@
         StatefulActivity<LauncherState> activity =
                 QuickstepLauncher.ACTIVITY_TRACKER.getCreatedActivity();
         View workspaceView = mLauncher.getWorkspace();
-        if (activity == null || workspaceView == null || !isDesktopModeSupported()) return;
+        if (activity == null || workspaceView == null || !isDesktopModeSupported()) {
+            return;
+        }
 
         if (mFreeformTasksVisible) {
             workspaceView.setVisibility(View.INVISIBLE);
@@ -93,7 +95,12 @@
         } else {
             workspaceView.setVisibility(View.VISIBLE);
             // If freeform isn't visible ensure that launcher appears resumed to behave normally.
-            activity.setResumed();
+            // Check activity state before calling setResumed(). Launcher may have been actually
+            // paused (eg fullscreen task moved to front).
+            // In this case we should not mark the activity as resumed.
+            if (activity.isResumed()) {
+                activity.setResumed();
+            }
         }
     }
 }
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
index 6d74526..731eea7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarActivityContext.java
@@ -284,9 +284,7 @@
     private void updateIconSize(Resources resources) {
         mDeviceProfile.iconSizePx = resources.getDimensionPixelSize(
                 DisplayController.isTransientTaskbar(this)
-                    ? mDeviceProfile.isTwoPanels
-                            ? R.dimen.transient_taskbar_two_panels_icon_size
-                            : R.dimen.transient_taskbar_icon_size
+                    ? R.dimen.transient_taskbar_icon_size
                     : R.dimen.taskbar_icon_size);
         mDeviceProfile.updateIconSize(1f, resources);
     }
@@ -694,9 +692,7 @@
         }
 
         if (DisplayController.isTransientTaskbar(this)) {
-            int taskbarSize = resources.getDimensionPixelSize(mDeviceProfile.isTwoPanels
-                    ? R.dimen.transient_taskbar_two_panels_size
-                    : R.dimen.transient_taskbar_size);
+            int taskbarSize = resources.getDimensionPixelSize(R.dimen.transient_taskbar_size);
             return taskbarSize
                     + (2 * resources.getDimensionPixelSize(R.dimen.transient_taskbar_margin))
                     + resources.getDimensionPixelSize(R.dimen.transient_taskbar_shadow_blur);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 29b8ee3..c269648 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -202,9 +202,7 @@
             Resources resources = mActivity.getResources();
             boolean isTransientTaskbar = DisplayController.isTransientTaskbar(mActivity);
             mUnstashedHeight = resources.getDimensionPixelSize(isTransientTaskbar
-                    ? (mActivity.getDeviceProfile().isTwoPanels
-                            ? R.dimen.transient_taskbar_two_panels_size
-                            : R.dimen.transient_taskbar_size)
+                    ? R.dimen.transient_taskbar_size
                     : R.dimen.taskbar_size);
             mStashedHeight = resources.getDimensionPixelSize(isTransientTaskbar
                     ? R.dimen.transient_taskbar_stashed_size
diff --git a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
index a07e4d7..bb76846 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/QuickstepLauncher.java
@@ -141,6 +141,7 @@
 import com.android.quickstep.util.SplitToWorkspaceController;
 import com.android.quickstep.util.SplitWithKeyboardShortcutController;
 import com.android.quickstep.util.TISBindHelper;
+import com.android.quickstep.views.DesktopTaskView;
 import com.android.quickstep.views.OverviewActionsView;
 import com.android.quickstep.views.RecentsView;
 import com.android.quickstep.views.TaskView;
@@ -664,6 +665,20 @@
     }
 
     @Override
+    public void setResumed() {
+        if (DesktopTaskView.DESKTOP_IS_PROTO2_ENABLED) {
+            DesktopVisibilityController controller = mDesktopVisibilityController;
+            if (controller != null && controller.areFreeformTasksVisible()) {
+                // Return early to skip setting activity to appear as resumed
+                // TODO(b/255649902): shouldn't be needed when we have a separate launcher state
+                //  for desktop that we can use to control other parts of launcher
+                return;
+            }
+        }
+        super.setResumed();
+    }
+
+    @Override
     protected void onDeferredResumed() {
         super.onDeferredResumed();
         handlePendingActivityRequest();
diff --git a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
index 308249c..c878278 100644
--- a/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
+++ b/quickstep/src/com/android/quickstep/views/DesktopTaskView.java
@@ -59,10 +59,14 @@
 // TODO(b/249371338): TaskView needs to be refactored to have better support for N tasks.
 public class DesktopTaskView extends TaskView {
 
+    /** Flag to indicate whether desktop windowing proto 2 is enabled */
+    public static final boolean DESKTOP_IS_PROTO2_ENABLED = SystemProperties.getBoolean(
+            "persist.wm.debug.desktop_mode_2", false);
+
     /** Flags to indicate whether desktop mode is available on the device */
     public static final boolean DESKTOP_MODE_SUPPORTED =
             SystemProperties.getBoolean("persist.wm.debug.desktop_mode", false)
-                    || SystemProperties.getBoolean("persist.wm.debug.desktop_mode_2", false);
+                    || DESKTOP_IS_PROTO2_ENABLED;
 
     private static final String TAG = DesktopTaskView.class.getSimpleName();
 
diff --git a/res/values-sw720dp/dimens.xml b/res/values-sw720dp/dimens.xml
index 09b2d6f..40e49f1 100644
--- a/res/values-sw720dp/dimens.xml
+++ b/res/values-sw720dp/dimens.xml
@@ -46,4 +46,7 @@
 
     <!--  Folder spaces  -->
     <dimen name="folder_footer_horiz_padding">24dp</dimen>
+
+    <!-- Transient taskbar -->
+    <dimen name="transient_taskbar_icon_size">57dp</dimen>
 </resources>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 7df5a9e..b57eb02 100644
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -366,11 +366,9 @@
     <dimen name="max_hotseat_icon_space">50dp</dimen>
     <dimen name="min_hotseat_qsb_width">0dp</dimen>
     <dimen name="taskbar_icon_size">44dp</dimen>
-    <dimen name="transient_taskbar_icon_size">57dp</dimen>
-    <dimen name="transient_taskbar_two_panels_icon_size">50dp</dimen>
+    <dimen name="transient_taskbar_icon_size">50dp</dimen>
     <!-- Transient taskbar (placeholders to compile in Launcher3 without Quickstep) -->
     <dimen name="transient_taskbar_size">0dp</dimen>
-    <dimen name="transient_taskbar_two_panels_size">0dp</dimen>
     <dimen name="transient_taskbar_margin">0dp</dimen>
     <dimen name="transient_taskbar_shadow_blur">0dp</dimen>
     <dimen name="transient_taskbar_key_shadow_distance">0dp</dimen>
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index b95b0af..25520e1 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -325,9 +325,7 @@
 
         if (isTaskbarPresent) {
             if (DisplayController.isTransientTaskbar(context)) {
-                taskbarSize = res.getDimensionPixelSize(isTwoPanels
-                        ? R.dimen.transient_taskbar_two_panels_size
-                        : R.dimen.transient_taskbar_size);
+                taskbarSize = res.getDimensionPixelSize(R.dimen.transient_taskbar_size);
                 stashedTaskbarSize =
                         res.getDimensionPixelSize(R.dimen.transient_taskbar_stashed_size);
                 transientTaskbarMargin =
@@ -1050,12 +1048,9 @@
     }
 
     private void updateFolderCellSize(float scale, Resources res) {
-        float invIconSizeDp = isVerticalBarLayout()
-                ? inv.iconSize[INDEX_LANDSCAPE]
-                : inv.iconSize[INDEX_DEFAULT];
+        float invIconSizeDp = inv.iconSize[mTypeIndex];
         folderChildIconSizePx = Math.max(1, pxFromDp(invIconSizeDp, mMetrics, scale));
-        folderChildTextSizePx =
-                pxFromSp(inv.iconTextSize[INDEX_DEFAULT], mMetrics, scale);
+        folderChildTextSizePx = pxFromSp(inv.iconTextSize[mTypeIndex], mMetrics, scale);
         folderLabelTextSizePx = Math.max(pxFromSp(MIN_FOLDER_TEXT_SIZE_SP, mMetrics),
                 (int) (folderChildTextSizePx * folderLabelTextScale));
 
@@ -1376,7 +1371,7 @@
     public int getOverviewActionsClaimedSpaceBelow() {
         if (isTaskbarPresent) {
             if (FeatureFlags.ENABLE_TASKBAR_IN_OVERVIEW.get()) {
-                return taskbarSize + transientTaskbarMargin;
+                return taskbarSize + transientTaskbarMargin * 2;
             }
 
             return isGestureMode
@@ -1647,6 +1642,8 @@
                 overviewActionsTopMarginPx));
         writer.println(prefix + pxToDpStr("overviewActionsHeight",
                 overviewActionsHeight));
+        writer.println(prefix + pxToDpStr("overviewActionsClaimedSpaceBelow",
+                getOverviewActionsClaimedSpaceBelow()));
         writer.println(prefix + pxToDpStr("overviewActionsButtonSpacing",
                 overviewActionsButtonSpacing));
         writer.println(prefix + pxToDpStr("overviewPageSpacing", overviewPageSpacing));
diff --git a/src/com/android/launcher3/LauncherSettings.java b/src/com/android/launcher3/LauncherSettings.java
index 932f98a..6ea331d 100644
--- a/src/com/android/launcher3/LauncherSettings.java
+++ b/src/com/android/launcher3/LauncherSettings.java
@@ -207,12 +207,9 @@
         public static final int CONTAINER_BOTTOM_WIDGETS_TRAY = -112;
         public static final int CONTAINER_PIN_WIDGETS = -113;
         public static final int CONTAINER_WALLPAPERS = -114;
-        // Represents search results view.
-        public static final int CONTAINER_SEARCH_RESULTS = -106;
         public static final int CONTAINER_SHORTCUTS = -107;
         public static final int CONTAINER_SETTINGS = -108;
         public static final int CONTAINER_TASKSWITCHER = -109;
-        public static final int CONTAINER_QSB = -110;
 
         // Represents any of the extended containers implemented in non-AOSP variants.
         public static final int EXTENDED_CONTAINERS = -200;
@@ -226,7 +223,6 @@
                 case CONTAINER_PREDICTION: return "prediction";
                 case CONTAINER_ALL_APPS: return "all_apps";
                 case CONTAINER_WIDGETS_TRAY: return "widgets_tray";
-                case CONTAINER_SEARCH_RESULTS: return "search_result";
                 case CONTAINER_SHORTCUTS: return "shortcuts";
                 default: return String.valueOf(container);
             }
diff --git a/src/com/android/launcher3/config/FeatureFlags.java b/src/com/android/launcher3/config/FeatureFlags.java
index 4658320..b46e43f 100644
--- a/src/com/android/launcher3/config/FeatureFlags.java
+++ b/src/com/android/launcher3/config/FeatureFlags.java
@@ -373,6 +373,10 @@
             "Enable the ability to generate monochromatic icons, if it is not provided by the app"
     );
 
+    public static final BooleanFlag ENABLE_TASKBAR_EDU_TOOLTIP = getDebugFlag(
+            "ENABLE_TASKBAR_EDU_TOOLTIP", false,
+            "Enable the tooltip version of the Taskbar education flow.");
+
     public static void initialize(Context context) {
         synchronized (sDebugFlags) {
             for (DebugFlag flag : sDebugFlags) {
diff --git a/src/com/android/launcher3/graphics/PreloadIconDrawable.java b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
index 0eb86b1..9a961ca 100644
--- a/src/com/android/launcher3/graphics/PreloadIconDrawable.java
+++ b/src/com/android/launcher3/graphics/PreloadIconDrawable.java
@@ -17,31 +17,41 @@
 
 package com.android.launcher3.graphics;
 
+import static com.android.launcher3.anim.Interpolators.LINEAR;
+import static com.android.launcher3.config.FeatureFlags.ENABLE_DOWNLOAD_APP_UX_V2;
+
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
+import android.graphics.Color;
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.Path;
 import android.graphics.PathMeasure;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffColorFilter;
 import android.graphics.Rect;
+import android.os.SystemClock;
 import android.util.Property;
 
 import com.android.launcher3.R;
 import com.android.launcher3.Utilities;
-import com.android.launcher3.anim.Interpolators;
 import com.android.launcher3.icons.FastBitmapDrawable;
 import com.android.launcher3.icons.GraphicsUtils;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
 import com.android.launcher3.util.Themes;
+import com.android.launcher3.util.window.RefreshRateTracker;
+
+import java.util.WeakHashMap;
+import java.util.function.Function;
 
 /**
  * Extension of {@link FastBitmapDrawable} which shows a progress bar around the icon.
  */
-public class PreloadIconDrawable extends FastBitmapDrawable {
+public class PreloadIconDrawable extends FastBitmapDrawable implements Runnable {
 
     private static final Property<PreloadIconDrawable, Float> INTERNAL_STATE =
             new Property<PreloadIconDrawable, Float>(Float.TYPE, "internalStateProgress") {
@@ -67,12 +77,20 @@
     // Duration = COMPLETE_ANIM_FRACTION * DURATION_SCALE
     private static final float COMPLETE_ANIM_FRACTION = 0.3f;
 
-    private static final float SMALL_SCALE = 0.7f;
+    private static final float SMALL_SCALE = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 0.85f : 0.7f;
     private static final float PROGRESS_STROKE_SCALE = 0.075f;
 
     private static final int PRELOAD_ACCENT_COLOR_INDEX = 0;
     private static final int PRELOAD_BACKGROUND_COLOR_INDEX = 1;
 
+    private static final int ALPHA_DURATION_MILLIS = 3000;
+    private static final float OVERLAY_ALPHA_RANGE = 127.5f;
+    private static final long WAVE_MOTION_DELAY_FACTOR_MILLIS = 100;
+    private static final WeakHashMap<Integer, PorterDuffColorFilter> COLOR_FILTER_MAP =
+            new WeakHashMap<>();
+    public static final Function<Integer, PorterDuffColorFilter> FILTER_FACTORY =
+            currArgb -> new PorterDuffColorFilter(currArgb, PorterDuff.Mode.SRC_ATOP);
+
     private final Matrix mTmpMatrix = new Matrix();
     private final PathMeasure mPathMeasure = new PathMeasure();
 
@@ -96,6 +114,9 @@
 
     private boolean mRanFinishAnimation;
 
+    private int mOverlayAlpha = 127;
+    private int mRefreshRateMillis;
+
     // Progress of the internal state. [0, 1] indicates the fraction of completed progress,
     // [1, (1 + COMPLETE_ANIM_FRACTION)] indicates the progress of zoom animation.
     private float mInternalStateProgress;
@@ -109,14 +130,16 @@
                 info,
                 IconPalette.getPreloadProgressColor(context, info.bitmap.color),
                 getPreloadColors(context),
-                Utilities.isDarkTheme(context));
+                Utilities.isDarkTheme(context),
+                getRefreshRateMillis(context));
     }
 
     public PreloadIconDrawable(
             ItemInfoWithIcon info,
             int indicatorColor,
             int[] preloadColors,
-            boolean isDarkMode) {
+            boolean isDarkMode,
+            int refreshRateMillis) {
         super(info.bitmap);
         mItem = info;
         mShapePath = GraphicsUtils.getShapePath(DEFAULT_PATH_SIZE);
@@ -130,6 +153,7 @@
         mSystemAccentColor = preloadColors[PRELOAD_ACCENT_COLOR_INDEX];
         mSystemBackgroundColor = preloadColors[PRELOAD_BACKGROUND_COLOR_INDEX];
         mIsDarkMode = isDarkMode;
+        mRefreshRateMillis = refreshRateMillis;
 
         setLevel(info.getProgressLevel());
         setIsStartable(info.isAppStartable());
@@ -178,11 +202,17 @@
         canvas.scale(mIconScale, mIconScale, bounds.exactCenterX(), bounds.exactCenterY());
         super.drawInternal(canvas, bounds);
         canvas.restoreToCount(saveCount);
+
+        if (ENABLE_DOWNLOAD_APP_UX_V2.get() && mInternalStateProgress == 0) {
+            reschedule();
+        }
     }
 
     @Override
     protected void updateFilter() {
-        setAlpha(mIsDisabled ? DISABLED_ICON_ALPHA : MAX_PAINT_ALPHA);
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+            setAlpha(mIsDisabled ? DISABLED_ICON_ALPHA : MAX_PAINT_ALPHA);
+        }
     }
 
     /**
@@ -237,7 +267,7 @@
             mCurrentAnim = ObjectAnimator.ofFloat(this, INTERNAL_STATE, finalProgress);
             mCurrentAnim.setDuration(
                     (long) ((finalProgress - mInternalStateProgress) * DURATION_SCALE));
-            mCurrentAnim.setInterpolator(Interpolators.LINEAR);
+            mCurrentAnim.setInterpolator(LINEAR);
             if (isFinish) {
                 mCurrentAnim.addListener(new AnimatorListenerAdapter() {
                     @Override
@@ -253,13 +283,13 @@
     /**
      * Sets the internal progress and updates the UI accordingly
      *   for progress <= 0:
-     *     - icon in the small scale and disabled state
-     *     - progress track is visible
+     *     - icon with pending motion
+     *     - progress track is not visible
      *     - progress bar is not visible
-     *   for 0 < progress < 1
-     *     - icon in the small scale and disabled state
+     *   for progress < 1
+     *     - icon without pending motion
      *     - progress track is visible
-     *     - progress bar is visible with dominant color. Progress bar is drawn as a fraction of
+     *     - progress bar is visible. Progress bar is drawn as a fraction of
      *       {@link #mScaledTrackPath}.
      *       @see PathMeasure#getSegment(float, float, Path, boolean)
      *   for 1 <= progress < (1 + COMPLETE_ANIM_FRACTION)
@@ -273,16 +303,18 @@
     private void setInternalProgress(float progress) {
         mInternalStateProgress = progress;
         if (progress <= 0) {
-            mIconScale = SMALL_SCALE;
+            mIconScale = ENABLE_DOWNLOAD_APP_UX_V2.get() ? 1 : SMALL_SCALE;
             mScaledTrackPath.reset();
             mTrackAlpha = MAX_PAINT_ALPHA;
-        }
-
-        if (progress < 1 && progress > 0) {
+        } else if (progress < 1) {
             mPathMeasure.getSegment(0, progress * mTrackLength, mScaledProgressPath, true);
+            if (ENABLE_DOWNLOAD_APP_UX_V2.get()) {
+                mPaint.setColorFilter(null);
+                mPathMeasure.getSegment(0, mTrackLength, mScaledTrackPath, true);
+            }
             mIconScale = SMALL_SCALE;
             mTrackAlpha = MAX_PAINT_ALPHA;
-        } else if (progress >= 1) {
+        } else {
             setIsDisabled(mItem.isDisabled());
             mScaledTrackPath.set(mScaledProgressPath);
             float fraction = (progress - 1) / COMPLETE_ANIM_FRACTION;
@@ -310,6 +342,10 @@
         return preloadColors;
     }
 
+    private static int getRefreshRateMillis(Context context) {
+        return RefreshRateTracker.getSingleFrameMs(context);
+    }
+
     /**
      * Returns a FastBitmapDrawable with the icon.
      */
@@ -325,7 +361,75 @@
                 mItem,
                 mIndicatorColor,
                 new int[] {mSystemAccentColor, mSystemBackgroundColor},
-                mIsDarkMode);
+                mIsDarkMode,
+                mRefreshRateMillis);
+    }
+
+    @Override
+    public void run() {
+        if (!ENABLE_DOWNLOAD_APP_UX_V2.get() || mInternalStateProgress > 0) {
+            return;
+        }
+        if (applyPendingIconOverlay()) {
+            invalidateSelf();
+        } else {
+            reschedule();
+        }
+    }
+
+    @Override
+    public boolean setVisible(boolean visible, boolean restart) {
+        boolean result = super.setVisible(visible, restart);
+        if (visible) {
+            reschedule();
+        } else {
+            unscheduleSelf(this);
+        }
+        return result;
+    }
+
+    private void reschedule() {
+        unscheduleSelf(this);
+
+        if (!isVisible()) {
+            return;
+        }
+
+        final long upTime = SystemClock.uptimeMillis();
+        scheduleSelf(this, upTime - ((upTime % mRefreshRateMillis)) + mRefreshRateMillis);
+    }
+
+
+    /**
+     * Apply an overlay on the pending icon with cascading motion based on its position.
+     * Returns {@code true} if the icon alpha is updated, so that we re-draw.
+     */
+    private boolean applyPendingIconOverlay() {
+        long waveMotionDelay = (mItem.cellX * WAVE_MOTION_DELAY_FACTOR_MILLIS)
+                + (mItem.cellY * WAVE_MOTION_DELAY_FACTOR_MILLIS);
+        long time = SystemClock.uptimeMillis();
+        int newAlpha = (int) Utilities.mapBoundToRange(
+                (float) (time + waveMotionDelay) % ALPHA_DURATION_MILLIS,
+                0,
+                ALPHA_DURATION_MILLIS,
+                0,
+                MAX_PAINT_ALPHA,
+                LINEAR);
+        if (newAlpha > OVERLAY_ALPHA_RANGE) {
+            newAlpha = (int) (OVERLAY_ALPHA_RANGE - (newAlpha % OVERLAY_ALPHA_RANGE));
+        }
+
+        boolean invalidate = false;
+        if (mOverlayAlpha != newAlpha) {
+            mOverlayAlpha = newAlpha;
+            int overlayColor = mIsDarkMode ? 0 : 255;
+            int currArgb = Color.argb(mOverlayAlpha, overlayColor, overlayColor, overlayColor);
+            mPaint.setColorFilter(COLOR_FILTER_MAP.computeIfAbsent(
+                    currArgb,
+                    FILTER_FACTORY));
+            invalidate = true;
+        }
+        return invalidate;
     }
 
     protected static class PreloadIconConstantState extends FastBitmapConstantState {
@@ -335,6 +439,7 @@
         protected final int[] mPreloadColors;
         protected final boolean mIsDarkMode;
         protected final int mLevel;
+        protected final int mRefreshRateMillis;
 
         public PreloadIconConstantState(
                 Bitmap bitmap,
@@ -342,13 +447,15 @@
                 ItemInfoWithIcon info,
                 int indicatorColor,
                 int[] preloadColors,
-                boolean isDarkMode) {
+                boolean isDarkMode,
+                int refreshRateMillis) {
             super(bitmap, iconColor);
             mInfo = info;
             mIndicatorColor = indicatorColor;
             mPreloadColors = preloadColors;
             mIsDarkMode = isDarkMode;
             mLevel = info.getProgressLevel();
+            mRefreshRateMillis = refreshRateMillis;
         }
 
         @Override
@@ -357,7 +464,8 @@
                     mInfo,
                     mIndicatorColor,
                     mPreloadColors,
-                    mIsDarkMode);
+                    mIsDarkMode,
+                    mRefreshRateMillis);
         }
     }
 }
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 159af60..2dd44a4 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -21,7 +21,6 @@
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT_PREDICTION;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_PREDICTION;
-import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SEARCH_RESULTS;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SETTINGS;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_SHORTCUTS;
 import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_TASKSWITCHER;
@@ -54,7 +53,6 @@
 import com.android.launcher3.logger.LauncherAtom.AllAppsContainer;
 import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
 import com.android.launcher3.logger.LauncherAtom.PredictionContainer;
-import com.android.launcher3.logger.LauncherAtom.SearchResultContainer;
 import com.android.launcher3.logger.LauncherAtom.SettingsContainer;
 import com.android.launcher3.logger.LauncherAtom.Shortcut;
 import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer;
@@ -439,10 +437,6 @@
                 return ContainerInfo.newBuilder()
                         .setPredictionContainer(PredictionContainer.getDefaultInstance())
                         .build();
-            case CONTAINER_SEARCH_RESULTS:
-                return ContainerInfo.newBuilder()
-                        .setSearchResultContainer(SearchResultContainer.getDefaultInstance())
-                        .build();
             case CONTAINER_SHORTCUTS:
                 return ContainerInfo.newBuilder()
                         .setShortcutsContainer(ShortcutsContainer.getDefaultInstance())
@@ -459,10 +453,12 @@
                 return ContainerInfo.newBuilder()
                         .setWallpapersContainer(WallpapersContainer.getDefaultInstance())
                         .build();
-            case EXTENDED_CONTAINERS:
-                return ContainerInfo.newBuilder()
-                        .setExtendedContainers(getExtendedContainer())
-                        .build();
+            default:
+                if (container <= EXTENDED_CONTAINERS) {
+                    return ContainerInfo.newBuilder()
+                            .setExtendedContainers(getExtendedContainer())
+                            .build();
+                }
         }
         return ContainerInfo.getDefaultInstance();
     }
diff --git a/src/com/android/launcher3/util/DisplayController.java b/src/com/android/launcher3/util/DisplayController.java
index 8e3daf3..c52890f 100644
--- a/src/com/android/launcher3/util/DisplayController.java
+++ b/src/com/android/launcher3/util/DisplayController.java
@@ -131,13 +131,20 @@
      * Returns whether taskbar is transient.
      */
     public static boolean isTransientTaskbar(Context context) {
+        return INSTANCE.get(context).isTransientTaskbar();
+    }
+
+    /**
+     * Returns whether taskbar is transient.
+     */
+    public boolean isTransientTaskbar() {
         // TODO(b/258604917): When running in test harness, use !sTransientTaskbarStatusForTests
         //  once tests are updated to expect new persistent behavior such as not allowing long press
         //  to stash.
         if (!Utilities.IS_RUNNING_IN_TEST_HARNESS && FORCE_PERSISTENT_TASKBAR.get()) {
             return false;
         }
-        return getNavigationMode(context) == NavigationMode.NO_BUTTON
+        return getInfo().navigationMode == NavigationMode.NO_BUTTON
                 && (Utilities.IS_RUNNING_IN_TEST_HARNESS
                     ? sTransientTaskbarStatusForTests
                     : ENABLE_TRANSIENT_TASKBAR.get());
diff --git a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
index 98eb32e..10afe13 100644
--- a/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
+++ b/tests/tapl/com/android/launcher3/tapl/AddToHomeScreenPrompt.java
@@ -45,7 +45,8 @@
             mLauncher.clickObject(
                     mLauncher.waitForObjectInContainer(
                             mWidgetCell.getParent().getParent().getParent().getParent(),
-                            By.text(ADD_AUTOMATICALLY)));
+                            By.text(ADD_AUTOMATICALLY)),
+                    LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER);
             mLauncher.waitUntilLauncherObjectGone(getSelector());
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index 302fabd..ae9ba67 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -1466,19 +1466,22 @@
         return getRealDisplaySize().x - getWindowInsets().right - 1;
     }
 
-    void clickObject(UiObject2 object) {
-        waitForObjectEnabled(object, "clickObject");
-        if (!isLauncher3() && getNavigationModel() != NavigationModel.THREE_BUTTON) {
-            expectEvent(TestProtocol.SEQUENCE_TIS, LauncherInstrumentation.EVENT_TOUCH_DOWN_TIS);
-            expectEvent(TestProtocol.SEQUENCE_TIS, LauncherInstrumentation.EVENT_TOUCH_UP_TIS);
-        }
-        object.click();
+    /**
+     * Click on the ui object right away without waiting for animation.
+     *
+     * [UiObject2.click] would wait for all animations finished before clicking. Not waiting for
+     * animations because in some scenarios there is a playing animations when the click is
+     * attempted.
+     */
+    void clickObject(UiObject2 uiObject, GestureScope gestureScope) {
+        final long clickTime = SystemClock.uptimeMillis();
+        final Point center = uiObject.getVisibleCenter();
+        sendPointer(clickTime, clickTime, MotionEvent.ACTION_DOWN, center, gestureScope);
+        sendPointer(clickTime, clickTime, MotionEvent.ACTION_UP, center, gestureScope);
     }
 
     void clickLauncherObject(UiObject2 object) {
-        expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_TOUCH_DOWN);
-        expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_TOUCH_UP);
-        clickObject(object);
+        clickObject(object, GestureScope.INSIDE);
     }
 
     void scrollToLastVisibleRow(
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index b2a2937..2c82c50 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -385,7 +385,7 @@
                     Until.hasObject(installerAlert), LauncherInstrumentation.WAIT_TIME_MS));
             final UiObject2 ok = device.findObject(By.text("OK"));
             assertNotNull("OK button is not shown", ok);
-            launcher.clickObject(ok);
+            launcher.clickObject(ok, LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER);
             assertTrue("Uninstall alert is not dismissed after clicking OK", device.wait(
                     Until.gone(installerAlert), LauncherInstrumentation.WAIT_TIME_MS));