Move drag related handler code to DragHandler

The CL creates new Handler in DragDropController and moved drag related
message from WindowManagerService#H and DragState#DragStateHandler.

Bug: 65564090
Test: android.server.wm.CrossAppDragAndDropTests, manually check the
      drag and drop behavior on test app.
Change-Id: Ifd0312853734468ef9ff8cf6490164a6fd8806fa
diff --git a/services/core/java/com/android/server/wm/DragDropController.java b/services/core/java/com/android/server/wm/DragDropController.java
index a3c6167..860ff38 100644
--- a/services/core/java/com/android/server/wm/DragDropController.java
+++ b/services/core/java/com/android/server/wm/DragDropController.java
@@ -24,7 +24,9 @@
 import android.content.ClipData;
 import android.graphics.PixelFormat;
 import android.os.Binder;
+import android.os.Handler;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.util.Slog;
 import android.view.Display;
@@ -33,7 +35,6 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
-import com.android.server.wm.WindowManagerService.H;
 
 /**
  * Managing drag and drop operations initiated by View#startDragAndDrop.
@@ -41,13 +42,28 @@
 class DragDropController {
     private static final float DRAG_SHADOW_ALPHA_TRANSPARENT = .7071f;
     private static final long DRAG_TIMEOUT_MS = 5000;
+
+    // Messages for Handler.
+    private static final int MSG_DRAG_START_TIMEOUT = 0;
+    static final int MSG_DRAG_END_TIMEOUT = 1;
+    static final int MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT = 2;
+    static final int MSG_ANIMATION_END = 3;
+
     DragState mDragState;
 
+    private WindowManagerService mService;
+    private final Handler mHandler;
+
     boolean dragDropActiveLocked() {
         return mDragState != null;
     }
 
-    IBinder prepareDrag(WindowManagerService service, SurfaceSession session, int callerPid,
+    DragDropController(WindowManagerService service, Looper looper) {
+        mService = service;
+        mHandler = new DragHandler(service, looper);
+    }
+
+    IBinder prepareDrag(SurfaceSession session, int callerPid,
             int callerUid, IWindow window, int flags, int width, int height, Surface outSurface) {
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "prepare drag surface: w=" + width + " h=" + height
@@ -57,7 +73,7 @@
 
         IBinder token = null;
 
-        synchronized (service.mWindowMap) {
+        synchronized (mService.mWindowMap) {
             if (dragDropActiveLocked()) {
                 Slog.w(TAG_WM, "Drag already in progress");
                 return null;
@@ -65,7 +81,7 @@
 
             // TODO(multi-display): support other displays
             final DisplayContent displayContent =
-                    service.getDefaultDisplayContentLocked();
+                    mService.getDefaultDisplayContentLocked();
             final Display display = displayContent.getDisplay();
 
             final SurfaceControl surface = new SurfaceControl.Builder(session)
@@ -84,29 +100,27 @@
             outSurface.copyFrom(surface);
             final IBinder winBinder = window.asBinder();
             token = new Binder();
-            mDragState = new DragState(service, token, surface, flags, winBinder);
+            mDragState = new DragState(mService, 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);
+            sendTimeoutMessage(MSG_DRAG_START_TIMEOUT, winBinder);
         }
 
         return token;
     }
 
-    boolean performDrag(WindowManagerService service, IWindow window, IBinder dragToken,
+    boolean performDrag(IWindow window, IBinder dragToken,
             int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
             ClipData data) {
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "perform drag: win=" + window + " data=" + data);
         }
 
-        synchronized (service.mWindowMap) {
+        synchronized (mService.mWindowMap) {
             if (mDragState == null) {
                 Slog.w(TAG_WM, "No drag prepared");
                 throw new IllegalStateException("performDrag() without prepareDrag()");
@@ -117,7 +131,7 @@
                 throw new IllegalStateException("performDrag() does not match prepareDrag()");
             }
 
-            final WindowState callingWin = service.windowForClientLocked(null, window, false);
+            final WindowState callingWin = mService.windowForClientLocked(null, window, false);
             if (callingWin == null) {
                 Slog.w(TAG_WM, "Bad requesting window " + window);
                 return false;  // !!! TODO: throw here?
@@ -127,12 +141,12 @@
             // the drag initiation (e.g. an alarm window popped up just as the application
             // called performDrag()
 
-            service.mH.removeMessages(H.DRAG_START_TIMEOUT, window.asBinder());
+            mHandler.removeMessages(MSG_DRAG_START_TIMEOUT, window.asBinder());
 
             // !!! TODO: extract the current touch (x, y) in screen coordinates.  That
             // will let us eliminate the (touchX,touchY) parameters from the API.
 
-            // !!! FIXME: put all this heavy stuff onto the mH looper, as well as
+            // !!! FIXME: put all this heavy stuff onto the mHandler looper, as well as
             // the actual drag event dispatch stuff in the dragstate
 
             final DisplayContent displayContent = callingWin.getDisplayContent();
@@ -141,7 +155,7 @@
             }
             Display display = displayContent.getDisplay();
             mDragState.register(display);
-            if (!service.mInputManager.transferTouchFocus(callingWin.mInputChannel,
+            if (!mService.mInputManager.transferTouchFocus(callingWin.mInputChannel,
                     mDragState.getInputChannel())) {
                 Slog.e(TAG_WM, "Unable to transfer touch focus");
                 mDragState.unregister();
@@ -152,8 +166,8 @@
 
             mDragState.mDisplayContent = displayContent;
             mDragState.mData = data;
-            mDragState.broadcastDragStartedLw(touchX, touchY);
-            mDragState.overridePointerIconLw(touchSource);
+            mDragState.broadcastDragStartedLocked(touchX, touchY);
+            mDragState.overridePointerIconLocked(touchSource);
 
             // remember the thumb offsets for later
             mDragState.mThumbOffsetX = thumbCenterX;
@@ -163,32 +177,32 @@
             final SurfaceControl surfaceControl = mDragState.mSurfaceControl;
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
                     TAG_WM, ">>> OPEN TRANSACTION performDrag");
-            service.openSurfaceTransaction();
+            mService.openSurfaceTransaction();
             try {
                 surfaceControl.setPosition(touchX - thumbCenterX,
                         touchY - thumbCenterY);
-                surfaceControl.setLayer(mDragState.getDragLayerLw());
+                surfaceControl.setLayer(mDragState.getDragLayerLocked());
                 surfaceControl.setLayerStack(display.getLayerStack());
                 surfaceControl.show();
             } finally {
-                service.closeSurfaceTransaction();
+                mService.closeSurfaceTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
                         TAG_WM, "<<< CLOSE TRANSACTION performDrag");
             }
 
-            mDragState.notifyLocationLw(touchX, touchY);
+            mDragState.notifyLocationLocked(touchX, touchY);
         }
 
         return true;    // success!
     }
 
-    void reportDropResult(WindowManagerService service, IWindow window, boolean consumed) {
+    void reportDropResult(IWindow window, boolean consumed) {
         IBinder token = window.asBinder();
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "Drop result=" + consumed + " reported by " + token);
         }
 
-        synchronized (service.mWindowMap) {
+        synchronized (mService.mWindowMap) {
             if (mDragState == null) {
                 // Most likely the drop recipient ANRed and we ended the drag
                 // out from under it.  Log the issue and move on.
@@ -205,24 +219,24 @@
             // The right window has responded, even if it's no longer around,
             // so be sure to halt the timeout even if the later WindowState
             // lookup fails.
-            service.mH.removeMessages(H.DRAG_END_TIMEOUT, window.asBinder());
-            WindowState callingWin = service.windowForClientLocked(null, window, false);
+            mHandler.removeMessages(MSG_DRAG_END_TIMEOUT, window.asBinder());
+            WindowState callingWin = mService.windowForClientLocked(null, window, false);
             if (callingWin == null) {
                 Slog.w(TAG_WM, "Bad result-reporting window " + window);
                 return;  // !!! TODO: throw here?
             }
 
             mDragState.mDragResult = consumed;
-            mDragState.endDragLw();
+            mDragState.endDragLocked();
         }
     }
 
-    void cancelDragAndDrop(WindowManagerService service, IBinder dragToken) {
+    void cancelDragAndDrop(IBinder dragToken) {
         if (DEBUG_DRAG) {
             Slog.d(TAG_WM, "cancelDragAndDrop");
         }
 
-        synchronized (service.mWindowMap) {
+        synchronized (mService.mWindowMap) {
             if (mDragState == null) {
                 Slog.w(TAG_WM, "cancelDragAndDrop() without prepareDrag()");
                 throw new IllegalStateException("cancelDragAndDrop() without prepareDrag()");
@@ -236,7 +250,7 @@
             }
 
             mDragState.mDragResult = false;
-            mDragState.cancelDragLw();
+            mDragState.cancelDragLocked();
         }
     }
 
@@ -252,49 +266,90 @@
         }
     }
 
-    void handleMessage(WindowManagerService service, Message msg) {
-        switch (msg.what) {
-            case H.DRAG_START_TIMEOUT: {
-                IBinder win = (IBinder) msg.obj;
-                if (DEBUG_DRAG) {
-                    Slog.w(TAG_WM, "Timeout starting drag by win " + win);
-                }
-                synchronized (service.mWindowMap) {
-                    // !!! TODO: ANR the app that has failed to start the drag in time
-                    if (mDragState != null) {
-                        mDragState.unregister();
-                        mDragState.reset();
-                        mDragState = null;
-                    }
-                }
-                break;
-            }
+    /**
+     * Sends a message to the Handler managed by DragDropController.
+     */
+    void sendHandlerMessage(int what, Object arg) {
+        mHandler.obtainMessage(what, arg).sendToTarget();
+    }
 
-            case H.DRAG_END_TIMEOUT: {
-                IBinder win = (IBinder) msg.obj;
-                if (DEBUG_DRAG) {
-                    Slog.w(TAG_WM, "Timeout ending drag to win " + win);
-                }
-                synchronized (service.mWindowMap) {
-                    // !!! TODO: ANR the drag-receiving app
-                    if (mDragState != null) {
-                        mDragState.mDragResult = false;
-                        mDragState.endDragLw();
-                    }
-                }
-                break;
-            }
+    /**
+     * Sends a timeout message to the Handler managed by DragDropController.
+     */
+    void sendTimeoutMessage(int what, Object arg) {
+        mHandler.removeMessages(what, arg);
+        final Message msg = mHandler.obtainMessage(what, arg);
+        mHandler.sendMessageDelayed(msg, DRAG_TIMEOUT_MS);
+    }
 
-            case H.TEAR_DOWN_DRAG_AND_DROP_INPUT: {
-                if (DEBUG_DRAG)
-                    Slog.d(TAG_WM, "Drag ending; tearing down input channel");
-                DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
-                if (interceptor != null) {
-                    synchronized (service.mWindowMap) {
-                        interceptor.tearDown();
+    private class DragHandler extends Handler {
+        /**
+         * Lock for window manager.
+         */
+        private final WindowManagerService mService;
+
+        DragHandler(WindowManagerService service, Looper looper) {
+            super(looper);
+            mService = service;
+        }
+
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case MSG_DRAG_START_TIMEOUT: {
+                    IBinder win = (IBinder) msg.obj;
+                    if (DEBUG_DRAG) {
+                        Slog.w(TAG_WM, "Timeout starting drag by win " + win);
                     }
+                    synchronized (mService.mWindowMap) {
+                        // !!! TODO: ANR the app that has failed to start the drag in time
+                        if (mDragState != null) {
+                            mDragState.unregister();
+                            mDragState.reset();
+                            mDragState = null;
+                        }
+                    }
+                    break;
                 }
-                break;
+
+                case MSG_DRAG_END_TIMEOUT: {
+                    IBinder win = (IBinder) msg.obj;
+                    if (DEBUG_DRAG) {
+                        Slog.w(TAG_WM, "Timeout ending drag to win " + win);
+                    }
+                    synchronized (mService.mWindowMap) {
+                        // !!! TODO: ANR the drag-receiving app
+                        if (mDragState != null) {
+                            mDragState.mDragResult = false;
+                            mDragState.endDragLocked();
+                        }
+                    }
+                    break;
+                }
+
+                case MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT: {
+                    if (DEBUG_DRAG)
+                        Slog.d(TAG_WM, "Drag ending; tearing down input channel");
+                    DragState.InputInterceptor interceptor = (DragState.InputInterceptor) msg.obj;
+                    if (interceptor != null) {
+                        synchronized (mService.mWindowMap) {
+                            interceptor.tearDown();
+                        }
+                    }
+                    break;
+                }
+
+                case MSG_ANIMATION_END: {
+                    synchronized (mService.mWindowMap) {
+                        if (mDragState == null) {
+                            Slog.wtf(TAG_WM, "mDragState unexpectedly became null while " +
+                                    "plyaing animation");
+                            return;
+                        }
+                        mDragState.onAnimationEndLocked();
+                    }
+                    break;
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index 11f2241..ba956bd 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -16,6 +16,9 @@
 
 package com.android.server.wm;
 
+import static com.android.server.wm.DragDropController.MSG_ANIMATION_END;
+import static com.android.server.wm.DragDropController.MSG_DRAG_END_TIMEOUT;
+import static com.android.server.wm.DragDropController.MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
 import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
@@ -29,14 +32,10 @@
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.Context;
-import android.graphics.Matrix;
 import android.graphics.Point;
 import android.hardware.input.InputManager;
 import android.os.Build;
-import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
-import android.os.Message;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -50,19 +49,15 @@
 import android.view.InputDevice;
 import android.view.PointerIcon;
 import android.view.SurfaceControl;
-import android.view.SurfaceControl.Transaction;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
-import android.view.animation.Transformation;
 
+import com.android.internal.view.IDragAndDropPermissions;
 import com.android.server.input.InputApplicationHandle;
 import com.android.server.input.InputWindowHandle;
 import com.android.server.wm.WindowManagerService.DragInputEventReceiver;
-import com.android.server.wm.WindowManagerService.H;
-
-import com.android.internal.view.IDragAndDropPermissions;
 
 import java.util.ArrayList;
 
@@ -86,10 +81,8 @@
     private static final String ANIMATED_PROPERTY_ALPHA = "alpha";
     private static final String ANIMATED_PROPERTY_SCALE = "scale";
 
-    // Messages for Handler.
-    private static final int MSG_ANIMATION_END = 0;
-
     final WindowManagerService mService;
+    final DragDropController mDragDropController;
     IBinder mToken;
     /**
      * Do not use the variable from the out of animation thread while mAnimator is not null.
@@ -118,17 +111,16 @@
     @Nullable private ValueAnimator mAnimator;
     private final Interpolator mCubicEaseOutInterpolator = new DecelerateInterpolator(1.5f);
     private Point mDisplaySize = new Point();
-    private final Handler mHandler;
 
     DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
             int flags, IBinder localWin) {
         mService = service;
+        mDragDropController = service.mDragDropController;
         mToken = token;
         mSurfaceControl = surface;
         mFlags = flags;
         mLocalWin = localWin;
         mNotifiedWindows = new ArrayList<WindowState>();
-        mHandler = new DragStateHandler(service.mH.getLooper());
     }
 
     void reset() {
@@ -171,7 +163,7 @@
                     display.getDisplayId());
             mDragWindowHandle.name = "drag";
             mDragWindowHandle.inputChannel = mServerChannel;
-            mDragWindowHandle.layer = getDragLayerLw();
+            mDragWindowHandle.layer = getDragLayerLocked();
             mDragWindowHandle.layoutParamsFlags = 0;
             mDragWindowHandle.layoutParamsType = WindowManager.LayoutParams.TYPE_DRAG;
             mDragWindowHandle.dispatchingTimeoutNanos =
@@ -250,14 +242,14 @@
             Slog.e(TAG_WM, "Unregister of nonexistent drag input channel");
         } else {
             // Input channel should be disposed on the thread where the input is being handled.
-            mService.mH.obtainMessage(
-                    H.TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor).sendToTarget();
+            mDragDropController.sendHandlerMessage(
+                    MSG_TEAR_DOWN_DRAG_AND_DROP_INPUT, mInputInterceptor);
             mInputInterceptor = null;
             mService.mInputMonitor.updateInputWindowsLw(true /*force*/);
         }
     }
 
-    int getDragLayerLw() {
+    int getDragLayerLocked() {
         return mService.mPolicy.getWindowLayerFromTypeLw(WindowManager.LayoutParams.TYPE_DRAG)
                 * WindowManagerService.TYPE_LAYER_MULTIPLIER
                 + WindowManagerService.TYPE_LAYER_OFFSET;
@@ -265,7 +257,7 @@
 
     /* call out to each visible window/session informing it about the drag
      */
-    void broadcastDragStartedLw(final float touchX, final float touchY) {
+    void broadcastDragStartedLocked(final float touchX, final float touchY) {
         mOriginalX = mCurrentX = touchX;
         mOriginalY = mCurrentY = touchY;
 
@@ -292,7 +284,7 @@
         }
 
         mDisplayContent.forAllWindows(w -> {
-            sendDragStartedLw(w, touchX, touchY, mDataDescription);
+            sendDragStartedLocked(w, touchX, touchY, mDataDescription);
         }, false /* traverseTopToBottom */ );
     }
 
@@ -304,7 +296,7 @@
      * This method clones the 'event' parameter if it's being delivered to the same
      * process, so it's safe for the caller to call recycle() on the event afterwards.
      */
-    private void sendDragStartedLw(WindowState newWin, float touchX, float touchY,
+    private void sendDragStartedLocked(WindowState newWin, float touchX, float touchY,
             ClipDescription desc) {
         if (mDragInProgress && isValidDropTarget(newWin)) {
             DragEvent event = obtainDragEvent(newWin, DragEvent.ACTION_DRAG_STARTED,
@@ -353,7 +345,7 @@
      * previously been notified, i.e. it became visible after the drag operation
      * was begun.  This is a rare case.
      */
-    void sendDragStartedIfNeededLw(WindowState newWin) {
+    void sendDragStartedIfNeededLocked(WindowState newWin) {
         if (mDragInProgress) {
             // If we have sent the drag-started, we needn't do so again
             if (isWindowNotified(newWin)) {
@@ -362,7 +354,7 @@
             if (DEBUG_DRAG) {
                 Slog.d(TAG_WM, "need to send DRAG_STARTED to new window " + newWin);
             }
-            sendDragStartedLw(newWin, mCurrentX, mCurrentY, mDataDescription);
+            sendDragStartedLocked(newWin, mCurrentX, mCurrentY, mDataDescription);
         }
     }
 
@@ -375,7 +367,7 @@
         return false;
     }
 
-    private void broadcastDragEndedLw() {
+    private void broadcastDragEndedLocked() {
         final int myPid = Process.myPid();
 
         if (DEBUG_DRAG) {
@@ -406,7 +398,7 @@
         mDragInProgress = false;
     }
 
-    void endDragLw() {
+    void endDragLocked() {
         if (mAnimator != null) {
             return;
         }
@@ -414,10 +406,10 @@
             mAnimator = createReturnAnimationLocked();
             return;  // Will call cleanUpDragLw when the animation is done.
         }
-        cleanUpDragLw();
+        cleanUpDragLocked();
     }
 
-    void cancelDragLw() {
+    void cancelDragLocked() {
         if (mAnimator != null) {
             return;
         }
@@ -430,14 +422,14 @@
             //    WindowManagerService, which will cause DragState#reset() while playing the
             //    cancel animation.
             reset();
-            mService.mDragDropController.mDragState = null;
+            mDragDropController.mDragState = null;
             return;
         }
         mAnimator = createCancelAnimationLocked();
     }
 
-    private void cleanUpDragLw() {
-        broadcastDragEndedLw();
+    private void cleanUpDragLocked() {
+        broadcastDragEndedLocked();
         if (isFromSource(InputDevice.SOURCE_MOUSE)) {
             mService.restorePointerIconLocked(mDisplayContent, mCurrentX, mCurrentY);
         }
@@ -447,10 +439,10 @@
 
         // free our resources and drop all the object references
         reset();
-        mService.mDragDropController.mDragState = null;
+        mDragDropController.mDragState = null;
     }
 
-    void notifyMoveLw(float x, float y) {
+    void notifyMoveLocked(float x, float y) {
         if (mAnimator != null) {
             return;
         }
@@ -459,7 +451,7 @@
 
         // Move the surface to the given touch
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
-                TAG_WM, ">>> OPEN TRANSACTION notifyMoveLw");
+                TAG_WM, ">>> OPEN TRANSACTION notifyMoveLocked");
         mService.openSurfaceTransaction();
         try {
             mSurfaceControl.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
@@ -469,12 +461,12 @@
         } finally {
             mService.closeSurfaceTransaction();
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(
-                    TAG_WM, "<<< CLOSE TRANSACTION notifyMoveLw");
+                    TAG_WM, "<<< CLOSE TRANSACTION notifyMoveLocked");
         }
-        notifyLocationLw(x, y);
+        notifyLocationLocked(x, y);
     }
 
-    void notifyLocationLw(float x, float y) {
+    void notifyLocationLocked(float x, float y) {
         // Tell the affected window
         WindowState touchedWin = mDisplayContent.getTouchableWinAtPointLocked(x, y);
         if (touchedWin != null && !isWindowNotified(touchedWin)) {
@@ -519,7 +511,7 @@
     // Find the drop target and tell it about the data.  Returns 'true' if we can immediately
     // dispatch the global drag-ended message, 'false' if we need to wait for a
     // result from the recipient.
-    boolean notifyDropLw(float x, float y) {
+    boolean notifyDropLocked(float x, float y) {
         if (mAnimator != null) {
             return false;
         }
@@ -563,9 +555,7 @@
             touchedWin.mClient.dispatchDragEvent(evt);
 
             // 5 second timeout for this window to respond to the drop
-            mService.mH.removeMessages(H.DRAG_END_TIMEOUT, token);
-            Message msg = mService.mH.obtainMessage(H.DRAG_END_TIMEOUT, token);
-            mService.mH.sendMessageDelayed(msg, 5000);
+            mDragDropController.sendTimeoutMessage(MSG_DRAG_END_TIMEOUT, token);
         } catch (RemoteException e) {
             Slog.w(TAG_WM, "can't send drop notification to win " + touchedWin);
             return true;
@@ -578,6 +568,15 @@
         return false;
     }
 
+    void onAnimationEndLocked() {
+        if (mAnimator == null) {
+            Slog.wtf(TAG_WM, "Unexpected null mAnimator");
+            return;
+        }
+        mAnimator = null;
+        cleanUpDragLocked();
+    }
+
     private static DragEvent obtainDragEvent(WindowState win, int action,
             float x, float y, Object localState,
             ClipDescription description, ClipData data,
@@ -641,40 +640,13 @@
         return (mTouchSource & source) == source;
     }
 
-    void overridePointerIconLw(int touchSource) {
+    void overridePointerIconLocked(int touchSource) {
         mTouchSource = touchSource;
         if (isFromSource(InputDevice.SOURCE_MOUSE)) {
             InputManager.getInstance().setPointerIconType(PointerIcon.TYPE_GRABBING);
         }
     }
 
-    private class DragStateHandler extends Handler {
-        DragStateHandler(Looper looper) {
-            super(looper);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            switch (msg.what) {
-                case MSG_ANIMATION_END:
-                    synchronized (mService.mWindowMap) {
-                        if (mService.mDragDropController.mDragState != DragState.this) {
-                            Slog.wtf(TAG_WM, "mDragState is updated unexpectedly while " +
-                                    "playing animation");
-                            return;
-                        }
-                        if (mAnimator == null) {
-                            Slog.wtf(TAG_WM, "Unexpected null mAnimator");
-                            return;
-                        }
-                        mAnimator = null;
-                        cleanUpDragLw();
-                    }
-                    break;
-            }
-        }
-    }
-
     private class AnimationListener
             implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
         @Override
@@ -708,7 +680,7 @@
         public void onAnimationEnd(Animator animator) {
             // Updating mDragState requires the WM lock so continues it on the out of
             // AnimationThread.
-            mHandler.sendEmptyMessage(MSG_ANIMATION_END);
+            mDragDropController.sendHandlerMessage(MSG_ANIMATION_END, null);
         }
     }
 }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index cf1f171..d23369e 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -690,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.mDragDropController.mDragState.sendDragStartedIfNeededLw(w);
+                mService.mDragDropController.mDragState.sendDragStartedIfNeededLocked(w);
             }
 
             addInputWindowHandle(
diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java
index 717c577..ad7c300 100644
--- a/services/core/java/com/android/server/wm/Session.java
+++ b/services/core/java/com/android/server/wm/Session.java
@@ -313,7 +313,7 @@
         final long ident = Binder.clearCallingIdentity();
         try {
             return mDragDropController.prepareDrag(
-                    mService, mSurfaceSession, callerPid, callerUid, window, flags, width, height,
+                    mSurfaceSession, callerPid, callerUid, window, flags, width, height,
                     outSurface);
         } finally {
             Binder.restoreCallingIdentity(ident);
@@ -324,7 +324,7 @@
     public boolean performDrag(IWindow window, IBinder dragToken,
             int touchSource, float touchX, float touchY, float thumbCenterX, float thumbCenterY,
             ClipData data) {
-        return mDragDropController.performDrag(mService, window, dragToken, touchSource,
+        return mDragDropController.performDrag(window, dragToken, touchSource,
                 touchX, touchY, thumbCenterX, thumbCenterY, data);
     }
 
@@ -332,7 +332,7 @@
     public void reportDropResult(IWindow window, boolean consumed) {
         final long ident = Binder.clearCallingIdentity();
         try {
-            mDragDropController.reportDropResult(mService, window, consumed);
+            mDragDropController.reportDropResult(window, consumed);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -342,7 +342,7 @@
     public void cancelDragAndDrop(IBinder dragToken) {
         final long ident = Binder.clearCallingIdentity();
         try {
-            mDragDropController.cancelDragAndDrop(mService, dragToken);
+            mDragDropController.cancelDragAndDrop(dragToken);
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index f31ea67..af26345 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -751,7 +751,7 @@
     boolean mAllowTheaterModeWakeFromLayout;
 
     TaskPositioner mTaskPositioner;
-    final DragDropController mDragDropController = new DragDropController();
+    final DragDropController mDragDropController;
 
     // For frozen screen animations.
     private int mExitAnimId, mEnterAnimId;
@@ -827,12 +827,12 @@
                                     + newX + "," + newY);
                             mMuteInput = true;
                             synchronized (mWindowMap) {
-                                endDrag = mDragDropController.mDragState.notifyDropLw(newX, newY);
+                                endDrag = mDragDropController.mDragState.notifyDropLocked(newX, newY);
                             }
                         } else {
                             synchronized (mWindowMap) {
                                 // move the surface and tell the involved window(s) where we are
-                                mDragDropController.mDragState.notifyMoveLw(newX, newY);
+                                mDragDropController.mDragState.notifyMoveLocked(newX, newY);
                             }
                         }
                     } break;
@@ -842,7 +842,7 @@
                                 + newX + "," + newY);
                         mMuteInput = true;
                         synchronized (mWindowMap) {
-                            endDrag = mDragDropController.mDragState.notifyDropLw(newX, newY);
+                            endDrag = mDragDropController.mDragState.notifyDropLocked(newX, newY);
                         }
                     } break;
 
@@ -857,9 +857,9 @@
                         if (DEBUG_DRAG) Slog.d(TAG_WM, "Drag ended; tearing down state");
                         // tell all the windows that the drag has ended
                         synchronized (mWindowMap) {
-                            // endDragLw will post back to looper to dispose the receiver
+                            // endDragLocked will post back to looper to dispose the receiver
                             // since we still need the receiver for the last finishInputEvent.
-                            mDragDropController.mDragState.endDragLw();
+                            mDragDropController.mDragState.endDragLocked();
                         }
                         mStylusButtonDownAtStart = false;
                         mIsStartEvent = true;
@@ -1164,6 +1164,7 @@
         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
 
+        mDragDropController = new DragDropController(this, mH.getLooper());
 
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
         initPolicy();
@@ -4796,8 +4797,6 @@
         public static final int APP_FREEZE_TIMEOUT = 17;
         public static final int SEND_NEW_CONFIGURATION = 18;
         public static final int REPORT_WINDOWS_CHANGE = 19;
-        public static final int DRAG_START_TIMEOUT = 20;
-        public static final int DRAG_END_TIMEOUT = 21;
 
         public static final int REPORT_HARD_KEYBOARD_STATUS_CHANGE = 22;
         public static final int BOOT_TIMEOUT = 23;
@@ -4824,8 +4823,6 @@
 
         public static final int UPDATE_DOCKED_STACK_DIVIDER = 41;
 
-        public static final int TEAR_DOWN_DRAG_AND_DROP_INPUT = 44;
-
         public static final int WINDOW_REPLACEMENT_TIMEOUT = 46;
 
         public static final int NOTIFY_APP_TRANSITION_STARTING = 47;
@@ -5053,13 +5050,6 @@
                     break;
                 }
 
-                case DRAG_START_TIMEOUT:
-                case DRAG_END_TIMEOUT:
-                case TEAR_DOWN_DRAG_AND_DROP_INPUT: {
-                    mDragDropController.handleMessage(WindowManagerService.this, msg);
-                    break;
-                }
-
                 case REPORT_HARD_KEYBOARD_STATUS_CHANGE: {
                     notifyHardKeyboardStatusChange();
                     break;