Add a flag to cancelDragAndDrop to skip animation

When running cancel animation for drag shadow image, the system cannot
start another drag operation, which is problematic when the system would
start the other drag operation quickly.

Bug: 130313958
Test: Cancel drag operation by calling cancelDragAndDrop
Change-Id: I5d6650a0ce9a4cd80bbdb1beabc9e514349ccadc
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index d317df0..b52fdb8 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -187,8 +187,10 @@
 
     /**
      * Cancel the current drag operation.
+     * skipAnimation is 'true' when it should skip the drag cancel animation which brings the drag
+     * shadow image back to the drag start position.
      */
-    void cancelDragAndDrop(IBinder dragToken);
+    void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation);
 
     /**
      * Tell the OS that we've just dragged into a View that is willing to accept the drop
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 10f9d38..5929c1b 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -25456,7 +25456,7 @@
         }
         if (mAttachInfo.mDragToken != null) {
             try {
-                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
+                mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken, false);
             } catch (Exception e) {
                 Log.e(VIEW_LOG_TAG, "Unable to cancel drag", e);
             }
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 716e4ef..f8f6334 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -236,7 +236,7 @@
         }
     }
 
-    void cancelDragAndDrop(IBinder dragToken) {
+    void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation) {
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "cancelDragAndDrop");
         }
@@ -257,7 +257,7 @@
                 }
 
                 mDragState.mDragResult = false;
-                mDragState.cancelDragLocked();
+                mDragState.cancelDragLocked(skipAnimation);
             }
         } finally {
             mCallback.get().postCancelDragAndDrop();
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index c438966..6127303 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -475,15 +475,16 @@
         closeLocked();
     }
 
-    void cancelDragLocked() {
+    void cancelDragLocked(boolean skipAnimation) {
         if (mAnimator != null) {
             return;
         }
-        if (!mDragInProgress) {
-            // This can happen if an app invokes Session#cancelDragAndDrop before
+        if (!mDragInProgress || skipAnimation) {
+            // mDragInProgress is false if an app invokes Session#cancelDragAndDrop before
             // Session#performDrag. Reset the drag state without playing the cancel animation
             // because H.DRAG_START_TIMEOUT may be sent to WindowManagerService, which will cause
             // DragState#reset() while playing the cancel animation.
+            // skipAnimation is true when a caller requests to skip the drag cancel animation.
             closeLocked();
             return;
         }
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 22b030d..b33f8c7 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -283,10 +283,10 @@
     }
 
     @Override
-    public void cancelDragAndDrop(IBinder dragToken) {
+    public void cancelDragAndDrop(IBinder dragToken, boolean skipAnimation) {
         final long ident = Binder.clearCallingIdentity();
         try {
-            mDragDropController.cancelDragAndDrop(dragToken);
+            mDragDropController.cancelDragAndDrop(dragToken, skipAnimation);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
diff --git a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
index 68d8bc0..196cc21 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DragDropControllerTests.java
@@ -137,7 +137,7 @@
                 return;
             }
             if (mToken != null) {
-                mTarget.cancelDragAndDrop(mToken);
+                mTarget.cancelDragAndDrop(mToken, false);
             }
             latch = new CountDownLatch(1);
             mTarget.setOnClosedCallbackLocked(latch::countDown);