Add callback to DragDropController.

The callback allows vendor code to hook drag and drop operations.

Bug: 63914027
Test: Manually drag and drop files between apps, CTS
      CrossAppDragAndDropTests
Change-Id: I33bf907b7c024a485c51bd87d7c4839718ebeb13
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index 76e25ba..4567e10 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -21,6 +21,7 @@
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
 
+import android.annotation.NonNull;
 import android.content.ClipData;
 import android.graphics.PixelFormat;
 import android.os.Binder;
@@ -35,6 +36,8 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
+import android.view.WindowManagerInternal.IDragDropCallback;
+import com.android.internal.util.Preconditions;
 import com.android.server.input.InputWindowHandle;
 
 /**
@@ -61,6 +64,7 @@
 
     private WindowManagerService mService;
     private final Handler mHandler;
+
     /**
      * Lock to preserve the order of state updates.
      * The lock is used to process drag and drop state updates in order without having the window
@@ -94,6 +98,11 @@
      */
     private final Object mWriteLock = new Object();
 
+    /**
+     * Callback which is used to sync drag state with the vendor-specific code.
+     */
+    @NonNull private IDragDropCallback mCallback = new IDragDropCallback() {};
+
     boolean dragDropActiveLocked() {
         return mDragState != null;
     }
@@ -102,6 +111,13 @@
         return mDragState.getInputWindowHandle();
     }
 
+    void registerCallback(IDragDropCallback callback) {
+        Preconditions.checkNotNull(callback);
+        synchronized (mWriteLock) {
+            mCallback = callback;
+        }
+    }
+
     DragDropController(WindowManagerService service, Looper looper) {
         mService = service;
         mHandler = new DragHandler(service, looper);
@@ -169,6 +185,10 @@
         }
 
         synchronized (mWriteLock) {
+            if (!mCallback.performDrag(window, dragToken, touchSource, touchX, touchY, thumbCenterX,
+                    thumbCenterY, data)) {
+                return false;
+            }
             synchronized (mService.mWindowMap) {
                 if (mDragState == null) {
                     Slog.w(TAG_WM, "No drag prepared");
@@ -251,6 +271,7 @@
         }
 
         synchronized (mWriteLock) {
+            mCallback.reportDropResult(window, consumed);
             synchronized (mService.mWindowMap) {
                 if (mDragState == null) {
                     // Most likely the drop recipient ANRed and we ended the drag
@@ -288,6 +309,7 @@
         }
 
         synchronized (mWriteLock) {
+            mCallback.cancelDragAndDrop(dragToken);
             synchronized (mService.mWindowMap) {
                 if (mDragState == null) {
                     Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");