Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fd70b324 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge changes I08e9462a,I5f000734 into main

* changes:
  [DnD] Update documentation and added TODO for DragState
  [DnD] Update handleMotionEvent to accept displayId
parents 26b95bf6 751a41ea
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -289,7 +289,8 @@ class DragDropController {
                transaction.setAlpha(surfaceControl, mDragState.mOriginalAlpha);
                transaction.show(surfaceControl);
                displayContent.reparentToOverlay(transaction, surfaceControl);
                mDragState.updateDragSurfaceLocked(true, touchX, touchY);
                mDragState.updateDragSurfaceLocked(true /* keepHandling */,
                        displayContent.getDisplayId(), touchX, touchY);
                if (SHOW_LIGHT_TRANSACTIONS) {
                    Slog.i(TAG_WM, "<<< CLOSE TRANSACTION performDrag");
                }
@@ -483,10 +484,11 @@ class DragDropController {
     * Handles motion events.
     * @param keepHandling Whether if the drag operation is continuing or this is the last motion
     *          event.
     * @param displayId id of the display the X,Y coordinate is n.
     * @param newX X coordinate value in dp in the screen coordinate
     * @param newY Y coordinate value in dp in the screen coordinate
     */
    void handleMotionEvent(boolean keepHandling, float newX, float newY) {
    void handleMotionEvent(boolean keepHandling, int displayId, float newX, float newY) {
        synchronized (mService.mGlobalLock) {
            if (!dragDropActiveLocked()) {
                // The drag has ended but the clean-up message has not been processed by
@@ -495,7 +497,7 @@ class DragDropController {
                return;
            }

            mDragState.updateDragSurfaceLocked(keepHandling, newX, newY);
            mDragState.updateDragSurfaceLocked(keepHandling, displayId, newX, newY);
        }
    }

+4 −2
Original line number Diff line number Diff line
@@ -22,13 +22,13 @@ import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.BUTTON_STYLUS_PRIMARY;

import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;

import android.os.Looper;
import android.util.Slog;
import android.view.InputChannel;
import android.view.InputDevice;
import android.view.InputEvent;
import android.view.InputEventReceiver;
import android.view.MotionEvent;
@@ -63,6 +63,7 @@ class DragInputEventReceiver extends InputEventReceiver {
                return;
            }
            final MotionEvent motionEvent = (MotionEvent) event;
            final int displayId = motionEvent.getDisplayId();
            final float newX = motionEvent.getRawX();
            final float newY = motionEvent.getRawY();
            final boolean isStylusButtonDown =
@@ -102,7 +103,8 @@ class DragInputEventReceiver extends InputEventReceiver {
                    return;
            }

            mDragDropController.handleMotionEvent(!mMuteInput /* keepHandling */, newX, newY);
            mDragDropController.handleMotionEvent(!mMuteInput /* keepHandling */, displayId, newX,
                    newY);
            handled = true;
        } catch (Exception e) {
            Slog.e(TAG_WM, "Exception caught by drag handleMotion", e);
+100 −81
Original line number Diff line number Diff line
@@ -113,8 +113,8 @@ class DragState {
    boolean mRelinquishDragSurfaceToDropTarget;
    float mAnimatedScale = 1.0f;
    float mOriginalAlpha;
    float mOriginalX, mOriginalY;
    float mCurrentX, mCurrentY;
    float mOriginalDisplayX, mOriginalDisplayY;
    float mCurrentDisplayX, mCurrentDisplayY;
    float mThumbOffsetX, mThumbOffsetY;
    InputInterceptor mInputInterceptor;
    ArrayList<WindowState> mNotifiedWindows;
@@ -230,22 +230,22 @@ class DragState {
        if (mDragInProgress) {
            if (DEBUG_DRAG) Slog.d(TAG_WM, "Broadcasting DRAG_ENDED");
            for (WindowState ws : mNotifiedWindows) {
                float x = 0;
                float y = 0;
                float inWindowX = 0;
                float inWindowY = 0;
                SurfaceControl dragSurface = null;
                if (!mDragResult && (ws.mSession.mPid == mPid)) {
                    // Report unconsumed drop location back to the app that started the drag.
                    x = ws.translateToWindowX(mCurrentX);
                    y = ws.translateToWindowY(mCurrentY);
                    inWindowX = ws.translateToWindowX(mCurrentDisplayX);
                    inWindowY = ws.translateToWindowY(mCurrentDisplayY);
                    if (relinquishDragSurfaceToDragSource()) {
                        // If requested (and allowed), report the drag surface back to the app
                        // starting the drag to handle the return animation
                        dragSurface = mSurfaceControl;
                    }
                }
                DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, x, y,
                        mThumbOffsetX, mThumbOffsetY, mFlags, null, null, null, dragSurface, null,
                        mDragResult);
                DragEvent event = DragEvent.obtain(DragEvent.ACTION_DRAG_ENDED, inWindowX,
                        inWindowY, mThumbOffsetX, mThumbOffsetY, mFlags, null, null, null,
                        dragSurface, null, mDragResult);
                try {
                    if (DEBUG_DRAG) Slog.d(TAG_WM, "Sending DRAG_ENDED to " + ws);
                    ws.mClient.dispatchDragEvent(event);
@@ -297,24 +297,26 @@ class DragState {
    }

    /**
     * Creates the drop event for this drag gesture.  If `touchedWin` is null, then the drop event
     * will be created for dispatching to the unhandled drag and the drag surface will be provided
     * as a part of the dispatched event.
     * Creates the drop event for dispatching to the unhandled drag.
     * TODO(b/384841906): Update `inWindowX` and `inWindowY` to be display-coordinate.
     */
    private DragEvent createDropEvent(float x, float y, @Nullable WindowState touchedWin,
            boolean includePrivateInfo) {
        if (touchedWin != null) {
    private DragEvent createUnhandledDropEvent(float inWindowX, float inWindowY) {
        return obtainDragEvent(DragEvent.ACTION_DROP, inWindowX, inWindowY, mDataDescription, mData,
                /* includeDragSurface= */ true,
                /* includeDragFlags= */ true, null /* dragAndDropPermissions */);
    }

    /**
     * Creates the drop event for this drag gesture.
     */
    private DragEvent createDropEvent(float inWindowX, float inWindowY, WindowState touchedWin) {
        final int targetUserId = UserHandle.getUserId(touchedWin.getOwningUid());
        final DragAndDropPermissionsHandler dragAndDropPermissions;
        if ((mFlags & View.DRAG_FLAG_GLOBAL) != 0 && (mFlags & DRAG_FLAGS_URI_ACCESS) != 0
                && mData != null) {
                dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock,
                        mData,
                        mUid,
                        touchedWin.getOwningPackage(),
                        mFlags & DRAG_FLAGS_URI_PERMISSIONS,
                        mSourceUserId,
                        targetUserId);
            dragAndDropPermissions = new DragAndDropPermissionsHandler(mService.mGlobalLock, mData,
                    mUid, touchedWin.getOwningPackage(), mFlags & DRAG_FLAGS_URI_PERMISSIONS,
                    mSourceUserId, targetUserId);
        } else {
            dragAndDropPermissions = null;
        }
@@ -324,43 +326,42 @@ class DragState {
            }
        }
        final boolean targetInterceptsGlobalDrag = targetInterceptsGlobalDrag(touchedWin);
            return obtainDragEvent(DragEvent.ACTION_DROP, x, y, mDataDescription, mData,
        return obtainDragEvent(DragEvent.ACTION_DROP, inWindowX, inWindowY, mDataDescription, mData,
                /* includeDragSurface= */ targetInterceptsGlobalDrag,
                    /* includeDragFlags= */ targetInterceptsGlobalDrag,
                    dragAndDropPermissions);
        } else {
            return obtainDragEvent(DragEvent.ACTION_DROP, x, y, mDataDescription, mData,
                    /* includeDragSurface= */ includePrivateInfo,
                    /* includeDragFlags= */ includePrivateInfo,
                    null /* dragAndDropPermissions */);
        }
                /* includeDragFlags= */ targetInterceptsGlobalDrag, dragAndDropPermissions);
    }

    /**
     * Notify the drop target and tells it about the data. If the drop event is not sent to the
     * target, invokes {@code endDragLocked} after the unhandled drag listener gets a chance to
     * handle the drop.
     * @param inWindowX if `token` refers to a dragEvent-accepting window, `inWindowX` will be
     *                  inside the window, else values might be invalid (0, 0).
     * @param inWindowY if `token` refers to a dragEvent-accepting window, `inWindowY` will be
     *                  inside the window, else values might be invalid (0, 0).
     */
    boolean reportDropWindowLock(IBinder token, float x, float y) {
    boolean reportDropWindowLock(IBinder token, float inWindowX, float inWindowY) {
        if (mAnimator != null) {
            return false;
        }
        try {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "DragDropController#DROP");
            return reportDropWindowLockInner(token, x, y);
            return reportDropWindowLockInner(token, inWindowX, inWindowY);
        } finally {
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
        }
    }

    private boolean reportDropWindowLockInner(IBinder token, float x, float y) {
    private boolean reportDropWindowLockInner(IBinder token, float inWindowX, float inWindowY) {
        if (mAnimator != null) {
            return false;
        }

        final WindowState touchedWin = mService.mInputToWindowMap.get(token);
        final DragEvent unhandledDropEvent = createDropEvent(x, y, null /* touchedWin */,
                true /* includePrivateInfo */);
        // TODO(b/384841906): The x, y here when sent to a window and unhandled, will still be
        //  relative to the window it was originally sent to. Need to update this to actually be
        //  display-coordinate.
        final DragEvent unhandledDropEvent = createUnhandledDropEvent(inWindowX, inWindowY);
        if (!isWindowNotified(touchedWin)) {
            // Delegate to the unhandled drag listener as a first pass
            if (mDragDropController.notifyUnhandledDrop(unhandledDropEvent, "unhandled-drop")) {
@@ -381,7 +382,7 @@ class DragState {
        if (DEBUG_DRAG) Slog.d(TAG_WM, "Sending DROP to " + touchedWin);

        final IBinder clientToken = touchedWin.mClient.asBinder();
        final DragEvent event = createDropEvent(x, y, touchedWin, false /* includePrivateInfo */);
        final DragEvent event = createDropEvent(inWindowX, inWindowY, touchedWin);
        try {
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "DragDropController#dispatchDrop");
            touchedWin.mClient.dispatchDragEvent(event);
@@ -486,8 +487,8 @@ class DragState {
     */
    void broadcastDragStartedLocked(final float touchX, final float touchY) {
        Trace.instant(TRACE_TAG_WINDOW_MANAGER, "DragDropController#DRAG_STARTED");
        mOriginalX = mCurrentX = touchX;
        mOriginalY = mCurrentY = touchY;
        mOriginalDisplayX = mCurrentDisplayX = touchX;
        mOriginalDisplayY = mCurrentDisplayY = touchY;

        // Cache a base-class instance of the clip metadata so that parceling
        // works correctly in calling out to the apps.
@@ -636,7 +637,7 @@ class DragState {
            if (isWindowNotified(newWin)) {
                return;
            }
            sendDragStartedLocked(newWin, mCurrentX, mCurrentY,
            sendDragStartedLocked(newWin, mCurrentDisplayX, mCurrentDisplayY,
                    containsApplicationExtras(mDataDescription));
        }
    }
@@ -685,12 +686,21 @@ class DragState {
        mAnimator = createCancelAnimationLocked();
    }

    void updateDragSurfaceLocked(boolean keepHandling, float x, float y) {
    /**
     * Updates the position of the drag surface.
     *
     * @param keepHandling whether to keep handling the drag.
     * @param displayId the display ID of the drag surface.
     * @param displayX the x-coordinate of the drag surface in the display's coordinate frame.
     * @param displayY the y-coordinate of the drag surface in the display's coordinate frame.
     */
    void updateDragSurfaceLocked(boolean keepHandling, int displayId, float displayX,
            float displayY) {
        if (mAnimator != null) {
            return;
        }
        mCurrentX = x;
        mCurrentY = y;
        mCurrentDisplayX = displayX;
        mCurrentDisplayY = displayY;

        if (!keepHandling) {
            return;
@@ -700,9 +710,10 @@ class DragState {
        if (SHOW_LIGHT_TRANSACTIONS) {
            Slog.i(TAG_WM, ">>> OPEN TRANSACTION notifyMoveLocked");
        }
        mTransaction.setPosition(mSurfaceControl, x - mThumbOffsetX, y - mThumbOffsetY).apply();
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "DRAG %s: pos=(%d,%d)", mSurfaceControl,
                (int) (x - mThumbOffsetX), (int) (y - mThumbOffsetY));
        mTransaction.setPosition(mSurfaceControl, displayX - mThumbOffsetX,
                displayY - mThumbOffsetY).apply();
        ProtoLog.i(WM_SHOW_TRANSACTIONS, "DRAG %s: displayId=%d, pos=(%d,%d)", mSurfaceControl,
                displayId, (int) (displayX - mThumbOffsetX), (int) (displayY - mThumbOffsetY));
    }

    /**
@@ -713,6 +724,12 @@ class DragState {
        return mDragInProgress;
    }

    /**
     * `x` and `y` here varies between local window coordinate, relative coordinate to another
     * window and local display coordinate, all depending on the `action`. Please take a look
     * at the callers to determine the type.
     * TODO(b/384845022): Properly document the events sent based on the event type.
     */
    private DragEvent obtainDragEvent(int action, float x, float y, ClipDescription description,
            ClipData data, boolean includeDragSurface, boolean includeDragFlags,
            IDragAndDropPermissions dragAndDropPermissions) {
@@ -728,34 +745,34 @@ class DragState {
        final long duration;
        if (mCallingTaskIdToHide != -1) {
            animator = ValueAnimator.ofPropertyValuesHolder(
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentX, mCurrentX),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentY, mCurrentY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentDisplayX,
                            mCurrentDisplayX),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentDisplayY,
                            mCurrentDisplayY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale,
                            mAnimatedScale),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, 0f));
            duration = MIN_ANIMATION_DURATION_MS;
        } else {
            animator = ValueAnimator.ofPropertyValuesHolder(
                    PropertyValuesHolder.ofFloat(
                            ANIMATED_PROPERTY_X, mCurrentX - mThumbOffsetX,
                            mOriginalX - mThumbOffsetX),
                    PropertyValuesHolder.ofFloat(
                            ANIMATED_PROPERTY_Y, mCurrentY - mThumbOffsetY,
                            mOriginalY - mThumbOffsetY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X,
                            mCurrentDisplayX - mThumbOffsetX, mOriginalDisplayX - mThumbOffsetX),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y,
                            mCurrentDisplayY - mThumbOffsetY, mOriginalDisplayY - mThumbOffsetY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale,
                            mAnimatedScale),
                    PropertyValuesHolder.ofFloat(
                            ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, mOriginalAlpha / 2));
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha,
                            mOriginalAlpha / 2));

            final float translateX = mOriginalX - mCurrentX;
            final float translateY = mOriginalY - mCurrentY;
            final float translateX = mOriginalDisplayX - mCurrentDisplayX;
            final float translateY = mOriginalDisplayY - mCurrentDisplayY;
            // Adjust the duration to the travel distance.
            final double travelDistance = Math.sqrt(
                    translateX * translateX + translateY * translateY);
            final double displayDiagonal =
                    Math.sqrt(mDisplaySize.x * mDisplaySize.x + mDisplaySize.y * mDisplaySize.y);
            duration = MIN_ANIMATION_DURATION_MS + (long) (travelDistance / displayDiagonal
                    * (MAX_ANIMATION_DURATION_MS - MIN_ANIMATION_DURATION_MS));
            final double displayDiagonal = Math.sqrt(
                    mDisplaySize.x * mDisplaySize.x + mDisplaySize.y * mDisplaySize.y);
            duration = MIN_ANIMATION_DURATION_MS + (long) (travelDistance / displayDiagonal * (
                    MAX_ANIMATION_DURATION_MS - MIN_ANIMATION_DURATION_MS));
        }

        final AnimationListener listener = new AnimationListener();
@@ -772,17 +789,19 @@ class DragState {
        final ValueAnimator animator;
        if (mCallingTaskIdToHide != -1) {
            animator = ValueAnimator.ofPropertyValuesHolder(
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentX, mCurrentX),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentY, mCurrentY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X, mCurrentDisplayX,
                            mCurrentDisplayX),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y, mCurrentDisplayY,
                            mCurrentDisplayY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale,
                            mAnimatedScale),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, 0f));
        } else {
            animator = ValueAnimator.ofPropertyValuesHolder(
                    PropertyValuesHolder.ofFloat(
                            ANIMATED_PROPERTY_X, mCurrentX - mThumbOffsetX, mCurrentX),
                    PropertyValuesHolder.ofFloat(
                            ANIMATED_PROPERTY_Y, mCurrentY - mThumbOffsetY, mCurrentY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_X,
                            mCurrentDisplayX - mThumbOffsetX, mCurrentDisplayX),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_Y,
                            mCurrentDisplayY - mThumbOffsetY, mCurrentDisplayY),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_SCALE, mAnimatedScale, 0),
                    PropertyValuesHolder.ofFloat(ANIMATED_PROPERTY_ALPHA, mOriginalAlpha, 0));
        }
+18 −13
Original line number Diff line number Diff line
@@ -150,8 +150,8 @@ public class DragDropControllerTests extends WindowTestsBase {
                mProcess).build();

        // Use a new TestIWindow so we don't collect events for other windows
        final WindowState window = createWindow(null, TYPE_BASE_APPLICATION, activity, name,
                ownerId, false, new TestIWindow());
        final WindowState window = newWindowBuilder(name, TYPE_BASE_APPLICATION).setWindowToken(
                activity).setOwnerId(ownerId).setClientWindow(new TestIWindow()).build();
        InputChannel channel = new InputChannel();
        window.openInputChannel(channel);
        window.mHasSurface = true;
@@ -249,7 +249,7 @@ public class DragDropControllerTests extends WindowTestsBase {
                        mTarget.mDeferDragStateClosed = true;
                        mTarget.reportDropWindow(mWindow.mInputChannelToken, 0, 0);
                        // Verify the drop event includes the drag surface
                        mTarget.handleMotionEvent(false, 0, 0);
                        mTarget.handleMotionEvent(false, mWindow.getDisplayId(), 0, 0);
                        final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
                        assertTrue(dropEvent.getDragSurface() != null);

@@ -296,7 +296,7 @@ public class DragDropControllerTests extends WindowTestsBase {
                            0).getClipData().willParcelWithActivityInfo());

                    mTarget.reportDropWindow(globalInterceptWindow.mInputChannelToken, 0, 0);
                    mTarget.handleMotionEvent(false, 0, 0);
                    mTarget.handleMotionEvent(false, globalInterceptWindow.getDisplayId(), 0, 0);
                    mToken = globalInterceptWindow.mClient.asBinder();

                    // Verify the drop event is only sent for the global intercept window
@@ -334,8 +334,8 @@ public class DragDropControllerTests extends WindowTestsBase {
                    try {
                        mTarget.mDeferDragStateClosed = true;
                        mTarget.reportDropWindow(mWindow.mInputChannelToken, 0, 0);
                        // // Verify the drop event does not have the drag flags
                        mTarget.handleMotionEvent(false, 0, 0);
                        // Verify the drop event does not have the drag flags
                        mTarget.handleMotionEvent(false, mWindow.getDisplayId(), 0, 0);
                        final DragEvent dropEvent = dragEvents.get(dragEvents.size() - 1);
                        assertTrue(dropEvent.getDragFlags() == (View.DRAG_FLAG_GLOBAL
                                | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG));
@@ -520,7 +520,7 @@ public class DragDropControllerTests extends WindowTestsBase {

                    // Verify after consuming that the drag surface is relinquished
                    mTarget.reportDropWindow(otherWindow.mInputChannelToken, 0, 0);
                    mTarget.handleMotionEvent(false, 0, 0);
                    mTarget.handleMotionEvent(false, otherWindow.getDisplayId(), 0, 0);
                    mToken = otherWindow.mClient.asBinder();
                    mTarget.reportDropResult(otherIWindow, true);

@@ -551,7 +551,7 @@ public class DragDropControllerTests extends WindowTestsBase {

                    // Verify after consuming that the drag surface is relinquished
                    mTarget.reportDropWindow(otherWindow.mInputChannelToken, 0, 0);
                    mTarget.handleMotionEvent(false, 0, 0);
                    mTarget.handleMotionEvent(false, otherWindow.getDisplayId(), 0, 0);
                    mToken = otherWindow.mClient.asBinder();
                    mTarget.reportDropResult(otherIWindow, false);

@@ -586,7 +586,8 @@ public class DragDropControllerTests extends WindowTestsBase {
                ClipData.newPlainText("label", "Test"), () -> {
                    // Trigger an unhandled drop and verify the global drag listener was called
                    mTarget.reportDropWindow(mWindow.mInputChannelToken, invalidXY, invalidXY);
                    mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
                    mTarget.handleMotionEvent(false /* keepHandling */, mWindow.getDisplayId(),
                            invalidXY, invalidXY);
                    mTarget.reportDropResult(mWindow.mClient, false);
                    mTarget.onUnhandledDropCallback(true);
                    mToken = null;
@@ -610,7 +611,8 @@ public class DragDropControllerTests extends WindowTestsBase {
                ClipData.newPlainText("label", "Test"), () -> {
                    // Trigger an unhandled drop and verify the global drag listener was called
                    mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
                    mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
                    mTarget.handleMotionEvent(false /* keepHandling */, mWindow.getDisplayId(),
                            invalidXY, invalidXY);
                    mTarget.onUnhandledDropCallback(true);
                    mToken = null;
                    try {
@@ -632,7 +634,8 @@ public class DragDropControllerTests extends WindowTestsBase {
        startDrag(View.DRAG_FLAG_GLOBAL, ClipData.newPlainText("label", "Test"), () -> {
            // Trigger an unhandled drop and verify the global drag listener was not called
            mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
            mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
            mTarget.handleMotionEvent(false /* keepHandling */, mDisplayContent.getDisplayId(),
                    invalidXY, invalidXY);
            mToken = null;
            try {
                verify(listener, never()).onUnhandledDrop(any(), any());
@@ -654,7 +657,8 @@ public class DragDropControllerTests extends WindowTestsBase {
                ClipData.newPlainText("label", "Test"), () -> {
                    // Trigger an unhandled drop and verify the global drag listener was called
                    mTarget.reportDropWindow(mock(IBinder.class), invalidXY, invalidXY);
                    mTarget.handleMotionEvent(false /* keepHandling */, invalidXY, invalidXY);
                    mTarget.handleMotionEvent(false /* keepHandling */,
                            mDisplayContent.getDisplayId(), invalidXY, invalidXY);

                    // Verify that the unhandled drop listener callback timeout has been scheduled
                    final Handler handler = mTarget.getHandler();
@@ -673,7 +677,8 @@ public class DragDropControllerTests extends WindowTestsBase {
    private void doDragAndDrop(int flags, ClipData data, float dropX, float dropY) {
        startDrag(flags, data, () -> {
            mTarget.reportDropWindow(mWindow.mInputChannelToken, dropX, dropY);
            mTarget.handleMotionEvent(false /* keepHandling */, dropX, dropY);
            mTarget.handleMotionEvent(false /* keepHandling */, mWindow.getDisplayId(), dropX,
                    dropY);
            mToken = mWindow.mClient.asBinder();
        });
    }