Merge "Fix restore not migrating to new grid"
diff --git a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
index 49b2cc5..3eb1935e 100644
--- a/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
+++ b/quickstep/src/com/android/launcher3/QuickstepTransitionManager.java
@@ -16,6 +16,7 @@
 
 package com.android.launcher3;
 
+import static android.provider.Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_NONE;
 import static android.window.StartingWindowInfo.STARTING_WINDOW_TYPE_SPLASH_SCREEN;
 
@@ -75,6 +76,7 @@
 import android.os.Looper;
 import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.provider.Settings;
 import android.util.Pair;
 import android.util.Size;
 import android.view.SurfaceControl;
@@ -683,6 +685,18 @@
         appAnimator.addListener(floatingView);
         appAnimator.addListener(new AnimatorListenerAdapter() {
             @Override
+            public void onAnimationStart(Animator animation) {
+                LauncherTaskbarUIController taskbarController = mLauncher.getTaskbarUIController();
+                if (taskbarController != null && taskbarController.shouldShowEdu()) {
+                    // LAUNCHER_TASKBAR_EDUCATION_SHOWING is set to true here, when the education
+                    // flow is about to start, to avoid a race condition with other components
+                    // that would show something else to the user as soon as the app is opened.
+                    Settings.Secure.putInt(mLauncher.getContentResolver(),
+                            LAUNCHER_TASKBAR_EDUCATION_SHOWING, 1);
+                }
+            }
+
+            @Override
             public void onAnimationEnd(Animator animation) {
                 if (v instanceof BubbleTextView) {
                     ((BubbleTextView) v).setStayPressed(false);
diff --git a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
index 4132c68..0f91aa2 100644
--- a/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/LauncherTaskbarUIController.java
@@ -216,9 +216,7 @@
      * Starts the taskbar education flow, if the user hasn't seen it yet.
      */
     public void showEdu() {
-        if (!FeatureFlags.ENABLE_TASKBAR_EDU.get()
-                || Utilities.IS_RUNNING_IN_TEST_HARNESS
-                || mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN)) {
+        if (!shouldShowEdu()) {
             return;
         }
         mLauncher.getOnboardingPrefs().markChecked(OnboardingPrefs.TASKBAR_EDU_SEEN);
@@ -227,6 +225,15 @@
     }
 
     /**
+     * Whether the taskbar education should be shown.
+     */
+    public boolean shouldShowEdu() {
+        return FeatureFlags.ENABLE_TASKBAR_EDU.get()
+                && !Utilities.IS_RUNNING_IN_TEST_HARNESS
+                && !mLauncher.getOnboardingPrefs().getBoolean(OnboardingPrefs.TASKBAR_EDU_SEEN);
+    }
+
+    /**
      * Manually ends the taskbar education flow.
      */
     public void hideEdu() {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
index 8525427..89d67be 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarEduView.java
@@ -20,6 +20,7 @@
 import android.animation.PropertyValuesHolder;
 import android.content.Context;
 import android.graphics.Rect;
+import android.provider.Settings;
 import android.util.AttributeSet;
 import android.util.Pair;
 import android.view.View;
@@ -92,6 +93,14 @@
         getPopupContainer().addView(this, 1);
     }
 
+    @Override
+    protected void onDetachedFromWindow() {
+        super.onDetachedFromWindow();
+
+        Settings.Secure.putInt(mContext.getContentResolver(),
+                Settings.Secure.LAUNCHER_TASKBAR_EDUCATION_SHOWING, 0);
+    }
+
     /** Show the Education flow. */
     public void show() {
         attachToContainer();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
index 20762b9..335b637 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashController.java
@@ -275,6 +275,9 @@
             // taskbar, we use an OnLongClickListener on TaskbarView instead.
             return false;
         }
+        if (!canCurrentlyManuallyUnstash()) {
+            return false;
+        }
         if (updateAndAnimateIsManuallyStashedInApp(false)) {
             mControllers.taskbarActivityContext.getDragLayer().performHapticFeedback(LONG_PRESS);
             return true;
@@ -283,6 +286,16 @@
     }
 
     /**
+     * Returns whether taskbar will unstash when long pressing it based on the current state. The
+     * only time this is true is if the user is in an app and the taskbar is only stashed because
+     * the user previously long pressed to manually stash (not due to other reasons like IME).
+     */
+    private boolean canCurrentlyManuallyUnstash() {
+        return (mState & (FLAG_IN_APP | FLAGS_STASHED_IN_APP))
+                == (FLAG_IN_APP | FLAG_STASHED_IN_APP_MANUAL);
+    }
+
+    /**
      * Updates whether we should stash the taskbar when in apps, and animates to the changed state.
      * @return Whether we started an animation to either be newly stashed or unstashed.
      */
@@ -423,6 +436,11 @@
             // Already unstashed, no need to hint in that direction.
             return;
         }
+        if (!canCurrentlyManuallyUnstash()) {
+            // If any other flags are causing us to be stashed, long press won't cause us to
+            // unstash, so don't hint that it will.
+            return;
+        }
         mTaskbarStashedHandleHintScale.animateToValue(
                 animateForward ? UNSTASHED_TASKBAR_HANDLE_HINT_SCALE : 1)
                 .setDuration(TASKBAR_HINT_STASH_DURATION).start();
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 62f1fa5..8b6831b 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -215,7 +215,7 @@
         PendingAnimation setter = new PendingAnimation(100);
         Rect hotseatPadding = launcherDp.getHotseatLayoutPadding(mActivity);
         float scaleUp = ((float) launcherDp.iconSizePx) / mActivity.getDeviceProfile().iconSizePx;
-        int borderSpacing = launcherDp.cellLayoutBorderSpacePx.x;
+        int borderSpacing = launcherDp.hotseatBorderSpace;
         int hotseatCellSize = DeviceProfile.calculateCellWidth(
                 launcherDp.availableWidthPx - hotseatPadding.left - hotseatPadding.right,
                 borderSpacing,
@@ -253,9 +253,9 @@
 
             float hotseatIconCenter = hotseatPadding.left
                     + (hotseatCellSize + borderSpacing) * positionInHotseat
-                    + hotseatCellSize / 2;
+                    + hotseatCellSize / 2f;
 
-            float childCenter = (child.getLeft() + child.getRight()) / 2;
+            float childCenter = (child.getLeft() + child.getRight()) / 2f;
             setter.setFloat(child, ICON_TRANSLATE_X, hotseatIconCenter - childCenter, LINEAR);
 
             setter.setFloat(child, SCALE_PROPERTY, scaleUp, LINEAR);
diff --git a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
index 0046bbe..12a638a 100644
--- a/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
+++ b/quickstep/src/com/android/quickstep/logging/StatsLogCompatManager.java
@@ -571,9 +571,14 @@
     }
 
     private static int getSearchAttributes(LauncherAtom.ItemInfo info) {
-        if (info.getContainerInfo().getExtendedContainers().getDeviceSearchResultContainer()
-                .hasSearchAttributes()) {
-            return searchAttributesToInt(info.getContainerInfo().getExtendedContainers()
+        ContainerInfo containerInfo = info.getContainerInfo();
+        if (containerInfo.getContainerCase() == EXTENDED_CONTAINERS
+                && containerInfo.getExtendedContainers().getContainerCase()
+                == DEVICE_SEARCH_RESULT_CONTAINER
+                && containerInfo.getExtendedContainers()
+                .getDeviceSearchResultContainer().hasSearchAttributes()
+        ) {
+            return searchAttributesToInt(containerInfo.getExtendedContainers()
                     .getDeviceSearchResultContainer().getSearchAttributes());
         }
         return 0;
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index 661aa00..ebc0c75 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -2401,6 +2401,10 @@
                     } else {
                         Log.d(TAG, desc);
                         getModelWriter().deleteItemFromDatabase(item);
+                        if (TestProtocol.sDebugTracing) {
+                            Log.d(TestProtocol.MISSING_PROMISE_ICON,
+                                    TAG + "bindItems failed for item=" + item);
+                        }
                         continue;
                     }
                 }
diff --git a/src/com/android/launcher3/SessionCommitReceiver.java b/src/com/android/launcher3/SessionCommitReceiver.java
index 558538c..b81637f 100644
--- a/src/com/android/launcher3/SessionCommitReceiver.java
+++ b/src/com/android/launcher3/SessionCommitReceiver.java
@@ -24,12 +24,14 @@
 import android.content.pm.PackageManager;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.WorkerThread;
 
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.model.ItemInstallQueue;
 import com.android.launcher3.pm.InstallSessionHelper;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.Executors;
 
 /**
@@ -51,6 +53,9 @@
     private static void processIntent(Context context, Intent intent) {
         if (!isEnabled(context)) {
             // User has decided to not add icons on homescreen.
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " not enabled");
+            }
             return;
         }
 
@@ -59,6 +64,9 @@
         if (!PackageInstaller.ACTION_SESSION_COMMITTED.equals(intent.getAction())
                 || info == null || user == null) {
             // Invalid intent.
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " invalid intent");
+            }
             return;
         }
 
@@ -68,6 +76,15 @@
                 || info.getInstallReason() != PackageManager.INSTALL_REASON_USER
                 || packageInstallerCompat.promiseIconAddedForId(info.getSessionId())) {
             packageInstallerCompat.removePromiseIconId(info.getSessionId());
+            if (TestProtocol.sDebugTracing) {
+                int id = info.getSessionId();
+                Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG
+                        + ", TextUtils.isEmpty=" + TextUtils.isEmpty(info.getAppPackageName())
+                        + ", info.getInstallReason()=" + info.getInstallReason()
+                        + ", INSTALL_REASON_USER=" + PackageManager.INSTALL_REASON_USER
+                        + ", icon added=" + packageInstallerCompat.promiseIconAddedForId(id)
+                );
+            }
             return;
         }
 
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index a13fa55..91fb44e 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -22,6 +22,7 @@
 import android.content.pm.LauncherApps;
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.os.UserHandle;
+import android.util.Log;
 import android.util.LongSparseArray;
 import android.util.Pair;
 
@@ -39,6 +40,7 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.InstallSessionHelper;
 import com.android.launcher3.pm.PackageInstallInfo;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.GridOccupancy;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.IntSet;
@@ -82,11 +84,19 @@
                         item.itemType == LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT) {
                     // Short-circuit this logic if the icon exists somewhere on the workspace
                     if (shortcutExists(dataModel, item.getIntent(), item.user)) {
+                        if (TestProtocol.sDebugTracing) {
+                            Log.d(TestProtocol.MISSING_PROMISE_ICON,
+                                    LOG + " Item already on workspace.");
+                        }
                         continue;
                     }
 
                     // b/139663018 Short-circuit this logic if the icon is a system app
                     if (PackageManagerHelper.isSystemApp(app.getContext(), item.getIntent())) {
+                        if (TestProtocol.sDebugTracing) {
+                            Log.d(TestProtocol.MISSING_PROMISE_ICON,
+                                    LOG + " Item is a system app.");
+                        }
                         continue;
                     }
                 }
@@ -126,6 +136,9 @@
                     String packageName = item.getTargetComponent() != null
                             ? item.getTargetComponent().getPackageName() : null;
                     if (packageName == null) {
+                        if (TestProtocol.sDebugTracing) {
+                            Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " Null packageName.");
+                        }
                         continue;
                     }
                     SessionInfo sessionInfo = packageInstaller.getActiveSessionInfo(item.user,
@@ -134,6 +147,9 @@
                     if (!packageInstaller.verifySessionInfo(sessionInfo)) {
                         FileLog.d(LOG, "Item info failed session info verification. "
                                 + "Skipping : " + workspaceInfo);
+                        if (TestProtocol.sDebugTracing) {
+                            Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + "Failed verification.");
+                        }
                         continue;
                     }
 
@@ -144,6 +160,9 @@
                     if (sessionInfo == null) {
                         if (!hasActivity) {
                             // Session was cancelled, do not add.
+                            if (TestProtocol.sDebugTracing) {
+                                Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + "Session cancelled");
+                            }
                             continue;
                         }
                     } else {
@@ -163,6 +182,9 @@
                             // workspace items as promise icons. At this point we now have the
                             // correct intent to compare against existing workspace icons.
                             // Icon already exists on the workspace and should not be auto-added.
+                            if (TestProtocol.sDebugTracing) {
+                                Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + "shortcutExists");
+                            }
                             continue;
                         }
 
diff --git a/src/com/android/launcher3/model/ItemInstallQueue.java b/src/com/android/launcher3/model/ItemInstallQueue.java
index 217f523..5a220f7 100644
--- a/src/com/android/launcher3/model/ItemInstallQueue.java
+++ b/src/com/android/launcher3/model/ItemInstallQueue.java
@@ -49,6 +49,7 @@
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.shortcuts.ShortcutKey;
 import com.android.launcher3.shortcuts.ShortcutRequest;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.MainThreadInitializedObject;
 import com.android.launcher3.util.PersistedItemArray;
 import com.android.launcher3.util.Preconditions;
@@ -118,10 +119,18 @@
         Launcher launcher = Launcher.ACTIVITY_TRACKER.getCreatedActivity();
         if (launcher == null) {
             // Launcher not loaded
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.MISSING_PROMISE_ICON,
+                        LOG + " flushQueueInBackground launcher not loaded");
+            }
             return;
         }
         ensureQueueLoaded();
         if (mItems.isEmpty()) {
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.MISSING_PROMISE_ICON,
+                        LOG + " flushQueueInBackground no items to load");
+            }
             return;
         }
 
@@ -131,6 +140,10 @@
 
         // Add the items and clear queue
         if (!installQueue.isEmpty()) {
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.MISSING_PROMISE_ICON,
+                        LOG + " flushQueueInBackground launcher addAndBindAddedWorkspaceItems");
+            }
             // add log
             launcher.getModel().addAndBindAddedWorkspaceItems(installQueue);
         }
@@ -191,6 +204,10 @@
         // Queue the item up for adding if launcher has not loaded properly yet
         MODEL_EXECUTOR.post(() -> {
             Pair<ItemInfo, Object> itemInfo = info.getItemInfo(mContext);
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " queuePendingShortcutInfo"
+                        + ", itemInfo=" + itemInfo);
+            }
             if (itemInfo == null) {
                 FileLog.d(LOG,
                         "Adding PendingInstallShortcutInfo with no attached info to queue.",
diff --git a/src/com/android/launcher3/pm/InstallSessionHelper.java b/src/com/android/launcher3/pm/InstallSessionHelper.java
index 4b86f65..618f926 100644
--- a/src/com/android/launcher3/pm/InstallSessionHelper.java
+++ b/src/com/android/launcher3/pm/InstallSessionHelper.java
@@ -27,6 +27,7 @@
 import android.os.Process;
 import android.os.UserHandle;
 import android.text.TextUtils;
+import android.util.Log;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.RequiresApi;
@@ -38,6 +39,7 @@
 import com.android.launcher3.config.FeatureFlags;
 import com.android.launcher3.logging.FileLog;
 import com.android.launcher3.model.ItemInstallQueue;
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.IntArray;
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.MainThreadInitializedObject;
@@ -142,6 +144,16 @@
         if (sessionInfo == null
                 || sessionInfo.getInstallerPackageName() == null
                 || TextUtils.isEmpty(sessionInfo.getAppPackageName())) {
+            if (TestProtocol.sDebugTracing) {
+                Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " verify"
+                        + ", info=" + (sessionInfo == null)
+                        + ", info install name" + (sessionInfo == null
+                                ? null
+                                : sessionInfo.getInstallerPackageName())
+                        + ", empty pkg name" + TextUtils.isEmpty((sessionInfo == null
+                                ? null
+                                : sessionInfo.getAppPackageName())));
+            }
             return null;
         }
         String pkg = sessionInfo.getInstallerPackageName();
@@ -211,6 +223,14 @@
      */
     @WorkerThread
     void tryQueuePromiseAppIcon(PackageInstaller.SessionInfo sessionInfo) {
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " tryQueuePromiseAppIcon"
+                    + ", FeatureFlags=" + FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
+                    + ", SessionCommitReceiveEnabled" + SessionCommitReceiver.isEnabled(mAppContext)
+                    + ", verifySessionInfo(sessionInfo)=" + verifySessionInfo(sessionInfo)
+                    + ", !promiseIconAdded=" + (sessionInfo != null
+                    && !promiseIconAddedForId(sessionInfo.getSessionId())));
+        }
         if (FeatureFlags.PROMISE_APPS_NEW_INSTALLS.get()
                 && SessionCommitReceiver.isEnabled(mAppContext)
                 && verifySessionInfo(sessionInfo)
@@ -227,6 +247,20 @@
     }
 
     public boolean verifySessionInfo(PackageInstaller.SessionInfo sessionInfo) {
+        if (TestProtocol.sDebugTracing) {
+            boolean appNotInstalled = sessionInfo == null
+                    || !new PackageManagerHelper(mAppContext)
+                    .isAppInstalled(sessionInfo.getAppPackageName(), getUserHandle(sessionInfo));
+            boolean labelNotEmpty = sessionInfo != null
+                    && !TextUtils.isEmpty(sessionInfo.getAppLabel());
+            Log.d(TestProtocol.MISSING_PROMISE_ICON, LOG + " verifySessionInfo"
+                    + ", verify(sessionInfo)=" + verify(sessionInfo)
+                    + ", reason=" + (sessionInfo == null ? null : sessionInfo.getInstallReason())
+                    + ", PackageManager.INSTALL_REASON_USER=" + PackageManager.INSTALL_REASON_USER
+                    + ", hasIcon=" + (sessionInfo != null && sessionInfo.getAppIcon() != null)
+                    + ", label is ! empty=" + labelNotEmpty
+                    + " +, app not installed="  + appNotInstalled);
+        }
         return verify(sessionInfo) != null
                 && sessionInfo.getInstallReason() == PackageManager.INSTALL_REASON_USER
                 && sessionInfo.getAppIcon() != null
diff --git a/src/com/android/launcher3/pm/InstallSessionTracker.java b/src/com/android/launcher3/pm/InstallSessionTracker.java
index e1b3c1a..75cf7a8 100644
--- a/src/com/android/launcher3/pm/InstallSessionTracker.java
+++ b/src/com/android/launcher3/pm/InstallSessionTracker.java
@@ -25,10 +25,12 @@
 import android.content.pm.PackageInstaller.SessionInfo;
 import android.os.Build;
 import android.os.UserHandle;
+import android.util.Log;
 import android.util.SparseArray;
 
 import androidx.annotation.WorkerThread;
 
+import com.android.launcher3.testing.TestProtocol;
 import com.android.launcher3.util.PackageUserKey;
 
 import java.lang.ref.WeakReference;
@@ -57,10 +59,19 @@
     public void onCreated(int sessionId) {
         InstallSessionHelper helper = mWeakHelper.get();
         Callback callback = mWeakCallback.get();
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.MISSING_PROMISE_ICON, "Session created sessionId=" + sessionId
+                    + ", callback=" + callback
+                    + ", helper=" + helper);
+        }
         if (callback == null || helper == null) {
             return;
         }
         SessionInfo sessionInfo = pushSessionDisplayToLauncher(sessionId, helper, callback);
+        if (TestProtocol.sDebugTracing) {
+            Log.d(TestProtocol.MISSING_PROMISE_ICON, "Session created sessionId=" + sessionId
+                    + ", sessionInfo=" + sessionInfo);
+        }
         if (sessionInfo != null) {
             callback.onInstallSessionCreated(PackageInstallInfo.fromInstallingState(sessionInfo));
         }
diff --git a/src/com/android/launcher3/testing/TestProtocol.java b/src/com/android/launcher3/testing/TestProtocol.java
index 7c6ad9f..78e9fe8 100644
--- a/src/com/android/launcher3/testing/TestProtocol.java
+++ b/src/com/android/launcher3/testing/TestProtocol.java
@@ -126,4 +126,5 @@
     public static final String TASK_VIEW_ID_CRASH = "b/195430732";
     public static final String NO_DROP_TARGET = "b/195031154";
     public static final String NULL_INT_SET = "b/200572078";
+    public static final String MISSING_PROMISE_ICON = "b/202985412";
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/Background.java b/tests/tapl/com/android/launcher3/tapl/Background.java
index d84d723..4333b27 100644
--- a/tests/tapl/com/android/launcher3/tapl/Background.java
+++ b/tests/tapl/com/android/launcher3/tapl/Background.java
@@ -80,7 +80,8 @@
     protected void goToOverviewUnchecked() {
         switch (mLauncher.getNavigationModel()) {
             case ZERO_BUTTON: {
-                sendDownPointerToEnterOverviewToLauncher();
+                final long downTime = SystemClock.uptimeMillis();
+                sendDownPointerToEnterOverviewToLauncher(downTime);
                 String swipeAndHoldToEnterOverviewActionName =
                         "swiping and holding to enter overview";
                 // If swiping from an app (e.g. Overview is in Background), we pause and hold on
@@ -89,16 +90,17 @@
                 // Workspace state where the below condition is true), there is no need to pause,
                 // and we will not test for an intermediate carousel as one will not exist.
                 if (zeroButtonToOverviewGestureStateTransitionWhileHolding()) {
-                    mLauncher.runToState(this::sendSwipeUpAndHoldToEnterOverviewGestureToLauncher,
+                    mLauncher.runToState(
+                            () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
                             OVERVIEW_STATE_ORDINAL, swipeAndHoldToEnterOverviewActionName);
-                    sendUpPointerToEnterOverviewToLauncher();
+                    sendUpPointerToEnterOverviewToLauncher(downTime);
                 } else {
                     // If swiping up from an app to overview, pause on intermediate carousel
                     // until snapshots are visible. No intermediate carousel when swiping from
                     // Home. The task swiped up is not a snapshot but the TaskViewSimulator. If
                     // only a single task exists, no snapshots will be available during swipe up.
                     mLauncher.executeAndWaitForLauncherEvent(
-                            this::sendSwipeUpAndHoldToEnterOverviewGestureToLauncher,
+                            () -> sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(downTime),
                             event -> TestProtocol.PAUSE_DETECTED_MESSAGE.equals(
                                     event.getClassName().toString()),
                             () -> "Pause wasn't detected",
@@ -127,7 +129,7 @@
                         }
                         String upPointerToEnterOverviewActionName =
                                 "sending UP pointer to enter overview";
-                        mLauncher.runToState(this::sendUpPointerToEnterOverviewToLauncher,
+                        mLauncher.runToState(() -> sendUpPointerToEnterOverviewToLauncher(downTime),
                                 OVERVIEW_STATE_ORDINAL, upPointerToEnterOverviewActionName);
                     }
                 }
@@ -153,21 +155,24 @@
     private void expectSwitchToOverviewEvents() {
     }
 
-    private void sendDownPointerToEnterOverviewToLauncher() {
+    private void sendDownPointerToEnterOverviewToLauncher(long downTime) {
         final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
         final int startY = getSwipeStartY();
         final Point start = new Point(centerX, startY);
-        final long downTime = SystemClock.uptimeMillis();
         final LauncherInstrumentation.GestureScope gestureScope =
                 zeroButtonToOverviewGestureStartsInLauncher()
                         ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
                         : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
 
-        mLauncher.sendPointer(
-                downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
+        mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, start, gestureScope);
+
+        if (!mLauncher.isLauncher3()) {
+            mLauncher.expectEvent(TestProtocol.SEQUENCE_PILFER,
+                    LauncherInstrumentation.EVENT_PILFER_POINTERS);
+        }
     }
 
-    private void sendSwipeUpAndHoldToEnterOverviewGestureToLauncher() {
+    private void sendSwipeUpAndHoldToEnterOverviewGestureToLauncher(long downTime) {
         final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
         final int startY = getSwipeStartY();
         final int swipeHeight = mLauncher.getTestInfo(getSwipeHeightRequestName()).getInt(
@@ -175,7 +180,6 @@
         final Point start = new Point(centerX, startY);
         final Point end =
                 new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
-        final long downTime = SystemClock.uptimeMillis();
         final LauncherInstrumentation.GestureScope gestureScope =
                 zeroButtonToOverviewGestureStartsInLauncher()
                         ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
@@ -190,18 +194,18 @@
                 gestureScope);
     }
 
-    private void sendUpPointerToEnterOverviewToLauncher() {
+    private void sendUpPointerToEnterOverviewToLauncher(long downTime) {
         final int centerX = mLauncher.getDevice().getDisplayWidth() / 2;
         final int startY = getSwipeStartY();
         final int swipeHeight = mLauncher.getTestInfo(getSwipeHeightRequestName()).getInt(
                 TestProtocol.TEST_INFO_RESPONSE_FIELD);
         final Point end =
                 new Point(centerX, startY - swipeHeight - mLauncher.getTouchSlop());
-        final long downTime = SystemClock.uptimeMillis();
+
         final LauncherInstrumentation.GestureScope gestureScope =
                 zeroButtonToOverviewGestureStartsInLauncher()
-                        ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE
-                        : LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER;
+                        ? LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER
+                        : LauncherInstrumentation.GestureScope.OUTSIDE_WITHOUT_PILFER;
 
         mLauncher.sendPointer(downTime, SystemClock.uptimeMillis(),
                 MotionEvent.ACTION_UP, end, gestureScope);
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index c22b4da..12be54e 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -105,7 +105,7 @@
     static final Pattern EVENT_TOUCH_DOWN = getTouchEventPattern("ACTION_DOWN");
     static final Pattern EVENT_TOUCH_UP = getTouchEventPattern("ACTION_UP");
     private static final Pattern EVENT_TOUCH_CANCEL = getTouchEventPattern("ACTION_CANCEL");
-    private static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
+    static final Pattern EVENT_PILFER_POINTERS = Pattern.compile("pilferPointers");
     static final Pattern EVENT_START = Pattern.compile("start:");
 
     static final Pattern EVENT_TOUCH_DOWN_TIS = getTouchEventPatternTIS("ACTION_DOWN");