Merge "Update drop target button alignment across devices." into tm-dev
diff --git a/quickstep/res/values-sw600dp-land/dimens.xml b/quickstep/res/values-sw600dp-land/dimens.xml
index 2cd48d5..0cd9b2b 100644
--- a/quickstep/res/values-sw600dp-land/dimens.xml
+++ b/quickstep/res/values-sw600dp-land/dimens.xml
@@ -15,7 +15,6 @@
 */
 -->
 <resources>
+    <!--  Overview actions  -->
     <dimen name="overview_actions_top_margin">12dp</dimen>
-    <dimen name="overview_grid_side_margin">52dp</dimen>
-    <dimen name="overview_page_spacing">38dp</dimen>
 </resources>
diff --git a/quickstep/res/values-sw600dp/dimens.xml b/quickstep/res/values-sw600dp/dimens.xml
index 5153afa..7494683 100644
--- a/quickstep/res/values-sw600dp/dimens.xml
+++ b/quickstep/res/values-sw600dp/dimens.xml
@@ -17,11 +17,13 @@
 <resources>
     <dimen name="navigation_key_padding">25dp</dimen>
 
+    <!--  Task View  -->
+    <dimen name="task_thumbnail_icon_size">48dp</dimen>
+    <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
     <dimen name="overview_task_margin">12dp</dimen>
-    <dimen name="overview_task_margin_grid">4dp</dimen>
-    <dimen name="overview_actions_button_spacing">36dp</dimen>
-    <dimen name="overview_grid_side_margin">60dp</dimen>
-    <dimen name="overview_grid_row_spacing">36dp</dimen>
+    <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
+    <dimen name="overview_task_margin_grid">12dp</dimen>
+    <dimen name="overview_grid_row_spacing">28dp</dimen>
     <dimen name="overview_page_spacing">36dp</dimen>
-    <dimen name="task_thumbnail_icon_drawable_size_grid">32dp</dimen>
+    <dimen name="overview_grid_side_margin">64dp</dimen>
 </resources>
diff --git a/quickstep/res/values-sw720dp-land/dimens.xml b/quickstep/res/values-sw720dp-land/dimens.xml
new file mode 100644
index 0000000..02d1189
--- /dev/null
+++ b/quickstep/res/values-sw720dp-land/dimens.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ * 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.
+*/
+-->
+<resources>
+    <!--  Overview actions  -->
+    <dimen name="overview_actions_top_margin">20dp</dimen>
+</resources>
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index e381cb0..ceaa8f8 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -15,11 +15,13 @@
 */
 -->
 <resources>
+    <!--  Task View  -->
+    <dimen name="task_thumbnail_icon_size">48dp</dimen>
+    <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
     <dimen name="overview_task_margin">16dp</dimen>
+    <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
     <dimen name="overview_task_margin_grid">16dp</dimen>
-    <dimen name="overview_grid_side_margin">64dp</dimen>
     <dimen name="overview_grid_row_spacing">36dp</dimen>
     <dimen name="overview_page_spacing">44dp</dimen>
-    <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
-    <dimen name="task_thumbnail_icon_drawable_size_grid">44dp</dimen>
+    <dimen name="overview_grid_side_margin">64dp</dimen>
 </resources>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 4210052..3072a3e 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -15,8 +15,6 @@
 -->
 
 <resources>
-    <dimen name="task_thumbnail_icon_size">48dp</dimen>
-    <dimen name="task_thumbnail_icon_drawable_size">48dp</dimen>
     <!-- For screens without rounded corners -->
     <dimen name="task_corner_radius_small">2dp</dimen>
     <!-- For Launchers that want to override the default dialog corner radius -->
@@ -32,18 +30,20 @@
     <dimen name="overview_proactive_row_bottom_margin">16dp</dimen>
 
     <dimen name="overview_minimum_next_prev_size">50dp</dimen>
+
+    <!--  Task View  -->
+    <dimen name="task_thumbnail_icon_size">48dp</dimen>
+    <dimen name="task_thumbnail_icon_drawable_size">44dp</dimen>
     <dimen name="overview_task_margin">16dp</dimen>
-    <dimen name="overview_task_margin_grid">0dp</dimen>
+    <dimen name="overview_page_spacing">16dp</dimen>
+
     <item name="overview_max_scale" format="float" type="dimen">0.7</item>
     <item name="overview_modal_max_scale" format="float" type="dimen">1.1</item>
 
     <!-- Overrideable in overlay that provides the Overview Actions. -->
-    <dimen name="overview_actions_height">48dp</dimen>
-    <dimen name="overview_actions_button_spacing">32dp</dimen>
     <dimen name="overview_actions_top_margin">24dp</dimen>
-    <dimen name="overview_actions_horizontal_margin">16dp</dimen>
-
-    <dimen name="overview_page_spacing">16dp</dimen>
+    <dimen name="overview_actions_height">48dp</dimen>
+    <dimen name="overview_actions_button_spacing">36dp</dimen>
 
     <!-- These speeds are in dp/s -->
     <dimen name="max_task_dismiss_drag_velocity">2.25dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java b/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
index 6c4c601..9c3b881 100644
--- a/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
+++ b/quickstep/src/com/android/launcher3/appprediction/InstantAppItemInfo.java
@@ -19,6 +19,7 @@
 import static com.android.quickstep.InstantAppResolverImpl.COMPONENT_CLASS_MARKER;
 
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 
 import com.android.launcher3.LauncherSettings;
@@ -38,8 +39,8 @@
     }
 
     @Override
-    public WorkspaceItemInfo makeWorkspaceItem() {
-        WorkspaceItemInfo workspaceItemInfo = super.makeWorkspaceItem();
+    public WorkspaceItemInfo makeWorkspaceItem(Context context) {
+        WorkspaceItemInfo workspaceItemInfo = super.makeWorkspaceItem(context);
         workspaceItemInfo.itemType = LauncherSettings.Favorites.ITEM_TYPE_APPLICATION;
         workspaceItemInfo.status = WorkspaceItemInfo.FLAG_AUTOINSTALL_ICON
                 | WorkspaceItemInfo.FLAG_RESTORE_STARTED
diff --git a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
index 9c3daea..7e3ee7d 100644
--- a/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
+++ b/quickstep/src/com/android/launcher3/model/PredictionUpdateTask.java
@@ -85,7 +85,7 @@
                         .filter(info -> user.equals(info.user) && cn.equals(info.componentName))
                         .map(ai -> {
                             app.getIconCache().getTitleAndIcon(ai, false);
-                            return ai.makeWorkspaceItem();
+                            return ai.makeWorkspaceItem(context);
                         })
                         .findAny()
                         .orElseGet(() -> {
@@ -96,7 +96,7 @@
                             }
                             AppInfo ai = new AppInfo(context, lai, user);
                             app.getIconCache().getTitleAndIcon(ai, lai, false);
-                            return ai.makeWorkspaceItem();
+                            return ai.makeWorkspaceItem(context);
                         });
 
                 if (itemInfo == null) {
diff --git a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
index 0e534f4..770dfb2 100644
--- a/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
+++ b/quickstep/src/com/android/launcher3/model/QuickstepModelDelegate.java
@@ -460,7 +460,7 @@
                     AppInfo info = new AppInfo(lai, user, mUMS.isUserQuiet(user));
                     mAppState.getIconCache().getTitleAndIcon(info, lai, false);
                     mReadCount++;
-                    return info.makeWorkspaceItem();
+                    return info.makeWorkspaceItem(mAppState.getContext());
                 }
                 case ITEM_TYPE_DEEP_SHORTCUT: {
                     ShortcutKey key = ShortcutKey.fromIntent(intent, user);
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
index c6dbc87..7b4501a 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarPopupController.java
@@ -43,6 +43,7 @@
 import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.LauncherBindableItemsContainer;
 import com.android.launcher3.util.PackageUserKey;
+import com.android.launcher3.util.ShortcutUtil;
 import com.android.launcher3.util.SplitConfigurationOptions.SplitPositionOption;
 import com.android.launcher3.views.ActivityContext;
 import com.android.quickstep.SystemUiProxy;
@@ -136,7 +137,7 @@
             return null;
         }
         ItemInfo item = (ItemInfo) icon.getTag();
-        if (!PopupContainerWithArrow.canShow(icon, item)) {
+        if (!ShortcutUtil.supportsShortcuts(item)) {
             return null;
         }
 
diff --git a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
index 351ec4a..5f3a990 100644
--- a/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
+++ b/quickstep/src/com/android/launcher3/uioverrides/PredictedAppIcon.java
@@ -180,7 +180,7 @@
                 : null;
         super.applyFromWorkspaceItem(info, animate, staggerIndex);
         int oldPlateColor = mPlateColor;
-        int newPlateColor = ColorUtils.setAlphaComponent(mDotParams.color, 200);
+        int newPlateColor = ColorUtils.setAlphaComponent(mDotParams.appColor, 200);
         if (!animate) {
             mPlateColor = newPlateColor;
         }
diff --git a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
index f60b225..dc2b61b 100644
--- a/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
+++ b/quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java
@@ -1065,10 +1065,11 @@
                                 : LAST_TASK;
             }
         } else {
-            // If swiping at a diagonal, base end target on the faster velocity.
+            // If swiping at a diagonal on the current task, base end target on the faster velocity.
             boolean isSwipeUp = endVelocity < 0;
-            boolean willGoToNewTask =
-                    canGoToNewTask && Math.abs(velocity.x) > Math.abs(endVelocity);
+            boolean willGoToNewTask = canGoToNewTask && (
+                    mRecentsView.getDestinationPage() != mRecentsView.getCurrentPage()
+                            || Math.abs(velocity.x) > Math.abs(endVelocity));
 
             if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp) {
                 endTarget = willGoToNewTask ? NEW_TASK : HOME;
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 6745246..2fcd286 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -222,32 +222,27 @@
      */
     public final void calculateTaskSize(Context context, DeviceProfile dp, Rect outRect) {
         Resources res = context.getResources();
+        float maxScale = res.getFloat(R.dimen.overview_max_scale);
         if (dp.isTablet) {
             Rect gridRect = new Rect();
             calculateGridSize(dp, gridRect);
 
-            PointF taskDimension = getTaskDimension(context, dp);
-            float scale = gridRect.height() / taskDimension.y;
-            scale = Math.min(scale, res.getFloat(R.dimen.overview_max_scale));
-            int outWidth = Math.round(scale * taskDimension.x);
-            int outHeight = Math.round(scale * taskDimension.y);
-
-            int gravity = Gravity.CENTER;
-            Gravity.apply(gravity, outWidth, outHeight, gridRect, outRect);
+            calculateTaskSizeInternal(context, dp, gridRect, maxScale, Gravity.CENTER, outRect);
         } else {
             int taskMargin = dp.overviewTaskMarginPx;
             calculateTaskSizeInternal(context, dp,
                     dp.overviewTaskThumbnailTopMarginPx,
                     dp.getOverviewActionsClaimedSpace(),
                     res.getDimensionPixelSize(R.dimen.overview_minimum_next_prev_size) + taskMargin,
+                    maxScale,
                     Gravity.CENTER,
                     outRect);
         }
     }
 
     private void calculateTaskSizeInternal(Context context, DeviceProfile dp, int claimedSpaceAbove,
-            int claimedSpaceBelow, int minimumHorizontalPadding, int gravity, Rect outRect) {
-        PointF taskDimension = getTaskDimension(context, dp);
+            int claimedSpaceBelow, int minimumHorizontalPadding, float maxScale, int gravity,
+            Rect outRect) {
         Rect insets = dp.getInsets();
 
         Rect potentialTaskRect = new Rect(0, 0, dp.widthPx, dp.heightPx);
@@ -258,9 +253,17 @@
                 minimumHorizontalPadding,
                 claimedSpaceBelow);
 
+        calculateTaskSizeInternal(context, dp, potentialTaskRect, maxScale, gravity, outRect);
+    }
+
+    private void calculateTaskSizeInternal(Context context, DeviceProfile dp,
+            Rect potentialTaskRect, float maxScale, int gravity, Rect outRect) {
+        PointF taskDimension = getTaskDimension(context, dp);
+
         float scale = Math.min(
                 potentialTaskRect.width() / taskDimension.x,
                 potentialTaskRect.height() / taskDimension.y);
+        scale = Math.min(scale, maxScale);
         int outWidth = Math.round(scale * taskDimension.x);
         int outHeight = Math.round(scale * taskDimension.y);
 
@@ -359,6 +362,7 @@
                 dp.overviewTaskMarginPx,
                 dp.heightPx - outRect.bottom - dp.getInsets().bottom,
                 Math.round((dp.availableWidthPx - outRect.width() * maxScale) / 2),
+                1f /*maxScale*/,
                 Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM,
                 outRect);
     }
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ee5e024..829a21d 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -277,6 +277,9 @@
     <!-- Summary for Notification dots setting. Tapping this will link enable/disable notification dots feature on the home screen. [CHAR LIMIT=50] -->
     <string name="notification_dots_service_title">Show notification dots</string>
 
+    <!-- Title for Developer Options setting. [CHAR LIMIT=50] -->
+    <string name="developer_options_title">Developer Options</string>
+
     <!-- Label for the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=60] -->
     <string name="auto_add_shortcuts_label">Add app icons to home screen</string>
     <!-- Text description of the setting that allows the automatic placement of launcher shortcuts for applications and games installed on the device [CHAR LIMIT=NONE] -->
diff --git a/res/xml/launcher_preferences.xml b/res/xml/launcher_preferences.xml
index 90de498..8a0c909 100644
--- a/res/xml/launcher_preferences.xml
+++ b/res/xml/launcher_preferences.xml
@@ -53,7 +53,7 @@
     <androidx.preference.PreferenceScreen
         android:key="pref_developer_options"
         android:persistent="false"
-        android:title="Developer Options"
+        android:title="@string/developer_options_title"
         android:fragment="com.android.launcher3.settings.DeveloperOptionsFragment"/>
 
 </androidx.preference.PreferenceScreen>
diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java
index 6302739..878ac3b 100644
--- a/src/com/android/launcher3/BubbleTextView.java
+++ b/src/com/android/launcher3/BubbleTextView.java
@@ -53,6 +53,7 @@
 
 import com.android.launcher3.accessibility.BaseAccessibilityDelegate;
 import com.android.launcher3.dot.DotInfo;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
 import com.android.launcher3.dragndrop.DraggableView;
 import com.android.launcher3.folder.FolderIcon;
 import com.android.launcher3.graphics.IconShape;
@@ -65,12 +66,11 @@
 import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.ItemInfoWithIcon;
-import com.android.launcher3.model.data.PackageItemInfo;
-import com.android.launcher3.model.data.SearchActionItemInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
+import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.util.SafeCloseable;
+import com.android.launcher3.util.ShortcutUtil;
 import com.android.launcher3.views.ActivityContext;
-import com.android.launcher3.views.BubbleTextHolder;
 import com.android.launcher3.views.IconLabelDotView;
 
 import java.text.NumberFormat;
@@ -174,7 +174,6 @@
     private HandlerRunnable mIconLoadRequest;
 
     private boolean mEnableIconUpdateAnimation = false;
-    private BubbleTextHolder mBubbleTextHolder;
 
     public BubbleTextView(Context context) {
         this(context, null, 0);
@@ -253,7 +252,8 @@
      */
     public void reset() {
         mDotInfo = null;
-        mDotParams.color = Color.TRANSPARENT;
+        mDotParams.dotColor = Color.TRANSPARENT;
+        mDotParams.appColor = Color.TRANSPARENT;
         cancelDotScaleAnim();
         mDotParams.scale = 0f;
         mForceHideDot = false;
@@ -361,15 +361,8 @@
         setDownloadStateContentDescription(info, info.getProgressLevel());
     }
 
-    private void setItemInfo(ItemInfoWithIcon itemInfo) {
+    protected void setItemInfo(ItemInfoWithIcon itemInfo) {
         setTag(itemInfo);
-        if (mBubbleTextHolder != null) {
-            mBubbleTextHolder.onItemInfoUpdated(itemInfo);
-        }
-    }
-
-    public void setBubbleTextHolder(BubbleTextHolder bubbleTextHolder) {
-        mBubbleTextHolder = bubbleTextHolder;
     }
 
     @UiThread
@@ -381,7 +374,9 @@
             flags |= FLAG_NO_BADGE;
         }
         FastBitmapDrawable iconDrawable = info.newIcon(getContext(), flags);
-        mDotParams.color = iconDrawable.getIconColor();
+        mDotParams.appColor = iconDrawable.getIconColor();
+        mDotParams.dotColor = getContext().getResources()
+                .getColor(android.R.color.system_accent3_100, getContext().getTheme());
         setIcon(iconDrawable);
         applyLabel(info);
     }
@@ -917,10 +912,8 @@
             } else if (info instanceof WorkspaceItemInfo) {
                 applyFromWorkspaceItem((WorkspaceItemInfo) info);
                 mActivity.invalidateParent(info);
-            } else if (info instanceof PackageItemInfo) {
-                applyFromItemInfoWithIcon((PackageItemInfo) info);
-            } else if (info instanceof SearchActionItemInfo) {
-                applyFromItemInfoWithIcon((SearchActionItemInfo) info);
+            } else if (info != null) {
+                applyFromItemInfoWithIcon(info);
             }
 
             mDisableRelayout = false;
@@ -1058,4 +1051,19 @@
         args.put("count", notificationCount);
         return icuCountFormat.format(args);
     }
+
+    /**
+     * Starts a long press action and returns the corresponding pre-drag condition
+     */
+    public PreDragCondition startLongPressAction() {
+        PopupContainerWithArrow popup = PopupContainerWithArrow.showForIcon(this);
+        return popup != null ? popup.createPreDragCondition(true) : null;
+    }
+
+    /**
+     * Returns true if the view can show long-press popup
+     */
+    public boolean canShowLongPressPopup() {
+        return getTag() instanceof ItemInfo && ShortcutUtil.supportsShortcuts((ItemInfo) getTag());
+    }
 }
diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java
index e088efa..f028d3c 100644
--- a/src/com/android/launcher3/DeviceProfile.java
+++ b/src/com/android/launcher3/DeviceProfile.java
@@ -1169,7 +1169,7 @@
             return  ((taskbarSize - overviewActionsHeight) / 2) + getTaskbarOffsetY();
         }
 
-        return 0;
+        return isTaskbarPresent ? stashedTaskbarSize : mInsets.bottom;
     }
 
     /** Gets the space that the overview actions will take, including bottom margin. */
diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java
index ad87451..135b88d 100644
--- a/src/com/android/launcher3/Launcher.java
+++ b/src/com/android/launcher3/Launcher.java
@@ -1169,6 +1169,7 @@
         }
 
         AbstractFloatingView.closeAllOpenViewsExcept(this, false, TYPE_REBIND_SAFE);
+        DragView.removeAllViews(this);
         TraceHelper.INSTANCE.endSection(traceToken);
     }
 
diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java
index fb028b9..6c091f0 100644
--- a/src/com/android/launcher3/Workspace.java
+++ b/src/com/android/launcher3/Workspace.java
@@ -85,14 +85,12 @@
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.logging.StatsLogManager.LauncherEvent;
-import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
-import com.android.launcher3.model.data.SearchActionItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pageindicators.PageIndicator;
-import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.statemanager.StateManager;
 import com.android.launcher3.statemanager.StateManager.StateHandler;
 import com.android.launcher3.states.StateAnimationConfig;
@@ -1680,11 +1678,7 @@
         }
 
         if (child instanceof BubbleTextView && !dragOptions.isAccessibleDrag) {
-            PopupContainerWithArrow<Launcher> popupContainer = PopupContainerWithArrow
-                    .showForIcon((BubbleTextView) child);
-            if (popupContainer != null) {
-                dragOptions.preDragCondition = popupContainer.createPreDragCondition(true);
-            }
+            dragOptions.preDragCondition = ((BubbleTextView) child).startLongPressAction();
         }
 
         final DragView dv;
@@ -2777,9 +2771,9 @@
                 case LauncherSettings.Favorites.ITEM_TYPE_SHORTCUT:
                 case LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT:
                 case LauncherSettings.Favorites.ITEM_TYPE_SEARCH_ACTION:
-                    if (info instanceof AppInfo) {
+                    if (info instanceof WorkspaceItemFactory) {
                         // Came from all apps -- make a copy
-                        info = ((AppInfo) info).makeWorkspaceItem();
+                        info = ((WorkspaceItemFactory) info).makeWorkspaceItem(mLauncher);
                         d.dragInfo = info;
                     }
                     if (info instanceof WorkspaceItemInfo
@@ -2788,11 +2782,6 @@
                         info = new WorkspaceItemInfo((WorkspaceItemInfo) info);
                         d.dragInfo = info;
                     }
-                    if (info instanceof SearchActionItemInfo) {
-                        info = ((SearchActionItemInfo) info).createWorkspaceItem(
-                                mLauncher.getModel());
-                        d.dragInfo = info;
-                    }
                     view = mLauncher.createShortcut(cellLayout, (WorkspaceItemInfo) info);
                     break;
                 case LauncherSettings.Favorites.ITEM_TYPE_FOLDER:
diff --git a/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
index 14b2431..19d0421 100644
--- a/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/BaseAccessibilityDelegate.java
@@ -23,6 +23,7 @@
 import android.view.View;
 import android.view.accessibility.AccessibilityNodeInfo;
 
+import com.android.launcher3.BubbleTextView;
 import com.android.launcher3.DropTarget;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.dragndrop.DragController;
@@ -31,9 +32,9 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
-import com.android.launcher3.popup.PopupContainerWithArrow;
 import com.android.launcher3.util.Thunk;
 import com.android.launcher3.views.ActivityContext;
+import com.android.launcher3.views.BubbleTextHolder;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -72,7 +73,7 @@
             getSupportedActions(host, item, actions);
             actions.forEach(la -> info.addAction(la.accessibilityAction));
 
-            if (!itemSupportsLongClick(host, item)) {
+            if (!itemSupportsLongClick(host)) {
                 info.setLongClickable(false);
                 info.removeAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_LONG_CLICK);
             }
@@ -84,8 +85,15 @@
      */
     protected abstract void getSupportedActions(View host, ItemInfo item, List<LauncherAction> out);
 
-    private boolean itemSupportsLongClick(View host, ItemInfo info) {
-        return PopupContainerWithArrow.canShow(host, info);
+    private boolean itemSupportsLongClick(View host) {
+        if (host instanceof BubbleTextView) {
+            return ((BubbleTextView) host).canShowLongPressPopup();
+        } else if (host instanceof BubbleTextHolder) {
+            BubbleTextHolder holder = (BubbleTextHolder) host;
+            return holder.getBubbleText() != null && holder.getBubbleText().canShowLongPressPopup();
+        } else {
+            return false;
+        }
     }
 
     protected boolean itemSupportsAccessibleDrag(ItemInfo item) {
@@ -113,7 +121,6 @@
     @Thunk
     protected void announceConfirmation(String confirmation) {
         mContext.getDragLayer().announceForAccessibility(confirmation);
-
     }
 
     public boolean isInAccessibleDrag() {
diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
index 12eb837..44d57d7 100644
--- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
+++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java
@@ -24,13 +24,14 @@
 import com.android.launcher3.R;
 import com.android.launcher3.Workspace;
 import com.android.launcher3.dragndrop.DragOptions;
+import com.android.launcher3.dragndrop.DragOptions.PreDragCondition;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.folder.Folder;
 import com.android.launcher3.keyboard.KeyboardDragAndDropView;
-import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.notification.NotificationListener;
 import com.android.launcher3.popup.ArrowPopup;
@@ -40,6 +41,7 @@
 import com.android.launcher3.util.IntSet;
 import com.android.launcher3.util.ShortcutUtil;
 import com.android.launcher3.util.Thunk;
+import com.android.launcher3.views.BubbleTextHolder;
 import com.android.launcher3.views.OptionsPopupView;
 import com.android.launcher3.views.OptionsPopupView.OptionItem;
 import com.android.launcher3.widget.LauncherAppWidgetHostView;
@@ -118,7 +120,7 @@
             }
         }
 
-        if ((item instanceof AppInfo) || (item instanceof WorkspaceItemInfo)
+        if ((item instanceof WorkspaceItemFactory) || (item instanceof WorkspaceItemInfo)
                 || (item instanceof PendingAddItemInfo)) {
             out.add(mActions.get(ADD_TO_WORKSPACE));
         }
@@ -143,13 +145,18 @@
     protected boolean performAction(final View host, final ItemInfo item, int action,
             boolean fromKeyboard) {
         if (action == ACTION_LONG_CLICK) {
-            if (PopupContainerWithArrow.canShow(host, item)) {
-                // Long press should be consumed for workspace items, and it should invoke the
-                // Shortcuts / Notifications / Actions pop-up menu, and not start a drag as the
-                // standard long press path does.
-                PopupContainerWithArrow.showForIcon((BubbleTextView) host);
-                return true;
+            PreDragCondition dragCondition = null;
+            // Long press should be consumed for workspace items, and it should invoke the
+            // Shortcuts / Notifications / Actions pop-up menu, and not start a drag as the
+            // standard long press path does.
+            if (host instanceof BubbleTextView) {
+                dragCondition = ((BubbleTextView) host).startLongPressAction();
+            } else if (host instanceof BubbleTextHolder) {
+                BubbleTextHolder holder = (BubbleTextHolder) host;
+                dragCondition = holder.getBubbleText() == null ? null
+                        : holder.getBubbleText().startLongPressAction();
             }
+            return dragCondition != null;
         } else if (action == MOVE) {
             return beginAccessibleDrag(host, item, fromKeyboard);
         } else if (action == ADD_TO_WORKSPACE) {
@@ -166,7 +173,10 @@
             popup.setOnCloseCallback(host::requestFocus);
             return true;
         } else if (action == DEEP_SHORTCUTS || action == SHORTCUTS_AND_NOTIFICATIONS) {
-            return PopupContainerWithArrow.showForIcon((BubbleTextView) host) != null;
+            BubbleTextView btv = host instanceof BubbleTextView ? (BubbleTextView) host
+                    : (host instanceof BubbleTextHolder
+                            ? ((BubbleTextHolder) host).getBubbleText() : null);
+            return btv != null && PopupContainerWithArrow.showForIcon(btv) != null;
         } else {
             for (ButtonDropTarget dropTarget : mContext.getDropTargetBar().getDropTargets()) {
                 if (dropTarget.supportsAccessibilityDrop(item, host)
@@ -367,8 +377,8 @@
             return false;
         }
         mContext.getStateManager().goToState(NORMAL, true, forSuccessCallback(() -> {
-            if (item instanceof AppInfo) {
-                WorkspaceItemInfo info = ((AppInfo) item).makeWorkspaceItem();
+            if (item instanceof WorkspaceItemFactory) {
+                WorkspaceItemInfo info = ((WorkspaceItemFactory) item).makeWorkspaceItem(mContext);
                 mContext.getModelWriter().addItemToDatabase(info,
                         LauncherSettings.Favorites.CONTAINER_DESKTOP,
                         screenId, coordinates[0], coordinates[1]);
diff --git a/src/com/android/launcher3/dragndrop/DragView.java b/src/com/android/launcher3/dragndrop/DragView.java
index a3945fd..0264ae2 100644
--- a/src/com/android/launcher3/dragndrop/DragView.java
+++ b/src/com/android/launcher3/dragndrop/DragView.java
@@ -578,4 +578,19 @@
         iv.setImageDrawable(drawable);
         return iv;
     }
+
+    /**
+     * Removes any stray DragView from the DragLayer.
+     */
+    public static void removeAllViews(ActivityContext activity) {
+        BaseDragLayer dragLayer = activity.getDragLayer();
+        // Iterate in reverse order. DragView is added later to the dragLayer,
+        // and will be one of the last views.
+        for (int i = dragLayer.getChildCount() - 1; i >= 0; i--) {
+            View child = dragLayer.getChildAt(i);
+            if (child instanceof DragView) {
+                dragLayer.removeView(child);
+            }
+        }
+    }
 }
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 8916519..512fa1c 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -88,10 +88,10 @@
 import com.android.launcher3.logger.LauncherAtom.ToState;
 import com.android.launcher3.logging.StatsLogManager;
 import com.android.launcher3.logging.StatsLogManager.StatsLogger;
-import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.FolderInfo.FolderListener;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pageindicators.PageIndicatorDots;
 import com.android.launcher3.util.Executors;
@@ -1283,9 +1283,9 @@
             final WorkspaceItemInfo si;
             if (pasiSi != null) {
                 si = pasiSi;
-            } else if (d.dragInfo instanceof AppInfo) {
+            } else if (d.dragInfo instanceof WorkspaceItemFactory) {
                 // Came from all apps -- make a copy.
-                si = ((AppInfo) d.dragInfo).makeWorkspaceItem();
+                si = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(launcher);
             } else {
                 // WorkspaceItemInfo
                 si = (WorkspaceItemInfo) d.dragInfo;
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 5fe2435..b1e2701 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -68,11 +68,11 @@
 import com.android.launcher3.logger.LauncherAtom.ToState;
 import com.android.launcher3.logging.InstanceId;
 import com.android.launcher3.logging.StatsLogManager;
-import com.android.launcher3.model.data.AppInfo;
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.FolderInfo.FolderListener;
 import com.android.launcher3.model.data.FolderInfo.LabelState;
 import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.touch.ItemClickHandler;
 import com.android.launcher3.util.Executors;
@@ -284,7 +284,7 @@
         mBackground.animateToAccept(cl, lp.cellX, lp.cellY);
         mOpenAlarm.setOnAlarmListener(mOnOpenListener);
         if (SPRING_LOADING_ENABLED &&
-                ((dragInfo instanceof AppInfo)
+                ((dragInfo instanceof WorkspaceItemFactory)
                         || (dragInfo instanceof WorkspaceItemInfo)
                         || (dragInfo instanceof PendingAddShortcutInfo))) {
             mOpenAlarm.setAlarm(ON_OPEN_DELAY);
@@ -486,9 +486,9 @@
 
     public void onDrop(DragObject d, boolean itemReturnedOnFailedDrop) {
         WorkspaceItemInfo item;
-        if (d.dragInfo instanceof AppInfo) {
+        if (d.dragInfo instanceof WorkspaceItemFactory) {
             // Came from all apps -- make a copy
-            item = ((AppInfo) d.dragInfo).makeWorkspaceItem();
+            item = ((WorkspaceItemFactory) d.dragInfo).makeWorkspaceItem(getContext());
         } else if (d.dragSource instanceof BaseItemDragListener){
             // Came from a different window -- make a copy
             item = new WorkspaceItemInfo((WorkspaceItemInfo) d.dragInfo);
@@ -637,7 +637,7 @@
 
             // If we are animating to the accepting state, animate the dot out.
             mDotParams.scale = Math.max(0, mDotScale - mBackground.getScaleProgress());
-            mDotParams.color = mBackground.getDotColor();
+            mDotParams.dotColor = mBackground.getDotColor();
             mDotRenderer.draw(canvas, mDotParams);
         }
     }
diff --git a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
index ca91296..31ef2e5 100644
--- a/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
+++ b/src/com/android/launcher3/model/AddWorkspaceItemsTask.java
@@ -32,6 +32,7 @@
 import com.android.launcher3.model.data.FolderInfo;
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.model.data.LauncherAppWidgetInfo;
+import com.android.launcher3.model.data.WorkspaceItemFactory;
 import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.pm.InstallSessionHelper;
 import com.android.launcher3.pm.PackageInstallInfo;
@@ -107,8 +108,8 @@
                 }
 
                 if (item.itemType == LauncherSettings.Favorites.ITEM_TYPE_APPLICATION) {
-                    if (item instanceof AppInfo) {
-                        item = ((AppInfo) item).makeWorkspaceItem();
+                    if (item instanceof WorkspaceItemFactory) {
+                        item = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
                     }
                 }
                 if (item != null) {
@@ -130,8 +131,8 @@
                 if (item instanceof WorkspaceItemInfo || item instanceof FolderInfo ||
                         item instanceof LauncherAppWidgetInfo) {
                     itemInfo = item;
-                } else if (item instanceof AppInfo) {
-                    itemInfo = ((AppInfo) item).makeWorkspaceItem();
+                } else if (item instanceof WorkspaceItemFactory) {
+                    itemInfo = ((WorkspaceItemFactory) item).makeWorkspaceItem(app.getContext());
                 } else {
                     throw new RuntimeException("Unexpected info type");
                 }
@@ -180,7 +181,7 @@
                         // App was installed while launcher was in the background,
                         // or app was already installed for another user.
                         itemInfo = new AppInfo(app.getContext(), activities.get(0), item.user)
-                                .makeWorkspaceItem();
+                                .makeWorkspaceItem(app.getContext());
 
                         if (shortcutExists(dataModel, itemInfo.getIntent(), itemInfo.user)) {
                             // We need this additional check here since we treat all auto added
diff --git a/src/com/android/launcher3/model/data/AppInfo.java b/src/com/android/launcher3/model/data/AppInfo.java
index 7f70bad..5b2bcf5 100644
--- a/src/com/android/launcher3/model/data/AppInfo.java
+++ b/src/com/android/launcher3/model/data/AppInfo.java
@@ -35,7 +35,6 @@
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.Utilities;
 import com.android.launcher3.pm.PackageInstallInfo;
-import com.android.launcher3.util.ComponentKey;
 import com.android.launcher3.util.PackageManagerHelper;
 
 import java.util.Comparator;
@@ -43,7 +42,7 @@
 /**
  * Represents an app in AllAppsView.
  */
-public class AppInfo extends ItemInfoWithIcon {
+public class AppInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
 
     public static final AppInfo[] EMPTY_ARRAY = new AppInfo[0];
     public static final Comparator<AppInfo> COMPONENT_KEY_COMPARATOR = (a, b) -> {
@@ -121,7 +120,8 @@
         return super.dumpProperties() + " componentName=" + componentName;
     }
 
-    public WorkspaceItemInfo makeWorkspaceItem() {
+    @Override
+    public WorkspaceItemInfo makeWorkspaceItem(Context context) {
         WorkspaceItemInfo workspaceItemInfo = new WorkspaceItemInfo(this);
 
         if ((runtimeStatusFlags & FLAG_INSTALL_SESSION_ACTIVE) != 0) {
@@ -139,10 +139,6 @@
         return workspaceItemInfo;
     }
 
-    public ComponentKey toComponentKey() {
-        return new ComponentKey(componentName, user);
-    }
-
     public static Intent makeLaunchIntent(LauncherActivityInfo info) {
         return makeLaunchIntent(info.getComponentName());
     }
diff --git a/src/com/android/launcher3/model/data/SearchActionItemInfo.java b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
index cc22601..e879313 100644
--- a/src/com/android/launcher3/model/data/SearchActionItemInfo.java
+++ b/src/com/android/launcher3/model/data/SearchActionItemInfo.java
@@ -18,6 +18,7 @@
 import static com.android.launcher3.LauncherSettings.Favorites.EXTENDED_CONTAINERS;
 
 import android.app.PendingIntent;
+import android.content.Context;
 import android.content.Intent;
 import android.graphics.drawable.Icon;
 import android.os.Process;
@@ -26,18 +27,14 @@
 import androidx.annotation.Nullable;
 
 import com.android.launcher3.LauncherAppState;
-import com.android.launcher3.LauncherModel;
 import com.android.launcher3.LauncherSettings;
 import com.android.launcher3.logger.LauncherAtom.ItemInfo;
 import com.android.launcher3.logger.LauncherAtom.SearchActionItem;
-import com.android.launcher3.model.AllAppsList;
-import com.android.launcher3.model.BaseModelUpdateTask;
-import com.android.launcher3.model.BgDataModel;
 
 /**
  * Represents a SearchAction with in launcher
  */
-public class SearchActionItemInfo extends ItemInfoWithIcon {
+public class SearchActionItemInfo extends ItemInfoWithIcon implements WorkspaceItemFactory {
 
     public static final int FLAG_SHOULD_START = 1 << 1;
     public static final int FLAG_SHOULD_START_FOR_RESULT = FLAG_SHOULD_START | 1 << 2;
@@ -158,7 +155,8 @@
     /**
      * Creates a {@link WorkspaceItemInfo} coorsponding to search action to be stored in launcher db
      */
-    public WorkspaceItemInfo createWorkspaceItem(LauncherModel model) {
+    @Override
+    public WorkspaceItemInfo makeWorkspaceItem(Context context) {
         WorkspaceItemInfo info = new WorkspaceItemInfo();
         info.title = title;
         info.bitmap = bitmap;
@@ -167,18 +165,12 @@
         if (hasFlags(FLAG_SHOULD_START_FOR_RESULT)) {
             info.options |= WorkspaceItemInfo.FLAG_START_FOR_RESULT;
         }
-
-        model.enqueueModelUpdateTask(new BaseModelUpdateTask() {
-            @Override
-            public void execute(LauncherAppState app, BgDataModel dataModel, AllAppsList apps) {
-
-                model.updateAndBindWorkspaceItem(() -> {
-                    PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
-                    app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
-                    info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
-                    return info;
-                });
-            }
+        LauncherAppState app = LauncherAppState.getInstance(context);
+        app.getModel().updateAndBindWorkspaceItem(() -> {
+            PackageItemInfo pkgInfo = new PackageItemInfo(getIntentPackageName(), user);
+            app.getIconCache().getTitleAndIconForApp(pkgInfo, false);
+            info.bitmap = info.bitmap.withBadgeInfo(pkgInfo.bitmap);
+            return info;
         });
         return info;
     }
diff --git a/src/com/android/launcher3/model/data/WorkspaceItemFactory.java b/src/com/android/launcher3/model/data/WorkspaceItemFactory.java
new file mode 100644
index 0000000..47b9c6e
--- /dev/null
+++ b/src/com/android/launcher3/model/data/WorkspaceItemFactory.java
@@ -0,0 +1,29 @@
+/*
+ * 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.model.data;
+
+import android.content.Context;
+
+/**
+ * Interface to objects capable of generating workspace item
+ */
+public interface WorkspaceItemFactory {
+
+    /**
+     * Called to create a pinnable item info
+     */
+    WorkspaceItemInfo makeWorkspaceItem(Context context);
+}
diff --git a/src/com/android/launcher3/popup/PopupContainerWithArrow.java b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
index 484b879..49d97d2 100644
--- a/src/com/android/launcher3/popup/PopupContainerWithArrow.java
+++ b/src/com/android/launcher3/popup/PopupContainerWithArrow.java
@@ -187,7 +187,10 @@
 
     /**
      * Returns true if we can show the container.
+     *
+     * @deprecated Left here since some dependent projects are using this method
      */
+    @Deprecated
     public static boolean canShow(View icon, ItemInfo item) {
         return icon instanceof BubbleTextView && ShortcutUtil.supportsShortcuts(item);
     }
@@ -204,7 +207,7 @@
             return null;
         }
         ItemInfo item = (ItemInfo) icon.getTag();
-        if (!canShow(icon, item)) {
+        if (!ShortcutUtil.supportsShortcuts(item)) {
             return null;
         }
 
@@ -538,7 +541,7 @@
     public static void dismissInvalidPopup(BaseDraggingActivity activity) {
         PopupContainerWithArrow popup = getOpen(activity);
         if (popup != null && (!popup.mOriginalIcon.isAttachedToWindow()
-                || !canShow(popup.mOriginalIcon, (ItemInfo) popup.mOriginalIcon.getTag()))) {
+                || !ShortcutUtil.supportsShortcuts((ItemInfo) popup.mOriginalIcon.getTag()))) {
             popup.animateClose();
         }
     }
diff --git a/src/com/android/launcher3/touch/ItemClickHandler.java b/src/com/android/launcher3/touch/ItemClickHandler.java
index cd00f15..c4d2bc4 100644
--- a/src/com/android/launcher3/touch/ItemClickHandler.java
+++ b/src/com/android/launcher3/touch/ItemClickHandler.java
@@ -100,8 +100,7 @@
                 onClickFolderIcon(v);
             }
         } else if (tag instanceof AppInfo) {
-            startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher
-            );
+            startAppShortcutOrInfoActivity(v, (AppInfo) tag, launcher);
         } else if (tag instanceof LauncherAppWidgetInfo) {
             if (v instanceof PendingAppWidgetHostView) {
                 onClickPendingWidget((PendingAppWidgetHostView) v, launcher);
diff --git a/src/com/android/launcher3/touch/ItemLongClickListener.java b/src/com/android/launcher3/touch/ItemLongClickListener.java
index f876dd9..6bae745 100644
--- a/src/com/android/launcher3/touch/ItemLongClickListener.java
+++ b/src/com/android/launcher3/touch/ItemLongClickListener.java
@@ -37,6 +37,7 @@
 import com.android.launcher3.model.data.ItemInfo;
 import com.android.launcher3.testing.TestLogging;
 import com.android.launcher3.testing.TestProtocol;
+import com.android.launcher3.views.BubbleTextHolder;
 
 /**
  * Class to handle long-clicks on workspace items and start drag as a result.
@@ -79,9 +80,12 @@
         launcher.getWorkspace().startDrag(longClickCellInfo, dragOptions);
     }
 
-    private static boolean onAllAppsItemLongClick(View v) {
+    private static boolean onAllAppsItemLongClick(View view) {
         TestLogging.recordEvent(TestProtocol.SEQUENCE_MAIN, "onAllAppsItemLongClick");
-        v.cancelLongPress();
+        view.cancelLongPress();
+        View v = (view instanceof BubbleTextHolder)
+                ? ((BubbleTextHolder) view).getBubbleText()
+                : view;
         Launcher launcher = Launcher.getLauncher(v.getContext());
         if (!canStartDrag(launcher)) return false;
         // When we have exited all apps or are in transition, disregard long clicks
diff --git a/src/com/android/launcher3/views/BubbleTextHolder.java b/src/com/android/launcher3/views/BubbleTextHolder.java
index 76c465c..84f8049 100644
--- a/src/com/android/launcher3/views/BubbleTextHolder.java
+++ b/src/com/android/launcher3/views/BubbleTextHolder.java
@@ -16,8 +16,6 @@
 package com.android.launcher3.views;
 
 import com.android.launcher3.BubbleTextView;
-import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.model.data.ItemInfoWithIcon;
 
 /**
  * Views that contain {@link BubbleTextView} should implement this interface.
@@ -25,14 +23,6 @@
 public interface BubbleTextHolder extends IconLabelDotView {
     BubbleTextView getBubbleText();
 
-    /**
-     * Called when new {@link ItemInfo} is set to {@link BubbleTextView}
-     *
-     * @param itemInfo the new itemInfo
-     */
-    default void onItemInfoUpdated(ItemInfoWithIcon itemInfo) {
-    }
-
     @Override
     default void setIconVisible(boolean visible) {
         getBubbleText().setIconVisible(visible);
diff --git a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
index 15e8f68..a3b05f6 100644
--- a/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
+++ b/tests/src/com/android/launcher3/ui/TaplTestsLauncher3.java
@@ -48,11 +48,13 @@
 import com.android.launcher3.tapl.Widgets;
 import com.android.launcher3.tapl.Workspace;
 import com.android.launcher3.util.TestUtil;
+import com.android.launcher3.util.rule.ScreenRecordRule;
 import com.android.launcher3.util.rule.ScreenRecordRule.ScreenRecord;
 import com.android.launcher3.widget.picker.WidgetsFullSheet;
 import com.android.launcher3.widget.picker.WidgetsRecyclerView;
 
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -66,6 +68,10 @@
     private static final String DUMMY_APP_NAME = "Aardwolf";
     private static final String MAPS_APP_NAME = "Maps";
     private static final String STORE_APP_NAME = "Play Store";
+    private static final String GMAIL_APP_NAME = "Gmail";
+
+    @Rule
+    public ScreenRecordRule mScreenRecordRule = new ScreenRecordRule();
 
     @Before
     public void setUp() throws Exception {
@@ -374,28 +380,23 @@
 
     @Test
     @PortraitLandscape
-    public void testDragToFolder() throws Exception {
-        final HomeAppIcon playStoreIcon = createShortcutIfNotExist("Play Store", 0, 1);
-        final HomeAppIcon gmailIcon = createShortcutIfNotExist("Gmail", 1, 1);
+    @ScreenRecord
+    public void testDragToFolder() {
+        // TODO: add the use case to drag an icon to an existing folder. Currently it either fails
+        // on tablets or phones due to difference in resolution.
+        final HomeAppIcon playStoreIcon = createShortcutIfNotExist(STORE_APP_NAME, 0, 1);
+        final HomeAppIcon gmailIcon = createShortcutInCenterIfNotExist(GMAIL_APP_NAME);
 
         FolderIcon folderIcon = gmailIcon.dragToIcon(playStoreIcon);
-
         Folder folder = folderIcon.open();
-        folder.getAppIcon("Play Store");
-        folder.getAppIcon("Gmail");
+        folder.getAppIcon(STORE_APP_NAME);
+        folder.getAppIcon(GMAIL_APP_NAME);
         Workspace workspace = folder.close();
 
-        assertNull("Gmail should be moved to a folder.",
-                workspace.tryGetWorkspaceAppIcon("Gmail"));
-        assertNull("Play Store should be moved to a folder.",
-                workspace.tryGetWorkspaceAppIcon("Play Store"));
-
-        final HomeAppIcon youTubeIcon = createShortcutInCenterIfNotExist("YouTube");
-
-        folderIcon = youTubeIcon.dragToIcon(folderIcon);
-        folder = folderIcon.open();
-        folder.getAppIcon("YouTube");
-        folder.close();
+        assertNull(STORE_APP_NAME + " should be moved to a folder.",
+                workspace.tryGetWorkspaceAppIcon(STORE_APP_NAME));
+        assertNull(GMAIL_APP_NAME + " should be moved to a folder.",
+                workspace.tryGetWorkspaceAppIcon(GMAIL_APP_NAME));
     }
 
     @Test
diff --git a/tests/tapl/com/android/launcher3/tapl/Launchable.java b/tests/tapl/com/android/launcher3/tapl/Launchable.java
index 39cd4ff..91ab1bd 100644
--- a/tests/tapl/com/android/launcher3/tapl/Launchable.java
+++ b/tests/tapl/com/android/launcher3/tapl/Launchable.java
@@ -16,8 +16,6 @@
 
 package com.android.launcher3.tapl;
 
-import static android.view.accessibility.AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
-
 import static com.android.launcher3.testing.TestProtocol.SPRING_LOADED_STATE_ORDINAL;
 
 import android.graphics.Point;
@@ -64,35 +62,25 @@
     protected abstract String launchableType();
 
     private LaunchedAppState launch(BySelector selector) {
-        try (LauncherInstrumentation.Closable c = mLauncher.addContextLayer(
+        try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer(
                 "want to launch an app from " + launchableType())) {
             LauncherInstrumentation.log("Launchable.launch before click "
                     + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
             final String label = mObject.getText();
 
-            executeAndWaitForWindowChange(() -> {
-                mLauncher.clickLauncherObject(mObject);
-                expectActivityStartEvents();
-            }, label, "clicking " + launchableType());
+            mLauncher.clickLauncherObject(mObject);
 
-            try (LauncherInstrumentation.Closable c1 = mLauncher.addContextLayer("clicked")) {
+            try (LauncherInstrumentation.Closable c2 = mLauncher.addContextLayer("clicked")) {
+                expectActivityStartEvents();
                 return assertAppLaunched(label, selector);
             }
         }
     }
 
-    protected void executeAndWaitForWindowChange(Runnable command, String label, String action) {
-        mLauncher.executeAndWaitForEvent(
-                command,
-                event -> event.getEventType() == TYPE_WINDOW_STATE_CHANGED,
-                () -> "Launching an app didn't open a new window: " + label,
-                action);
-    }
-
     protected LaunchedAppState assertAppLaunched(String label, BySelector selector) {
         mLauncher.assertTrue(
                 "App didn't start: " + label + " (" + selector + ")",
-                TestHelpers.wait(Until.hasObject(selector),
+                mLauncher.getDevice().wait(Until.hasObject(selector),
                         LauncherInstrumentation.WAIT_TIME_MS));
         return new LaunchedAppState(mLauncher);
     }
@@ -117,7 +105,6 @@
                     expectLongClickEvents);
         }
 
-
         return dragStartCenter;
     }
 
diff --git a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
index 2033a42..face02a 100644
--- a/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
+++ b/tests/tapl/com/android/launcher3/tapl/LaunchedAppState.java
@@ -129,42 +129,25 @@
 
                 try (LauncherInstrumentation.Closable c3 = launcher.addContextLayer(
                         "moved pointer to drop point")) {
-                    dropDraggedItem(
-                            launcher,
-                            launchable,
-                            expectedNewPackageName,
-                            endPoint, downTime,
-                            itemVisibleCenter,
-                            itemVisibleBounds,
-                            itemLabel,
-                            expectedExistingPackageName);
+                    LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+                            + "before drop " + itemVisibleCenter + " in " + itemVisibleBounds);
+                    launcher.sendPointer(
+                            downTime,
+                            SystemClock.uptimeMillis(),
+                            MotionEvent.ACTION_UP,
+                            endPoint,
+                            LauncherInstrumentation.GestureScope.INSIDE_TO_OUTSIDE_WITHOUT_PILFER);
+                    LauncherInstrumentation.log("SplitscreenDragSource.dragToSplitscreen: "
+                            + "after drop");
+
+                    try (LauncherInstrumentation.Closable c4 = launcher.addContextLayer(
+                            "dropped item")) {
+                        launchable.assertAppLaunched(itemLabel, By.pkg(expectedNewPackageName));
+                        launchable.assertAppLaunched(
+                                itemLabel, By.pkg(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 2b3583e..9d25b1b 100644
--- a/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
+++ b/tests/tapl/com/android/launcher3/tapl/LauncherInstrumentation.java
@@ -84,7 +84,6 @@
 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;
@@ -92,7 +91,6 @@
 import java.util.function.Supplier;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 /**
  * The main tapl object. The only object that can be explicitly constructed by the using code. It
@@ -501,29 +499,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()
-                ? "active app: " + apps
-                : "the test doesn't see views from any app, including Launcher";
-    }
-
-    private Stream<String> getVisiblePackagesStream() {
-        return mDevice.findObjects(getAnyObjectSelector())
+        final String apps = mDevice.findObjects(getAnyObjectSelector())
                 .stream()
                 .map(LauncherInstrumentation::getApplicationPackageSafe)
                 .distinct()
-                .filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg));
+                .filter(pkg -> pkg != null && !SYSTEMUI_PACKAGE.equals(pkg))
+                .collect(Collectors.joining(", "));
+        return !apps.isEmpty()
+                ? "active app: " + apps
+                : "the test doesn't see views from any app, including Launcher";
     }
 
     private static String getApplicationPackageSafe(UiObject2 object) {
@@ -1567,11 +1552,11 @@
 
             // vx0: initial speed at the x-dimension, set as twice the avg speed
             // dx: the constant deceleration at the x-dimension
-            double vx0 = 2 * (to.x - from.x) / duration;
+            double vx0 = 2.0 * (to.x - from.x) / duration;
             double dx = vx0 / duration;
             // vy0: initial speed at the y-dimension, set as twice the avg speed
             // dy: the constant deceleration at the y-dimension
-            double vy0 = 2 * (to.y - from.y) / duration;
+            double vy0 = 2.0 * (to.y - from.y) / duration;
             double dy = vy0 / duration;
 
             for (long i = 0; i < steps; ++i) {
diff --git a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java b/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
deleted file mode 100644
index 42b6bc9..0000000
--- a/tests/tapl/com/android/launcher3/tapl/OptionsPopupMenuItem.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2020 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.By;
-import androidx.test.uiautomator.UiObject2;
-import androidx.test.uiautomator.Until;
-
-import com.android.launcher3.testing.TestProtocol;
-
-public class OptionsPopupMenuItem {
-
-    private final LauncherInstrumentation mLauncher;
-    private final UiObject2 mObject;
-
-    OptionsPopupMenuItem(@NonNull LauncherInstrumentation launcher, @NonNull UiObject2 shortcut) {
-        mLauncher = launcher;
-        mObject = shortcut;
-    }
-
-    /**
-     * Clicks the option.
-     */
-    @NonNull
-    public void launch(@NonNull String expectedPackageName) {
-        try (LauncherInstrumentation.Closable e = mLauncher.eventsCheck()) {
-            LauncherInstrumentation.log("OptionsPopupMenuItem before click "
-                    + mObject.getVisibleCenter() + " in " + mLauncher.getVisibleBounds(mObject));
-            mLauncher.clickLauncherObject(mObject);
-            mLauncher.expectEvent(TestProtocol.SEQUENCE_MAIN, LauncherInstrumentation.EVENT_START);
-            mLauncher.assertTrue(
-                    "App didn't start: " + By.pkg(expectedPackageName),
-                    mLauncher.getDevice().wait(Until.hasObject(By.pkg(expectedPackageName)),
-                            LauncherInstrumentation.WAIT_TIME_MS));
-        }
-    }
-}