Move mDragState from WindowManagerService to DragDropController

Bug: 65564090
Test: android.server.wm.CrossAppDragAndDropTests, manually check the drag
      and drop behavior on test app.
Change-Id: I2445ccff6e2cfd673c47f591ac88f3f60a7a6ddc
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index cd20421..a3c6167 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -16,8 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.graphics.PixelFormat.TRANSLUCENT;
-import static android.view.SurfaceControl.HIDDEN;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
@@ -26,14 +24,12 @@
 import android.content.ClipData;
 import android.graphics.PixelFormat;
 import android.os.Binder;
-import android.os.Handler;
 import android.os.IBinder;
 import android.os.Message;
 import android.util.Slog;
 import android.view.Display;
 import android.view.IWindow;
 import android.view.Surface;
-import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
@@ -45,6 +41,11 @@
 class DragDropController {
     private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
     private static final long DRAG_TIMEOUT_MS = 5000;
+    DragState mDragState;
+
+    boolean dragDropActiveLocked() {
+        return mDragState != null;
+    }
 
     IBinder prepareDrag(WindowManagerService service, SurfaceSession session, int callerPid,
             int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) {
@@ -57,52 +58,42 @@
         IBinder token = null;
 
         synchronized (service.mWindowMap) {
-            try {
-                if (service.mDragState == null) {
-                    // TODO(multi-display): support other displays
-                    final DisplayContent displayContent =
-                            service.getDefaultDisplayContentLocked();
-                    final Display display = displayContent.getDisplay();
-
-                    final SurfaceControl surface = new SurfaceControl.Builder(session)
-                            .setName("drag surface")
-                            .setSize(width, height)
-                            .setFormat(PixelFormat.TRANSLUCENT)
-                            .build();
-                    surface.setLayerStack(display.getLayerStack());
-                    float alpha = 1;
-                    if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
-                        alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
-                    }
-                    surface.setAlpha(alpha);
-
-                    if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG "
-                            + surface + ": CREATE");
-                    outSurface.copyFrom(surface);
-                    final IBinder winBinder = window.asBinder();
-                    token = new Binder();
-                    service.mDragState =
-                            new DragState(service, token, surface, flags, winBinder);
-                    service.mDragState.mPid = callerPid;
-                    service.mDragState.mUid = callerUid;
-                    service.mDragState.mOriginalAlpha = alpha;
-                    token = service.mDragState.mToken = new Binder();
-
-                    // 5 second timeout for this window to actually begin the drag
-                    service.mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
-                    Message msg = service.mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
-                    service.mH.sendMessageDelayed(msg, DRAG_TIMEOUT_MS);
-                } else {
-                    Slog.w(TAG_WM, "Drag already in progress");
-                }
-            } catch (OutOfResourcesException e) {
-                Slog.e(TAG_WM, "Can't allocate drag surface w=" + width + " h=" + height,
-                        e);
-                if (service.mDragState != null) {
-                    service.mDragState.reset();
-                    service.mDragState = null;
-                }
+            if (dragDropActiveLocked()) {
+                Slog.w(TAG_WM, "Drag already in progress");
+                return null;
             }
+
+            // TODO(multi-display): support other displays
+            final DisplayContent displayContent =
+                    service.getDefaultDisplayContentLocked();
+            final Display display = displayContent.getDisplay();
+
+            final SurfaceControl surface = new SurfaceControl.Builder(session)
+                    .setName("drag surface")
+                    .setSize(width, height)
+                    .setFormat(PixelFormat.TRANSLUCENT)
+                    .build();
+            surface.setLayerStack(display.getLayerStack());
+            float alpha = 1;
+            if ((flags & View.DRAG_FLAG_OPAQUE) == 0) {
+                alpha = DRAG_SHADOW_ALPHA_TRANSPARENT;
+            }
+            surface.setAlpha(alpha);
+
+            if (SHOW_TRANSACTIONS) Slog.i(TAG_WM, "  DRAG " + surface + ": CREATE");
+            outSurface.copyFrom(surface);
+            final IBinder winBinder = window.asBinder();
+            token = new Binder();
+            mDragState = new DragState(service, token, surface, flags, winBinder);
+            mDragState.mPid = callerPid;
+            mDragState.mUid = callerUid;
+            mDragState.mOriginalAlpha = alpha;
+            token = mDragState.mToken = new Binder();
+
+            // 5 second timeout for this window to actually begin the drag
+            service.mH.removeMessages(H.DRAG_START_TIMEOUT, winBinder);
+            Message msg = service.mH.obtainMessage(H.DRAG_START_TIMEOUT, winBinder);
+            service.mH.sendMessageDelayed(msg, DRAG_TIMEOUT_MS);
         }
 
         return token;
@@ -116,12 +107,12 @@
         }
 
         synchronized (service.mWindowMap) {
-            if (service.mDragState == null) {
+            if (mDragState == null) {
                 Slog.w(TAG_WM, "No drag prepared");
                 throw new IllegalStateException("performDrag() without prepareDrag()");
             }
 
-            if (dragToken != service.mDragState.mToken) {
+            if (dragToken != mDragState.mToken) {
                 Slog.w(TAG_WM, "Performing mismatched drag");
                 throw new IllegalStateException("performDrag() does not match prepareDrag()");
             }
@@ -149,34 +140,34 @@
                 return false;
             }
             Display display = displayContent.getDisplay();
-            service.mDragState.register(display);
+            mDragState.register(display);
             if (!service.mInputManager.transferTouchFocus(callingWin.mInputChannel,
-                    service.mDragState.getInputChannel())) {
+                    mDragState.getInputChannel())) {
                 Slog.e(TAG_WM, "Unable to transfer touch focus");
-                service.mDragState.unregister();
-                service.mDragState.reset();
-                service.mDragState = null;
+                mDragState.unregister();
+                mDragState.reset();
+                mDragState = null;
                 return false;
             }
 
-            service.mDragState.mDisplayContent = displayContent;
-            service.mDragState.mData = data;
-            service.mDragState.broadcastDragStartedLw(touchX, touchY);
-            service.mDragState.overridePointerIconLw(touchSource);
+            mDragState.mDisplayContent = displayContent;
+            mDragState.mData = data;
+            mDragState.broadcastDragStartedLw(touchX, touchY);
+            mDragState.overridePointerIconLw(touchSource);
 
             // remember the thumb offsets for later
-            service.mDragState.mThumbOffsetX = thumbCenterX;
-            service.mDragState.mThumbOffsetY = thumbCenterY;
+            mDragState.mThumbOffsetX = thumbCenterX;
+            mDragState.mThumbOffsetY = thumbCenterY;
 
             // Make the surface visible at the proper location
-            final SurfaceControl surfaceControl = service.mDragState.mSurfaceControl;
+            final SurfaceControl surfaceControl = mDragState.mSurfaceControl;
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
                     TAG_WM, ">>> OPEN TRANSACTION performDrag");
             service.openSurfaceTransaction();
             try {
                 surfaceControl.setPosition(touchX - thumbCenterX,
                         touchY - thumbCenterY);
-                surfaceControl.setLayer(service.mDragState.getDragLayerLw());
+                surfaceControl.setLayer(mDragState.getDragLayerLw());
                 surfaceControl.setLayerStack(display.getLayerStack());
                 surfaceControl.show();
             } finally {
@@ -185,7 +176,7 @@
                         TAG_WM, "<<< CLOSE TRANSACTION performDrag");
             }
 
-            service.mDragState.notifyLocationLw(touchX, touchY);
+            mDragState.notifyLocationLw(touchX, touchY);
         }
 
         return true;    // success!
@@ -198,14 +189,14 @@
         }
 
         synchronized (service.mWindowMap) {
-            if (service.mDragState == null) {
+            if (mDragState == null) {
                 // Most likely the drop recipient ANRed and we ended the drag
                 // out from under it.  Log the issue and move on.
                 Slog.w(TAG_WM, "Drop result given but no drag in progress");
                 return;
             }
 
-            if (service.mDragState.mToken != token) {
+            if (mDragState.mToken != token) {
                 // We're in a drag, but the wrong window has responded.
                 Slog.w(TAG_WM, "Invalid drop-result claim by " + window);
                 throw new IllegalStateException("reportDropResult() by non-recipient");
@@ -221,8 +212,8 @@
                 return;  // !!! TODO: throw here?
             }
 
-            service.mDragState.mDragResult = consumed;
-            service.mDragState.endDragLw();
+            mDragState.mDragResult = consumed;
+            mDragState.endDragLw();
         }
     }
 
@@ -232,20 +223,20 @@
         }
 
         synchronized (service.mWindowMap) {
-            if (service.mDragState == null) {
+            if (mDragState == null) {
                 Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");
                 throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()");
             }
 
-            if (service.mDragState.mToken != dragToken) {
+            if (mDragState.mToken != dragToken) {
                 Slog.w(TAG_WM,
                         "cancelDragAndDrop() does not match prepareDrag()");
                 throw new IllegalStateException(
                         "cancelDragAndDrop() does not match prepareDrag()");
             }
 
-            service.mDragState.mDragResult = false;
-            service.mDragState.cancelDragLw();
+            mDragState.mDragResult = false;
+            mDragState.cancelDragLw();
         }
     }
 
@@ -270,10 +261,10 @@
                 }
                 synchronized (service.mWindowMap) {
                     // !!! TODO: ANR the app that has failed to start the drag in time
-                    if (service.mDragState != null) {
-                        service.mDragState.unregister();
-                        service.mDragState.reset();
-                        service.mDragState = null;
+                    if (mDragState != null) {
+                        mDragState.unregister();
+                        mDragState.reset();
+                        mDragState = null;
                     }
                 }
                 break;
@@ -286,9 +277,9 @@
                 }
                 synchronized (service.mWindowMap) {
                     // !!! TODO: ANR the drag-receiving app
-                    if (service.mDragState != null) {
-                        service.mDragState.mDragResult = false;
-                        service.mDragState.endDragLw();
+                    if (mDragState != null) {
+                        mDragState.mDragResult = false;
+                        mDragState.endDragLw();
                     }
                 }
                 break;
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 4a75e01..11f2241 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -430,7 +430,7 @@
             //    WindowManagerService, which will cause DragState#reset() while playing the
             //    cancel animation.
             reset();
-            mService.mDragState = null;
+            mService.mDragDropController.mDragState = null;
             return;
         }
         mAnimator = createCancelAnimationLocked();
@@ -447,7 +447,7 @@
 
         // free our resources and drop all the object references
         reset();
-        mService.mDragState = null;
+        mService.mDragDropController.mDragState = null;
     }
 
     void notifyMoveLw(float x, float y) {
@@ -658,7 +658,7 @@
             switch (msg.what) {
                 case MSG_ANIMATION_END:
                     synchronized (mService.mWindowMap) {
-                        if (mService.mDragState != DragState.this) {
+                        if (mService.mDragDropController.mDragState != DragState.this) {
                             Slog.wtf(TAG_WM, "mDragState is updated unexpectedly while " +
                                     "playing animation");
                             return;
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 238cb9f..cf1f171 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -367,12 +367,13 @@
         // currently has touch focus.
 
         // If there's a drag in flight, provide a pseudo-window to catch drag input
-        final boolean inDrag = (mService.mDragState != null);
+        final boolean inDrag = mService.mDragDropController.dragDropActiveLocked();
         if (inDrag) {
             if (DEBUG_DRAG) {
                 Log.d(TAG_WM, "Inserting drag window");
             }
-            final InputWindowHandle dragWindowHandle = mService.mDragState.getInputWindowHandle();
+            final InputWindowHandle dragWindowHandle =
+                    mService.mDragDropController.mDragState.getInputWindowHandle();
             if (dragWindowHandle != null) {
                 addInputWindowHandle(dragWindowHandle);
             } else {
@@ -689,7 +690,7 @@
             // If there's a drag in progress and 'child' is a potential drop target,
             // make sure it's been told about the drag
             if (inDrag && isVisible && w.getDisplayContent().isDefaultDisplay) {
-                mService.mDragState.sendDragStartedIfNeededLw(w);
+                mService.mDragDropController.mDragState.sendDragStartedIfNeededLw(w);
             }
 
             addInputWindowHandle(
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 492d6a7..f31ea67 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -752,7 +752,6 @@
 
     TaskPositioner mTaskPositioner;
     final DragDropController mDragDropController = new DragDropController();
-    DragState mDragState = null;
 
     // For frozen screen animations.
     private int mExitAnimId, mEnterAnimId;
@@ -789,7 +788,7 @@
         public void onInputEvent(InputEvent event, int displayId) {
             boolean handled = false;
             try {
-                if (mDragState == null) {
+                if (mDragDropController.mDragState == null) {
                     // The drag has ended but the clean-up message has not been processed by
                     // window manager. Drop events that occur after this until window manager
                     // has a chance to clean-up the input handle.
@@ -828,12 +827,12 @@
                                     + newX + "," + newY);
                             mMuteInput = true;
                             synchronized (mWindowMap) {
-                                endDrag = mDragState.notifyDropLw(newX, newY);
+                                endDrag = mDragDropController.mDragState.notifyDropLw(newX, newY);
                             }
                         } else {
                             synchronized (mWindowMap) {
                                 // move the surface and tell the involved window(s) where we are
-                                mDragState.notifyMoveLw(newX, newY);
+                                mDragDropController.mDragState.notifyMoveLw(newX, newY);
                             }
                         }
                     } break;
@@ -843,7 +842,7 @@
                                 + newX + "," + newY);
                         mMuteInput = true;
                         synchronized (mWindowMap) {
-                            endDrag = mDragState.notifyDropLw(newX, newY);
+                            endDrag = mDragDropController.mDragState.notifyDropLw(newX, newY);
                         }
                     } break;
 
@@ -860,7 +859,7 @@
                         synchronized (mWindowMap) {
                             // endDragLw will post back to looper to dispose the receiver
                             // since we still need the receiver for the last finishInputEvent.
-                            mDragState.endDragLw();
+                            mDragDropController.mDragState.endDragLw();
                         }
                         mStylusButtonDownAtStart = false;
                         mIsStartEvent = true;
@@ -7171,7 +7170,7 @@
         }
 
         synchronized (mWindowMap) {
-            if (mDragState != null) {
+            if (mDragDropController.mDragState != null) {
                 // Drag cursor overrides the app cursor.
                 return;
             }