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

Commit 55048e88 authored by Winson Chung's avatar Winson Chung
Browse files

Fix issue with the unhandled drag flag not being respected

- We should always only call the unhandled drag callback if the drag
  flag is set (even if there is a launchable intent in the clip data)
- Also renaming some tests now that the unhandled drag listener is
  a more generic global drag listener

Bug: 320797628
Test: atest DragDropControllerTests
Change-Id: I6e50745ec64373926c99b2c4f562bd23f434708c
parent 12adb88b
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package com.android.server.wm;

import static android.view.View.DRAG_FLAG_GLOBAL;
import static android.view.View.DRAG_FLAG_GLOBAL_SAME_APPLICATION;
import static android.view.View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG;

import static com.android.input.flags.Flags.enablePointerChoreographer;
import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DRAG;
@@ -373,8 +374,11 @@ class DragDropController {
    boolean notifyUnhandledDrop(DragEvent dropEvent, String reason) {
        final boolean isLocalDrag =
                (mDragState.mFlags & (DRAG_FLAG_GLOBAL_SAME_APPLICATION | DRAG_FLAG_GLOBAL)) == 0;
        final boolean shouldDelegateUnhandledDrag =
                (mDragState.mFlags & DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG) != 0;
        if (!com.android.window.flags.Flags.delegateUnhandledDrags()
                || mGlobalDragListener == null
                || !shouldDelegateUnhandledDrag
                || isLocalDrag) {
            // Skip if the flag is disabled, there is no unhandled-drag listener, or if this is a
            // purely local drag
+36 −10
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;

@@ -541,7 +542,7 @@ public class DragDropControllerTests extends WindowTestsBase {
    }

    @Test
    public void testUnhandledDragListenerNotCalledForNormalDrags() throws RemoteException {
    public void testUnhandledDragNotCalledForNormalDrags() throws RemoteException {
        assumeTrue(com.android.window.flags.Flags.delegateUnhandledDrags());

        final IGlobalDragListener listener = mock(IGlobalDragListener.class);
@@ -552,15 +553,16 @@ public class DragDropControllerTests extends WindowTestsBase {
    }

    @Test
    public void testUnhandledDragListenerReceivesUnhandledDropOverWindow() {
    public void testUnhandledDragReceivesUnhandledDropOverWindow() {
        assumeTrue(com.android.window.flags.Flags.delegateUnhandledDrags());

        final IGlobalDragListener listener = mock(IGlobalDragListener.class);
        doReturn(mock(Binder.class)).when(listener).asBinder();
        mTarget.setGlobalDragListener(listener);
        final int invalidXY = 100_000;
        startDrag(View.DRAG_FLAG_GLOBAL, ClipData.newPlainText("label", "Test"), () -> {
            // Notify the unhandled drag listener
        startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
                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.reportDropResult(mWindow.mClient, false);
@@ -575,15 +577,16 @@ public class DragDropControllerTests extends WindowTestsBase {
    }

    @Test
    public void testUnhandledDragListenerReceivesUnhandledDropOverNoValidWindow() {
    public void testUnhandledDragReceivesUnhandledDropOverNoValidWindow() {
        assumeTrue(com.android.window.flags.Flags.delegateUnhandledDrags());

        final IGlobalDragListener listener = mock(IGlobalDragListener.class);
        doReturn(mock(Binder.class)).when(listener).asBinder();
        mTarget.setGlobalDragListener(listener);
        final int invalidXY = 100_000;
        startDrag(View.DRAG_FLAG_GLOBAL, ClipData.newPlainText("label", "Test"), () -> {
            // Notify the unhandled drag listener
        startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
                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.onUnhandledDropCallback(true);
@@ -597,15 +600,38 @@ public class DragDropControllerTests extends WindowTestsBase {
    }

    @Test
    public void testUnhandledDragListenerCallbackTimeout() {
    public void testUnhandledDragDoesNotReceiveUnhandledDropWithoutDragFlag() {
        assumeTrue(com.android.window.flags.Flags.delegateUnhandledDrags());

        final IGlobalDragListener listener = mock(IGlobalDragListener.class);
        doReturn(mock(Binder.class)).when(listener).asBinder();
        mTarget.setGlobalDragListener(listener);
        final int invalidXY = 100_000;
        startDrag(View.DRAG_FLAG_GLOBAL, ClipData.newPlainText("label", "Test"), () -> {
            // Notify the unhandled drag listener
        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);
                    mToken = null;
                    try {
                        verify(listener, never()).onUnhandledDrop(any(), any());
                    } catch (RemoteException e) {
                        fail("Failed to verify unhandled drop: " + e);
                    }
                });
    }

    @Test
    public void testUnhandledDragCallbackTimeout() {
        assumeTrue(com.android.window.flags.Flags.delegateUnhandledDrags());

        final IGlobalDragListener listener = mock(IGlobalDragListener.class);
        doReturn(mock(Binder.class)).when(listener).asBinder();
        mTarget.setGlobalDragListener(listener);
        final int invalidXY = 100_000;
        startDrag(View.DRAG_FLAG_GLOBAL | View.DRAG_FLAG_START_INTENT_SENDER_ON_UNHANDLED_DRAG,
                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);