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;
+ }
}
}
}