Add taskbar TAPL tests

- Added TAPL objects to support TAPL tests for taskbar features
- Added tests for major taskbar features: hiding/showing the taskbar, opening all apps, lauching apps and app deep shortcuts from the taskbar/all apps page, launching apps and app deep shortcuts in splitscreen
- These tests should only run for large devices

Design: go/taskbar-tapl-tests
Test: ran tests locally with invalid configurations and remotely
Bug: 215218813
Change-Id: I3c28c339707467414aa47fa633f87fa0c1fdee57
diff --git a/tests/AndroidManifest-common.xml b/tests/AndroidManifest-common.xml
index b4cd773..9cc3aed 100644
--- a/tests/AndroidManifest-common.xml
+++ b/tests/AndroidManifest-common.xml
@@ -94,7 +94,6 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
-                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
         </activity>
 
@@ -138,6 +137,7 @@
             <intent-filter>
                 <action android:name="android.intent.action.MAIN"/>
                 <category android:name="android.intent.category.LAUNCHER"/>
+                <category android:name="android.intent.category.DEFAULT"/>
             </intent-filter>
             <intent-filter>
                 <action android:name="com.android.launcher3.intent.action.test_shortcut"/>
diff --git a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
index c99c4f1..136f115 100644
--- a/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
+++ b/tests/src/com/android/launcher3/ui/AbstractLauncherUiTest.java
@@ -567,6 +567,7 @@
                             ordinal == TestProtocol.OVERVIEW_STATE_ORDINAL);
                     break;
                 }
+                case TASKBAR_ALL_APPS:
                 case LAUNCHED_APP: {
                     assertTrue("Launcher is resumed in state: " + expectedContainerType,
                             !isResumed);
@@ -580,9 +581,10 @@
             }
         } else {
             assertTrue(
-                    "Container type is not LAUNCHED_APP or FALLBACK_OVERVIEW: "
-                            + expectedContainerType,
+                    "Container type is not LAUNCHED_APP, TASKBAR_ALL_APPS "
+                            + "or FALLBACK_OVERVIEW: " + expectedContainerType,
                     expectedContainerType == ContainerType.LAUNCHED_APP
+                            || expectedContainerType == ContainerType.TASKBAR_ALL_APPS
                             || expectedContainerType == ContainerType.FALLBACK_OVERVIEW);
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/AllApps.java b/tests/tapl/com/android/launcher3/tapl/AllApps.java
index 3658f41..bfb115d 100644
--- a/tests/tapl/com/android/launcher3/tapl/AllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/AllApps.java
@@ -74,7 +74,7 @@
             LauncherInstrumentation.log("hasClickableIcon: icon has insufficient height");
             return false;
         }
-        if (iconCenterInSearchBox(allAppsContainer, icon)) {
+        if (hasSearchBox() && iconCenterInSearchBox(allAppsContainer, icon)) {
             LauncherInstrumentation.log("hasClickableIcon: icon center is under search box");
             return false;
         }
@@ -107,7 +107,7 @@
             final UiObject2 allAppsContainer = verifyActiveContainer();
             final UiObject2 appListRecycler = mLauncher.waitForObjectInContainer(allAppsContainer,
                     "apps_list_view");
-            final UiObject2 searchBox = getSearchBox(allAppsContainer);
+            final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null;
 
             int deviceHeight = mLauncher.getRealDisplaySize().y;
             int bottomGestureStartOnScreen = mLauncher.getBottomGestureStartOnScreen();
@@ -128,8 +128,10 @@
                                                 mLauncher.getVisibleBounds(icon).top
                                                         < bottomGestureStartOnScreen)
                                         .collect(Collectors.toList()),
-                                mLauncher.getVisibleBounds(searchBox).bottom
-                                        - mLauncher.getVisibleBounds(allAppsContainer).top);
+                                hasSearchBox()
+                                        ? mLauncher.getVisibleBounds(searchBox).bottom
+                                        - mLauncher.getVisibleBounds(allAppsContainer).top
+                                        : 0);
                         verifyActiveContainer();
                         final int newScroll = getAllAppsScroll();
                         mLauncher.assertTrue(
@@ -173,18 +175,21 @@
         return appIcon;
     }
 
+    @NonNull
     protected abstract AppIcon createAppIcon(UiObject2 icon);
 
+    protected abstract boolean hasSearchBox();
+
     private void scrollBackToBeginning() {
         try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                 "want to scroll back in all apps")) {
             LauncherInstrumentation.log("Scrolling to the beginning");
             final UiObject2 allAppsContainer = verifyActiveContainer();
-            final UiObject2 searchBox = getSearchBox(allAppsContainer);
+            final UiObject2 searchBox = hasSearchBox() ? getSearchBox(allAppsContainer) : null;
 
             int attempts = 0;
-            final Rect margins =
-                    new Rect(0, mLauncher.getVisibleBounds(searchBox).bottom + 1, 0, 5);
+            final Rect margins = new Rect(
+                    0, hasSearchBox() ? mLauncher.getVisibleBounds(searchBox).bottom + 1 : 0, 0, 5);
 
             for (int scroll = getAllAppsScroll();
                     scroll != 0;
@@ -196,7 +201,11 @@
                         ++attempts <= MAX_SCROLL_ATTEMPTS);
 
                 mLauncher.scroll(
-                        allAppsContainer, Direction.UP, margins, 12, false);
+                        allAppsContainer,
+                        Direction.UP,
+                        margins,
+                        /* steps= */ 12,
+                        /* slowDown= */ false);
             }
 
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("scrolled up")) {
@@ -225,7 +234,11 @@
             final UiObject2 allAppsContainer = verifyActiveContainer();
             // Start the gesture in the center to avoid starting at elements near the top.
             mLauncher.scroll(
-                    allAppsContainer, Direction.DOWN, new Rect(0, 0, 0, mHeight / 2), 10, false);
+                    allAppsContainer,
+                    Direction.DOWN,
+                    new Rect(0, 0, 0, mHeight / 2),
+                    /* steps= */ 10,
+                    /* slowDown= */ false);
             verifyActiveContainer();
         }
     }
@@ -240,7 +253,11 @@
             final UiObject2 allAppsContainer = verifyActiveContainer();
             // Start the gesture in the center, for symmetry with forward.
             mLauncher.scroll(
-                    allAppsContainer, Direction.UP, new Rect(0, mHeight / 2, 0, 0), 10, false);
+                    allAppsContainer,
+                    Direction.UP,
+                    new Rect(0, mHeight / 2, 0, 0),
+                    /* steps= */ 10,
+                    /*slowDown= */ false);
             verifyActiveContainer();
         }
     }
diff --git a/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
new file mode 100644
index 0000000..5164025
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/AllAppsFromTaskbar.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Operations on AllApps opened from the Taskbar.
+ */
+public class AllAppsFromTaskbar extends AllApps {
+
+    AllAppsFromTaskbar(LauncherInstrumentation launcher) {
+        super(launcher);
+    }
+
+    @Override
+    protected LauncherInstrumentation.ContainerType getContainerType() {
+        return LauncherInstrumentation.ContainerType.TASKBAR_ALL_APPS;
+    }
+
+    @NonNull
+    @Override
+    public TaskbarAppIcon getAppIcon(String appName) {
+        return (TaskbarAppIcon) super.getAppIcon(appName);
+    }
+
+    @NonNull
+    @Override
+    protected TaskbarAppIcon createAppIcon(UiObject2 icon) {
+        return new TaskbarAppIcon(mLauncher, icon);
+    }
+
+    @Override
+    protected boolean hasSearchBox() {
+        return false;
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIcon.java b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
index bef242c..e28f0af 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIcon.java
@@ -51,7 +51,7 @@
     public AppIconMenu openMenu() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             return createMenu(mLauncher.clickAndGet(
-                    mObject, "popup_container", getLongClickEvent()));
+                    mObject, /* resName= */ "popup_container", getLongClickEvent()));
         }
     }
 
@@ -61,7 +61,7 @@
     public AppIconMenu openDeepShortcutMenu() {
         try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
             return createMenu(mLauncher.clickAndGet(
-                    mObject, "deep_shortcuts_container", getLongClickEvent()));
+                    mObject, /* resName= */ "deep_shortcuts_container", getLongClickEvent()));
         }
     }
 
@@ -73,8 +73,8 @@
     }
 
     @Override
-    protected String getLongPressIndicator() {
-        return "popup_container";
+    protected void waitForLongPressConfirmation() {
+        mLauncher.waitForLauncherObject("popup_container");
     }
 
     @Override
diff --git a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
index a6a1531..5cf5aba 100644
--- a/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
+++ b/tests/tapl/com/android/launcher3/tapl/AppIconMenuItem.java
@@ -41,8 +41,8 @@
     }
 
     @Override
-    protected String getLongPressIndicator() {
-        return "drop_target_bar";
+    protected void waitForLongPressConfirmation() {
+        mLauncher.waitForLauncherObject("drop_target_bar");
     }
 
     @Override
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
index 2e00d59..c275f3b 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAllApps.java
@@ -35,8 +35,14 @@
         return (AllAppsAppIcon) super.getAppIcon(appName);
     }
 
+    @NonNull
     @Override
     protected HomeAppIcon createAppIcon(UiObject2 icon) {
         return new AllAppsAppIcon(mLauncher, icon);
     }
+
+    @Override
+    protected boolean hasSearchBox() {
+        return true;
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
index baabe12..71d8ba9 100644
--- a/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
+++ b/tests/tapl/com/android/launcher3/tapl/HomeAppIcon.java
@@ -51,8 +51,7 @@
                     () -> {
                         final Rect bounds = target.getDropLocationBounds();
                         return new Point(bounds.centerX(), bounds.centerY());
-                    },
-                    getLongPressIndicator());
+                    });
             FolderIcon result = target.getTargetFolder(dropBounds);
             mLauncher.assertTrue("Can't find the target folder.", result != null);
             return result;
@@ -115,8 +114,12 @@
                      String.format("want to drag the icon to cell(%d, %d)", cellX, cellY))
         ) {
             final Supplier<Point> dest = () -> Workspace.getCellCenter(mLauncher, cellX, cellY);
-            Workspace.dragIconToWorkspace(mLauncher, this, dest, getLongPressIndicator(),
-                    () -> addExpectedEventsForLongClick(), null);
+            Workspace.dragIconToWorkspace(
+                    mLauncher,
+                    /* launchable= */ this,
+                    dest,
+                    () -> addExpectedEventsForLongClick(),
+                    /*expectDropEvents= */ null);
             try (LauncherInstrumentation.Closable ignore = mLauncher.addContextLayer("dragged")) {
                 WorkspaceAppIcon appIcon =
                         (WorkspaceAppIcon) mLauncher.getWorkspace().getWorkspaceAppIcon(mAppName);
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index a28eac6..45a0196 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -97,8 +97,7 @@
         return new LaunchedAppState(mLauncher);
     }
 
-    Point startDrag(long downTime, String longPressIndicator,
-            Runnable expectLongClickEvents, boolean runToSpringLoadedState) {
+    Point startDrag(long downTime, Runnable expectLongClickEvents, boolean runToSpringLoadedState) {
         final Point iconCenter = getObject().getVisibleCenter();
         final Point dragStartCenter = new Point(iconCenter.x,
                 iconCenter.y - getStartDragThreshold());
@@ -108,7 +107,6 @@
                     downTime,
                     iconCenter,
                     dragStartCenter,
-                    longPressIndicator,
                     expectLongClickEvents),
                     SPRING_LOADED_STATE_ORDINAL, "long-pressing and triggering drag start");
         } else {
@@ -116,7 +114,6 @@
                     downTime,
                     iconCenter,
                     dragStartCenter,
-                    longPressIndicator,
                     expectLongClickEvents);
         }
 
@@ -125,21 +122,43 @@
     }
 
     /**
+     * Waits for a confirmation that a long press has successfully been triggered.
+     *
+     * This method waits for a view to either appear or disappear to confirm that the long press
+     * has been triggered and fails if no confirmation is received before the default timeout.
+     */
+    protected abstract void waitForLongPressConfirmation();
+
+    /**
      * Drags this Launchable a short distance before starting a full drag.
      *
      * This is necessary for shortcuts, which require being dragged beyond a threshold to close
      * their container and start drag callbacks.
      */
-    private void movePointerForStartDrag(long downTime, Point iconCenter, Point dragStartCenter,
-            String longPressIndicator, Runnable expectLongClickEvents) {
-        mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN,
-                iconCenter, LauncherInstrumentation.GestureScope.INSIDE);
+    private void movePointerForStartDrag(
+            long downTime,
+            Point iconCenter,
+            Point dragStartCenter,
+            Runnable expectLongClickEvents) {
+        mLauncher.sendPointer(
+                downTime,
+                downTime,
+                MotionEvent.ACTION_DOWN,
+                iconCenter,
+                LauncherInstrumentation.GestureScope.INSIDE);
         LauncherInstrumentation.log("movePointerForStartDrag: sent down");
         expectLongClickEvents.run();
-        mLauncher.waitForLauncherObject(longPressIndicator);
+        waitForLongPressConfirmation();
         LauncherInstrumentation.log("movePointerForStartDrag: indicator");
-        mLauncher.movePointer(iconCenter, dragStartCenter, DEFAULT_DRAG_STEPS, false,
-                downTime, downTime, true, LauncherInstrumentation.GestureScope.INSIDE);
+        mLauncher.movePointer(
+                iconCenter,
+                dragStartCenter,
+                DEFAULT_DRAG_STEPS,
+                /* isDecelerating= */ false,
+                downTime,
+                downTime,
+                /* slowDown= */ true,
+                LauncherInstrumentation.GestureScope.INSIDE);
     }
 
     private int getStartDragThreshold() {
@@ -148,6 +167,4 @@
     }
 
     protected abstract void addExpectedEventsForLongClick();
-
-    protected abstract String getLongPressIndicator();
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index 3f1be80..2033a42 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -16,11 +16,27 @@
 
 package com.android.launcher3.tapl;
 
+import static com.android.launcher3.testing.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
+import static com.android.launcher3.testing.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
+import static com.android.launcher3.testing.TestProtocol.REQUEST_STASHED_TASKBAR_HEIGHT;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.SystemClock;
+import android.view.MotionEvent;
+
+import androidx.test.uiautomator.By;
+
+import com.android.launcher3.testing.TestProtocol;
+
 /**
  * Background state operations specific to when an app has been launched.
  */
 public final class LaunchedAppState extends Background {
 
+    // More drag steps than Launchables to give the window manager time to register the drag.
+    private static final int DEFAULT_DRAG_STEPS = 35;
+
     LaunchedAppState(LauncherInstrumentation launcher) {
         super(launcher);
     }
@@ -29,4 +45,126 @@
     protected LauncherInstrumentation.ContainerType getContainerType() {
         return LauncherInstrumentation.ContainerType.LAUNCHED_APP;
     }
+
+    /**
+     * Returns the taskbar.
+     *
+     * The taskbar must already be visible when calling this method.
+     */
+    public Taskbar getTaskbar() {
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "want to get the taskbar")) {
+            mLauncher.waitForLauncherObject("taskbar_view");
+
+            return new Taskbar(mLauncher);
+        }
+    }
+
+    /**
+     * Returns the Taskbar in a visible state.
+     *
+     * The taskbar must already be hidden when calling this method.
+     */
+    public Taskbar showTaskbar() {
+        mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING);
+
+        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck();
+             LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
+                     "want to show the taskbar")) {
+            mLauncher.waitUntilLauncherObjectGone("taskbar_view");
+
+            final long downTime = SystemClock.uptimeMillis();
+            final int unstashTargetY = mLauncher.getRealDisplaySize().y
+                    - (mLauncher.getTestInfo(REQUEST_STASHED_TASKBAR_HEIGHT)
+                            .getInt(TestProtocol.TEST_INFO_RESPONSE_FIELD) / 2);
+            final Point unstashTarget = new Point(
+                    mLauncher.getRealDisplaySize().x / 2, unstashTargetY);
+
+            mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, unstashTarget,
+                    LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+            LauncherInstrumentation.log("showTaskbar: sent down");
+
+            try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
+                mLauncher.waitForLauncherObject("taskbar_view");
+                mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, unstashTarget,
+                        LauncherInstrumentation.GestureScope.OUTSIDE_WITH_PILFER);
+
+                return new Taskbar(mLauncher);
+            }
+        } finally {
+            mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
+        }
+    }
+
+    static void dragToSplitscreen(
+            LauncherInstrumentation launcher, Launchable launchable, String expectedNewPackageName,
+            String expectedExistingPackageName) {
+        try (LauncherInstrumentation.Closable c1 = launcher.addContextLayer(
+                "want to drag taskbar item to splitscreen")) {
+            final Point displaySize = launcher.getRealDisplaySize();
+            final Point endPoint = new Point(displaySize.x / 4, 3 * displaySize.y / 4);
+            final long downTime = SystemClock.uptimeMillis();
+            // Use mObject before starting drag since the system drag and drop moves the original
+            // view.
+            Point itemVisibleCenter = launchable.mObject.getVisibleCenter();
+            Rect itemVisibleBounds = launcher.getVisibleBounds(launchable.mObject);
+            String itemLabel = launchable.mObject.getText();
+
+            Point dragStart = launchable.startDrag(
+                    downTime,
+                    launchable::addExpectedEventsForLongClick,
+                    /* runToSpringLoadedState= */ false);
+
+            try (LauncherInstrumentation.Closable c2 = launcher.addContextLayer(
+                    "started item drag")) {
+                launcher.movePointer(
+                        dragStart,
+                        endPoint,
+                        DEFAULT_DRAG_STEPS,
+                        /* isDecelerating= */ true,
+                        downTime,
+                        SystemClock.uptimeMillis(),
+                        /* slowDown= */ false,
+                        LauncherInstrumentation.GestureScope.INSIDE);
+
+                try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
+                        "moved pointer to drop point")) {
+                    dropDraggedItem(
+                            launcher,
+                            launchable,
+                            expectedNewPackageName,
+                            endPoint, downTime,
+                            itemVisibleCenter,
+                            itemVisibleBounds,
+                            itemLabel,
+                            expectedExistingPackageName);
+                }
+            }
+        }
+    }
+
+    private static void dropDraggedItem(
+            LauncherInstrumentation launcher, Launchable launchable, String expectedNewPackageName,
+            Point endPoint, long downTime, Point itemVisibleCenter, Rect itemVisibleBounds,
+            String itemLabel, String expectedExistingPackageName) {
+        LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen before drop "
+                + itemVisibleCenter + " in " + itemVisibleBounds);
+
+        launchable.executeAndWaitForWindowChange(() -> {
+            launcher.sendPointer(
+                    downTime,
+                    SystemClock.uptimeMillis(),
+                    MotionEvent.ACTION_UP,
+                    endPoint,
+                    LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
+            LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: after "
+                    + "drop");
+        }, itemLabel, "dropping taskbar item");
+
+        try (LauncherInstrumentation.Closable c = launcher.addContextLayer("dropped item")) {
+            launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName));
+            launcher.checkPackagesVisible(
+                    new String[] {expectedNewPackageName, expectedExistingPackageName});
+        }
+    }
 }
diff --git a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
index bbfbc55..1e3b078 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -84,6 +84,7 @@
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Optional;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
 import java.util.function.Consumer;
@@ -123,7 +124,8 @@
     // Types for launcher containers that the user is interacting with. "Background" is a
     // pseudo-container corresponding to inactive launcher covered by another app.
     public enum ContainerType {
-        WORKSPACE, HOME_ALL_APPS, OVERVIEW, WIDGETS, FALLBACK_OVERVIEW, LAUNCHED_APP
+        WORKSPACE, HOME_ALL_APPS, OVERVIEW, WIDGETS, FALLBACK_OVERVIEW, LAUNCHED_APP,
+        TASKBAR_ALL_APPS
     }
 
     public enum NavigationModel {ZERO_BUTTON, THREE_BUTTON}
@@ -167,6 +169,7 @@
     private static final String OVERVIEW_RES_ID = "overview_panel";
     private static final String WIDGETS_RES_ID = "primary_widgets_list_view";
     private static final String CONTEXT_MENU_RES_ID = "popup_container";
+    private static final String TASKBAR_RES_ID = "taskbar_view";
     public static final int WAIT_TIME_MS = 60000;
     private static final String SYSTEMUI_PACKAGE = "com.android.systemui";
     private static final String ANDROID_PACKAGE = "android";
@@ -500,6 +503,16 @@
         }
     }
 
+    void checkPackagesVisible(String[] expectedVisiblePackages) {
+        Set<String> actualVisiblePackages =
+                getVisiblePackagesStream().collect(Collectors.toSet());
+
+        for (String expectedVisible : expectedVisiblePackages) {
+            assertTrue("Expected package not visible: " + expectedVisible,
+                    actualVisiblePackages.contains(expectedVisible));
+        }
+    }
+
     private String getVisiblePackages() {
         final String apps = getVisiblePackagesStream().collect(Collectors.joining(", "));
         return !apps.isEmpty()
@@ -722,27 +735,41 @@
                     waitUntilLauncherObjectGone(APPS_RES_ID);
                     waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
                     waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+                    waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
                     return waitForLauncherObject(WORKSPACE_RES_ID);
                 }
                 case WIDGETS: {
                     waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
                     waitUntilLauncherObjectGone(APPS_RES_ID);
                     waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
+                    waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
                     return waitForLauncherObject(WIDGETS_RES_ID);
                 }
+                case TASKBAR_ALL_APPS:
                 case HOME_ALL_APPS: {
                     waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
                     waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
                     waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+                    waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
                     return waitForLauncherObject(APPS_RES_ID);
                 }
                 case OVERVIEW: {
                     waitUntilLauncherObjectGone(APPS_RES_ID);
                     waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
                     waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+                    waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
                     return waitForLauncherObject(OVERVIEW_RES_ID);
                 }
                 case FALLBACK_OVERVIEW: {
+                    waitUntilLauncherObjectGone(APPS_RES_ID);
+                    waitUntilLauncherObjectGone(WORKSPACE_RES_ID);
+                    waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+                    waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+
                     return waitForFallbackLauncherObject(OVERVIEW_RES_ID);
                 }
                 case LAUNCHED_APP: {
@@ -750,6 +777,12 @@
                     waitUntilLauncherObjectGone(APPS_RES_ID);
                     waitUntilLauncherObjectGone(OVERVIEW_RES_ID);
                     waitUntilLauncherObjectGone(WIDGETS_RES_ID);
+
+                    if (isTablet() && !isFallbackOverview()) {
+                        waitForLauncherObject(TASKBAR_RES_ID);
+                    } else {
+                        waitUntilLauncherObjectGone(TASKBAR_RES_ID);
+                    }
                     return null;
                 }
                 default:
@@ -863,8 +896,13 @@
                 setForcePauseTimeout(FORCE_PAUSE_TIMEOUT_MS);
 
                 final Point displaySize = getRealDisplaySize();
+                // The swipe up to home gesture starts from inside the launcher when the user is
+                // already home. Otherwise, the gesture can start inside the launcher process if the
+                // taskbar is visible.
                 boolean gestureStartFromLauncher = isTablet()
-                        ? !isLauncher3() || hasLauncherObject(WORKSPACE_RES_ID)
+                        ? !isLauncher3()
+                        || hasLauncherObject(WORKSPACE_RES_ID)
+                        || hasLauncherObject(TASKBAR_RES_ID)
                         : isLauncherVisible();
 
                 // CLose floating views before going back to home.
@@ -1301,9 +1339,7 @@
     }
 
     void scrollToLastVisibleRow(
-            UiObject2 container,
-            Collection<UiObject2> items,
-            int topPaddingInContainer) {
+            UiObject2 container, Collection<UiObject2> items, int topPaddingInContainer) {
         final UiObject2 lowestItem = Collections.max(items, (i1, i2) ->
                 Integer.compare(getVisibleBounds(i1).top, getVisibleBounds(i2).top));
 
@@ -1326,8 +1362,8 @@
                         containerRect.height() - distance - bottomGestureMarginInContainer,
                         0,
                         bottomGestureMarginInContainer),
-                10,
-                true);
+                /* steps= */ 10,
+                /* slowDown= */ true);
     }
 
     void scrollLeftByDistance(UiObject2 container, int distance) {
@@ -1650,6 +1686,29 @@
         getTestInfo(TestProtocol.REQUEST_CLEAR_DATA);
     }
 
+    /**
+     * Reloads the workspace with a test layout that includes the Test Activity app icon on the
+     * hotseat.
+     */
+    public void useTestWorkspaceLayoutOnReload() {
+        getTestInfo(TestProtocol.REQUEST_USE_TEST_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);
+    }
+
+    /** Shows the taskbar if it is hidden, otherwise does nothing. */
+    public void showTaskbarIfHidden() {
+        getTestInfo(TestProtocol.REQUEST_UNSTASH_TASKBAR_IF_STASHED);
+    }
+
+    public List<String> getHotseatIconNames() {
+        return getTestInfo(TestProtocol.REQUEST_HOTSEAT_ICON_NAMES)
+                .getStringArrayList(TestProtocol.TEST_INFO_RESPONSE_FIELD);
+    }
+
     private String[] getActivities() {
         return getTestInfo(TestProtocol.REQUEST_GET_ACTIVITIES)
                 .getStringArray(TestProtocol.TEST_INFO_RESPONSE_FIELD);
diff --git a/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java b/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java
new file mode 100644
index 0000000..ce1c3c0
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/SplitscreenDragSource.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+package com.android.launcher3.tapl;
+
+/** Launchable that can serve as a source for dragging and dropping to splitscreen. */
+interface SplitscreenDragSource {
+
+    /**
+     * Drags this app icon to the left (landscape) or bottom (portrait) of the screen, launching it
+     * in splitscreen.
+     *
+     * @param expectedNewPackageName package name of the app being dragged
+     * @param expectedExistingPackageName package name of the already-launched app
+     */
+    default void dragToSplitscreen(
+            String expectedNewPackageName, String expectedExistingPackageName) {
+        Launchable launchable = getLaunchable();
+        LauncherInstrumentation launcher = launchable.mLauncher;
+        try (LauncherInstrumentation.Closable e = launcher.eventsCheck()) {
+            LaunchedAppState.dragToSplitscreen(
+                    launcher, launchable, expectedNewPackageName, expectedExistingPackageName);
+        }
+    }
+
+    Launchable getLaunchable();
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Taskbar.java b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
new file mode 100644
index 0000000..b5a08c3
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/Taskbar.java
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+package com.android.launcher3.tapl;
+
+import static com.android.launcher3.testing.TestProtocol.REQUEST_DISABLE_MANUAL_TASKBAR_STASHING;
+import static com.android.launcher3.testing.TestProtocol.REQUEST_ENABLE_MANUAL_TASKBAR_STASHING;
+
+import android.graphics.Point;
+import android.os.SystemClock;
+import android.text.TextUtils;
+import android.view.MotionEvent;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.test.uiautomator.By;
+import androidx.test.uiautomator.BySelector;
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Operations on the Taskbar from LaunchedApp.
+ */
+public final class Taskbar {
+
+    private final LauncherInstrumentation mLauncher;
+
+    Taskbar(LauncherInstrumentation launcher) {
+        mLauncher = launcher;
+    }
+
+    /**
+     * Returns an app icon with the given name. This fails if the icon is not found.
+     */
+    @NonNull
+    public TaskbarAppIcon getAppIcon(String appName) {
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "want to get a taskbar icon")) {
+            return new TaskbarAppIcon(mLauncher, mLauncher.waitForObjectInContainer(
+                    mLauncher.waitForLauncherObject("taskbar_view"),
+                    AppIcon.getAppIconSelector(appName, mLauncher)));
+        }
+    }
+
+    /**
+     * Hides this taskbar.
+     *
+     * The taskbar must already be visible when calling this method.
+     */
+    public void hide() {
+        mLauncher.getTestInfo(REQUEST_ENABLE_MANUAL_TASKBAR_STASHING);
+
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "want to hide the taskbar");
+             LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+            mLauncher.waitForLauncherObject("taskbar_view");
+
+            final long downTime = SystemClock.uptimeMillis();
+            Point stashTarget = new Point(
+                    mLauncher.getRealDisplaySize().x - 1, mLauncher.getRealDisplaySize().y - 1);
+
+            mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_DOWN, stashTarget,
+                    LauncherInstrumentation.GestureScope.INSIDE);
+            LauncherInstrumentation.log("hideTaskbar: sent down");
+
+            try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("pressed down")) {
+                mLauncher.waitUntilLauncherObjectGone("taskbar_view");
+                mLauncher.sendPointer(downTime, downTime, MotionEvent.ACTION_UP, stashTarget,
+                        LauncherInstrumentation.GestureScope.INSIDE);
+            }
+        } finally {
+            mLauncher.getTestInfo(REQUEST_DISABLE_MANUAL_TASKBAR_STASHING);
+        }
+    }
+
+    /**
+     * Opens the Taskbar all apps page.
+     */
+    public AllAppsFromTaskbar openAllApps() {
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "want to open taskbar all apps");
+             LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
+
+            mLauncher.clickLauncherObject(mLauncher.waitForObjectInContainer(
+                    mLauncher.waitForLauncherObject("taskbar_view"), getAllAppsButtonSelector()));
+
+            return new AllAppsFromTaskbar(mLauncher);
+        }
+    }
+
+    /** Returns a list of app icon names on the Taskbar */
+    public List<String> getIconNames() {
+        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+                "want to get all taskbar icons")) {
+            return mLauncher.waitForObjectsInContainer(
+                    mLauncher.waitForLauncherObject("taskbar_view"),
+                    AppIcon.getAnyAppIconSelector())
+                    .stream()
+                    .map(UiObject2::getText)
+                    .filter(text -> !TextUtils.isEmpty(text)) // Filter out the all apps button
+                    .collect(Collectors.toList());
+        }
+    }
+
+    private static BySelector getAllAppsButtonSelector() {
+        // Look for an icon with no text
+        return By.clazz(TextView.class).text("");
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java
new file mode 100644
index 0000000..099acd4
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIcon.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import java.util.regex.Pattern;
+
+/**
+ * App icon specifically on the Taskbar.
+ */
+public final class TaskbarAppIcon extends AppIcon implements SplitscreenDragSource {
+
+    private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onTaskbarItemLongClick");
+
+    TaskbarAppIcon(LauncherInstrumentation launcher, UiObject2 icon) {
+        super(launcher, icon);
+    }
+
+    @Override
+    protected Pattern getLongClickEvent() {
+        return LONG_CLICK_EVENT;
+    }
+
+    @Override
+    public TaskbarAppIconMenu openDeepShortcutMenu() {
+        return (TaskbarAppIconMenu) super.openDeepShortcutMenu();
+    }
+
+    @Override
+    protected TaskbarAppIconMenu createMenu(UiObject2 menu) {
+        return new TaskbarAppIconMenu(mLauncher, menu);
+    }
+
+    @Override
+    public Launchable getLaunchable() {
+        return this;
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java
new file mode 100644
index 0000000..1f137c5
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenu.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+/**
+ * Context menu of a Taskbar app icon.
+ */
+public final class TaskbarAppIconMenu extends AppIconMenu {
+
+    TaskbarAppIconMenu(LauncherInstrumentation launcher, UiObject2 deepShortcutsContainer) {
+        super(launcher, deepShortcutsContainer);
+    }
+
+    @Override
+    public TaskbarAppIconMenuItem getMenuItem(String shortcutText) {
+        return (TaskbarAppIconMenuItem) super.getMenuItem(shortcutText);
+    }
+
+    @Override
+    protected TaskbarAppIconMenuItem createMenuItem(UiObject2 menuItem) {
+        return new TaskbarAppIconMenuItem(mLauncher, menuItem);
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java
new file mode 100644
index 0000000..69a8a08
--- /dev/null
+++ b/tests/tapl/com/android/launcher3/tapl/TaskbarAppIconMenuItem.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2022 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.
+ */
+package com.android.launcher3.tapl;
+
+import androidx.test.uiautomator.UiObject2;
+
+import com.android.launcher3.testing.TestProtocol;
+
+import java.util.regex.Pattern;
+
+/**
+ * Menu item in a Taskbar app icon menu.
+ */
+public final class TaskbarAppIconMenuItem extends AppIconMenuItem implements SplitscreenDragSource {
+
+    private static final Pattern LONG_CLICK_EVENT = Pattern.compile("onTaskbarItemLongClick");
+
+    TaskbarAppIconMenuItem(
+            LauncherInstrumentation launcher, UiObject2 shortcut) {
+        super(launcher, shortcut);
+    }
+
+    @Override
+    protected void addExpectedEventsForLongClick() {
+        mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT);
+    }
+
+    @Override
+    protected void waitForLongPressConfirmation() {
+        // On long-press, the popup container closes and the system drag-and-drop begins. This
+        // only leaves launcher views that were previously visible.
+        mLauncher.waitUntilLauncherObjectGone("popup_container");
+    }
+
+    @Override
+    protected String launchableType() {
+        return "taskbar app icon menu item";
+    }
+
+    @Override
+    public Launchable getLaunchable() {
+        return this;
+    }
+}
diff --git a/tests/tapl/com/android/launcher3/tapl/Widget.java b/tests/tapl/com/android/launcher3/tapl/Widget.java
index 73e9830..2346249 100644
--- a/tests/tapl/com/android/launcher3/tapl/Widget.java
+++ b/tests/tapl/com/android/launcher3/tapl/Widget.java
@@ -39,8 +39,8 @@
     }
 
     @Override
-    protected String getLongPressIndicator() {
-        return "drop_target_bar";
+    protected void waitForLongPressConfirmation() {
+        mLauncher.waitForLauncherObject("drop_target_bar");
     }
 
     @Override
diff --git a/tests/tapl/com/android/launcher3/tapl/Workspace.java b/tests/tapl/com/android/launcher3/tapl/Workspace.java
index 3bc5389..fee4490 100644
--- a/tests/tapl/com/android/launcher3/tapl/Workspace.java
+++ b/tests/tapl/com/android/launcher3/tapl/Workspace.java
@@ -205,7 +205,6 @@
                 mLauncher,
                 homeAppIcon,
                 new Point(targetX, mLauncher.getVisibleBounds(workspace).centerY()),
-                "popup_container",
                 false,
                 false,
                 () -> mLauncher.expectEvent(
@@ -244,11 +243,11 @@
              LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
                      "removing app icon from workspace")) {
             dragIconToWorkspace(
-                    mLauncher, homeAppIcon,
+                    mLauncher,
+                    homeAppIcon,
                     () -> getDropPointFromDropTargetBar(mLauncher, DELETE_TARGET_TEXT_ID),
-                    homeAppIcon.getLongPressIndicator(),
                     () -> mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT),
-                    null);
+                    /* expectDropEvents= */ null);
 
             try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
                     "dragged the app to the drop bar")) {
@@ -274,11 +273,11 @@
         try (LauncherInstrumentation.Closable c = launcher.addContextLayer(
                 "uninstalling app icon")) {
             dragIconToWorkspace(
-                    launcher, homeAppIcon,
+                    launcher,
+                    homeAppIcon,
                     () -> getDropPointFromDropTargetBar(launcher, UNINSTALL_TARGET_TEXT_ID),
-                    homeAppIcon.getLongPressIndicator(),
                     expectLongClickEvents,
-                    null);
+                    /* expectDropEvents= */null);
 
             launcher.waitUntilLauncherObjectGone(DROP_BAR_RES_ID);
 
@@ -345,15 +344,15 @@
     }
 
     static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
-            Point dest, String longPressIndicator, boolean startsActivity, boolean isWidgetShortcut,
+            Point dest, boolean startsActivity, boolean isWidgetShortcut,
             Runnable expectLongClickEvents) {
         Runnable expectDropEvents = null;
         if (startsActivity || isWidgetShortcut) {
             expectDropEvents = () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN,
                     LauncherInstrumentation.EVENT_START);
         }
-        dragIconToWorkspace(launcher, launchable, () -> dest, longPressIndicator,
-                expectLongClickEvents, expectDropEvents);
+        dragIconToWorkspace(
+                launcher, launchable, () -> dest, expectLongClickEvents, expectDropEvents);
     }
 
     /**
@@ -361,22 +360,27 @@
      * (There is no slow down time before drop event)
      * This function expects the launchable is inside the workspace and there is no drop event.
      */
-    static void dragIconToWorkspace(LauncherInstrumentation launcher, Launchable launchable,
-            Supplier<Point> destSupplier, String longPressIndicator) {
-        dragIconToWorkspace(launcher, launchable, destSupplier, longPressIndicator,
-                () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT), null);
+    static void dragIconToWorkspace(
+            LauncherInstrumentation launcher, Launchable launchable, Supplier<Point> destSupplier) {
+        dragIconToWorkspace(
+                launcher,
+                launchable,
+                destSupplier,
+                () -> launcher.expectEvent(TestProtocol.SEQUENCE_MAIN, LONG_CLICK_EVENT),
+                /* expectDropEvents= */ null);
     }
 
     static void dragIconToWorkspace(
-            LauncherInstrumentation launcher, Launchable launchable, Supplier<Point> dest,
-            String longPressIndicator, Runnable expectLongClickEvents,
+            LauncherInstrumentation launcher,
+            Launchable launchable,
+            Supplier<Point> dest,
+            Runnable expectLongClickEvents,
             @Nullable Runnable expectDropEvents) {
         try (LauncherInstrumentation.Closable ignored = launcher.addContextLayer(
                 "want to drag icon to workspace")) {
             final long downTime = SystemClock.uptimeMillis();
             Point dragStart = launchable.startDrag(
                     downTime,
-                    longPressIndicator,
                     expectLongClickEvents,
                     /* runToSpringLoadedState= */ true);
             Point targetDest = dest.get();
diff --git a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
index 93c2213..d8d4420 100644
--- a/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
+++ b/tests/tapl/com/android/launcher3/tapl/WorkspaceDragSource.java
@@ -41,7 +41,6 @@
                                     ? launchableCenter.x - width / 2
                                     : launchableCenter.x + width / 2,
                             displaySize.y / 2),
-                    launchable.getLongPressIndicator(),
                     startsActivity,
                     isWidgetShortcut,
                     launchable::addExpectedEventsForLongClick);