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