Merge changes from topic "bubblebar_drop_target" into main

* changes:
  Removed fly-back animation after a taskbar item drop on the bubble bar
  Added BubbleBarLocation drop target.
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
index d531e2c..1b516be 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragController.java
@@ -68,6 +68,7 @@
 import com.android.launcher3.dragndrop.DragOptions;
 import com.android.launcher3.dragndrop.DragView;
 import com.android.launcher3.dragndrop.DraggableView;
+import com.android.launcher3.folder.Folder;
 import com.android.launcher3.graphics.DragPreviewProvider;
 import com.android.launcher3.logger.LauncherAtom.ContainerInfo;
 import com.android.launcher3.logging.StatsLogManager;
@@ -116,6 +117,7 @@
     private int mRegistrationY;
 
     private boolean mIsSystemDragInProgress;
+    private boolean mIsDropHandledByDropTarget;
 
     // Animation for the drag shadow back into position after an unsuccessful drag
     private ValueAnimator mReturnAnimator;
@@ -252,7 +254,8 @@
                 /* originalView = */ btv,
                 dragLayerX + dragOffset.x,
                 dragLayerY + dragOffset.y,
-                (View target, DropTarget.DragObject d, boolean success) -> {} /* DragSource */,
+                (View target, DropTarget.DragObject d, boolean success) ->
+                        mIsDropHandledByDropTarget = success /* DragSource */,
                 btv.getTag() instanceof ItemInfo itemInfo ? itemInfo : null,
                 dragRect,
                 scale * iconScale,
@@ -561,7 +564,7 @@
 
     @Override
     protected void endDrag() {
-        if (mDisallowGlobalDrag) {
+        if (mDisallowGlobalDrag && !mIsDropHandledByDropTarget) {
             // We need to explicitly set deferDragViewCleanupPostAnimation to true here so the
             // super call doesn't remove it from the drag layer before the animation completes.
             // This variable gets set in to false in super.dispatchDropComplete() because it
@@ -765,8 +768,11 @@
 
     @Override
     public void addDropTarget(DropTarget target) {
-        // No-op as Taskbar currently doesn't support any drop targets internally.
-        // Note: if we do add internal DropTargets, we'll still need to ignore Folder.
+        if (target instanceof Folder) {
+            // we need to ignore Folder.
+            return;
+        }
+        super.addDropTarget(target);
     }
 
     @Override
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarLocationDropTarget.kt b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarLocationDropTarget.kt
new file mode 100644
index 0000000..383f4d2
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarLocationDropTarget.kt
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2025 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.taskbar.bubbles
+
+import android.graphics.Rect
+import android.view.View
+import com.android.launcher3.DropTarget
+import com.android.launcher3.dragndrop.DragOptions
+import com.android.launcher3.model.data.ItemInfo
+import com.android.wm.shell.shared.bubbles.BubbleBarLocation
+
+/**
+ * Implementation of the {@link DropTarget} that handles drag and drop events over the bubble bar
+ * locations.
+ */
+class BubbleBarLocationDropTarget(
+    private val bubbleBarLocation: BubbleBarLocation,
+    private val bubbleBarDragListener: BubbleBarDragListener,
+) : DropTarget {
+
+    /** Controller that takes care of the bubble bar drag events inside launcher process. */
+    interface BubbleBarDragListener {
+
+        /** Called when the drag event is over the bubble bar drop zone. */
+        fun onLauncherItemDraggedOverBubbleBarDragZone(location: BubbleBarLocation)
+
+        /** Called when the drag event leaves the bubble bar drop zone. */
+        fun onLauncherItemDraggedOutsideBubbleBarDropZone()
+
+        /** Called when the drop event happens over the bubble bar drop zone. */
+        fun onLauncherItemDroppedOverBubbleBarDragZone(
+            location: BubbleBarLocation,
+            itemInfo: ItemInfo,
+        )
+
+        /** Gets the hit [rect][android.graphics.Rect] of the bubble bar location. */
+        fun getBubbleBarLocationHitRect(bubbleBarLocation: BubbleBarLocation, outRect: Rect)
+
+        /** Provides the view that will accept the drop. */
+        fun getDropView(): View
+    }
+
+    private var isShowingDropTarget = false
+
+    override fun isDropEnabled(): Boolean = true
+
+    override fun onDrop(dragObject: DropTarget.DragObject, options: DragOptions) {
+        val itemInfo = dragObject.dragInfo ?: return
+        // TODO(b/397459664) : fix task bar icon animation after drop
+        // TODO(b/397459664) : update bubble bar location
+        bubbleBarDragListener.onLauncherItemDroppedOverBubbleBarDragZone(
+            bubbleBarLocation,
+            itemInfo,
+        )
+    }
+
+    override fun onDragEnter(dragObject: DropTarget.DragObject) {}
+
+    override fun onDragOver(dragObject: DropTarget.DragObject) {
+        if (isShowingDropTarget) return
+        isShowingDropTarget = true
+        bubbleBarDragListener.onLauncherItemDraggedOverBubbleBarDragZone(bubbleBarLocation)
+    }
+
+    override fun onDragExit(dragObject: DropTarget.DragObject) {
+        // TODO(b/397459664) : fix the issue for no bubbles, when moving task bar icon out of
+        // the bubble bar drag zone drag ends and swipes gesture swipes the overview
+        if (!isShowingDropTarget) return
+        isShowingDropTarget = false
+        bubbleBarDragListener.onLauncherItemDraggedOutsideBubbleBarDropZone()
+    }
+
+    override fun acceptDrop(dragObject: DropTarget.DragObject): Boolean = true
+
+    override fun prepareAccessibilityDrop() {}
+
+    override fun getHitRectRelativeToDragLayer(outRect: Rect) {
+        bubbleBarDragListener.getBubbleBarLocationHitRect(bubbleBarLocation, outRect)
+    }
+
+    override fun getDropView(): View = bubbleBarDragListener.getDropView()
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
index b90a5b0..1f5c541 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleBarViewController.java
@@ -24,6 +24,8 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorSet;
+import android.content.Intent;
+import android.content.pm.ShortcutInfo;
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.PointF;
@@ -43,11 +45,15 @@
 import com.android.launcher3.R;
 import com.android.launcher3.anim.AnimatedFloat;
 import com.android.launcher3.anim.RoundedRectRevealOutlineProvider;
+import com.android.launcher3.model.data.ItemInfo;
+import com.android.launcher3.model.data.WorkspaceItemInfo;
 import com.android.launcher3.taskbar.TaskbarActivityContext;
 import com.android.launcher3.taskbar.TaskbarControllers;
+import com.android.launcher3.taskbar.TaskbarDragController;
 import com.android.launcher3.taskbar.TaskbarInsetsController;
 import com.android.launcher3.taskbar.TaskbarSharedState;
 import com.android.launcher3.taskbar.TaskbarStashController;
+import com.android.launcher3.taskbar.bubbles.BubbleBarLocationDropTarget.BubbleBarDragListener;
 import com.android.launcher3.taskbar.bubbles.animation.BubbleBarViewAnimator;
 import com.android.launcher3.taskbar.bubbles.flyout.BubbleBarFlyoutController;
 import com.android.launcher3.taskbar.bubbles.flyout.BubbleBarFlyoutPositioner;
@@ -59,6 +65,7 @@
 import com.android.quickstep.SystemUiProxy;
 import com.android.wm.shell.Flags;
 import com.android.wm.shell.shared.bubbles.BubbleBarLocation;
+import com.android.wm.shell.shared.bubbles.DeviceConfig;
 
 import java.io.PrintWriter;
 import java.util.List;
@@ -117,6 +124,61 @@
         updateTranslationY();
         setBubbleBarScaleAndPadding(pinningProgress);
     });
+    private final BubbleBarDragListener mDragListener = new BubbleBarDragListener() {
+
+        @NonNull
+        @Override
+        public void getBubbleBarLocationHitRect(@NonNull BubbleBarLocation bubbleBarLocation,
+                Rect outRect) {
+            Point screenSize = DisplayController.INSTANCE.get(mActivity).getInfo().currentSize;
+            outRect.top = screenSize.y - mBubbleBarDropTargetSize;
+            outRect.bottom = screenSize.y;
+            if (bubbleBarLocation.isOnLeft(mBarView.isLayoutRtl())) {
+                outRect.left = 0;
+                outRect.right = mBubbleBarDropTargetSize;
+            } else {
+                outRect.left = screenSize.x - mBubbleBarDropTargetSize;
+                outRect.right = screenSize.x;
+            }
+        }
+
+        @Override
+        public void onLauncherItemDroppedOverBubbleBarDragZone(@NonNull BubbleBarLocation location,
+                @NonNull ItemInfo itemInfo) {
+            //TODO(b/397459664) : fix drag interruption when there are no bubbles
+            //TODO(b/397459664) : update bubble bar location
+            ShortcutInfo shortcutInfo = null;
+            if (itemInfo instanceof WorkspaceItemInfo) {
+                shortcutInfo = ((WorkspaceItemInfo) itemInfo).getDeepShortcutInfo();
+            }
+            Intent itemIntent = itemInfo.getIntent();
+            SystemUiProxy systemUiProxy = SystemUiProxy.INSTANCE.get(mActivity);
+            if (shortcutInfo != null) {
+                systemUiProxy.showShortcutBubble(shortcutInfo);
+            } else if (itemIntent != null && itemIntent.getComponent() != null) {
+                systemUiProxy.showAppBubble(itemIntent, itemInfo.user);
+            }
+        }
+
+        @Override
+        public void onLauncherItemDraggedOutsideBubbleBarDropZone() {
+            //TODO(b/397459664) : hide expanded view drop target
+            onItemDraggedOutsideBubbleBarDropZone();
+        }
+
+        @Override
+        public void onLauncherItemDraggedOverBubbleBarDragZone(
+                @NonNull BubbleBarLocation location) {
+            //TODO(b/397459664) : show expanded view drop target
+            onDragItemOverBubbleBarDragZone(location);
+        }
+
+        @NonNull
+        @Override
+        public View getDropView() {
+            return mBarView;
+        }
+    };
 
     // Modified when swipe up is happening on the bubble bar or task bar.
     private float mBubbleBarSwipeUpTranslationY;
@@ -139,8 +201,12 @@
     private BubbleBarFlyoutController mBubbleBarFlyoutController;
     private BubbleBarPinController mBubbleBarPinController;
     private TaskbarSharedState mTaskbarSharedState;
+    private TaskbarDragController mTaskbarDragController;
+    private final BubbleBarLocationDropTarget mBubbleBarLeftDropTarget;
+    private final BubbleBarLocationDropTarget mBubbleBarRightDropTarget;
     private final TimeSource mTimeSource = System::currentTimeMillis;
     private final int mTaskbarTranslationDelta;
+    private final int mBubbleBarDropTargetSize;
 
     @Nullable
     private BubbleBarBoundsChangeListener mBoundsChangeListener;
@@ -158,11 +224,21 @@
                 R.dimen.bubblebar_transient_taskbar_min_distance);
         mDragElevation = res.getDimensionPixelSize(R.dimen.bubblebar_drag_elevation);
         mTaskbarTranslationDelta = getBubbleBarTranslationDeltaForTaskbar(activity);
+        if (DeviceConfig.isSmallTablet(mActivity)) {
+            mBubbleBarDropTargetSize = res.getDimensionPixelSize(R.dimen.drag_zone_bubble_fold);
+        } else {
+            mBubbleBarDropTargetSize = res.getDimensionPixelSize(R.dimen.drag_zone_bubble_tablet);
+        }
+        mBubbleBarLeftDropTarget = new BubbleBarLocationDropTarget(BubbleBarLocation.LEFT,
+                mDragListener);
+        mBubbleBarRightDropTarget = new BubbleBarLocationDropTarget(BubbleBarLocation.RIGHT,
+                mDragListener);
     }
 
     /** Initializes controller. */
     public void init(TaskbarControllers controllers, BubbleControllers bubbleControllers,
             TaskbarViewPropertiesProvider taskbarViewPropertiesProvider) {
+        mTaskbarDragController = controllers.taskbarDragController;
         mTaskbarSharedState = controllers.getSharedState();
         mBubbleStashController = bubbleControllers.bubbleStashController;
         mBubbleBarController = bubbleControllers.bubbleBarController;
@@ -264,6 +340,8 @@
                 mBubbleBarController.updateBubbleBarLocation(location, source);
             }
         };
+        mTaskbarDragController.addDropTarget(mBubbleBarLeftDropTarget);
+        mTaskbarDragController.addDropTarget(mBubbleBarRightDropTarget);
     }
 
     /** Returns animated float property responsible for pinning transition animation. */
@@ -542,7 +620,9 @@
      */
     public void onDragItemOverBubbleBarDragZone(@NonNull BubbleBarLocation bubbleBarLocation) {
         mBarView.showDropTarget(/* isDropTarget = */ true);
-        mIsLocationUpdatedForDropTarget = getBubbleBarLocation() != bubbleBarLocation;
+        boolean isRtl = mBarView.isLayoutRtl();
+        mIsLocationUpdatedForDropTarget = getBubbleBarLocation().isOnLeft(isRtl)
+                != bubbleBarLocation.isOnLeft(isRtl);
         if (mIsLocationUpdatedForDropTarget) {
             animateBubbleBarLocation(bubbleBarLocation);
         }
@@ -1278,6 +1358,8 @@
     /** Called when the controller is destroyed. */
     public void onDestroy() {
         adjustTaskbarAndHotseatToBubbleBarState(/*isBubbleBarExpanded = */false);
+        mTaskbarDragController.removeDropTarget(mBubbleBarLeftDropTarget);
+        mTaskbarDragController.removeDropTarget(mBubbleBarRightDropTarget);
     }
 
     /**
diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java
index 2d99510..7f0c7b5 100644
--- a/src/com/android/launcher3/DropTarget.java
+++ b/src/com/android/launcher3/DropTarget.java
@@ -18,6 +18,7 @@
 
 import android.content.Context;
 import android.graphics.Rect;
+import android.view.View;
 
 import com.android.launcher3.accessibility.DragViewStateAnnouncer;
 import com.android.launcher3.dragndrop.DragOptions;
@@ -145,4 +146,9 @@
 
     // These methods are implemented in Views
     void getHitRectRelativeToDragLayer(Rect outRect);
+
+    /** Returns the drop target view. By default, the implementor class is cast to the view. */
+    default View getDropView() {
+        return (View) this;
+    }
 }
diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java
index c50c008..613b430 100644
--- a/src/com/android/launcher3/dragndrop/DragController.java
+++ b/src/com/android/launcher3/dragndrop/DragController.java
@@ -558,7 +558,7 @@
 
             target.getHitRectRelativeToDragLayer(r);
             if (r.contains(x, y)) {
-                mActivity.getDragLayer().mapCoordInSelfToDescendant((View) target,
+                mActivity.getDragLayer().mapCoordInSelfToDescendant(target.getDropView(),
                         mCoordinatesTemp);
                 mDragObject.x = mCoordinatesTemp[0];
                 mDragObject.y = mCoordinatesTemp[1];