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

Commit 6d0571e4 authored by Arthur Hung's avatar Arthur Hung
Browse files

Fix the drag window still alive after drop failed

We should report the invalid drop window even if there is no visible
window can be found, the DragState from WindowManager side would
decide playing a cancel animation or remove the drag window immediately.

Test: atest CrossAppDragAndDrop
Test: atest inputflinger_tests
Bug: 182792292
Bug: 183880545
Bug: 183880412
Bug: 182234653
Bug: 183877512
Change-Id: I017caeb2ed953e395831cd5b77186f5ab3d33765
parent cb1d05d0
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -2326,6 +2326,8 @@ void InputDispatcher::finishDragAndDrop(int32_t displayId, float x, float y) {
    if (dropWindow) {
        vec2 local = dropWindow->getInfo()->transform.transform(x, y);
        notifyDropWindowLocked(dropWindow->getToken(), local.x, local.y);
    } else {
        notifyDropWindowLocked(nullptr, 0, 0);
    }
    mDragState.reset();
}
@@ -2372,6 +2374,7 @@ void InputDispatcher::addDragEventLocked(const MotionEntry& entry) {
    } else if (maskedAction == AMOTION_EVENT_ACTION_UP) {
        finishDragAndDrop(entry.displayId, x, y);
    } else if (maskedAction == AMOTION_EVENT_ACTION_CANCEL) {
        notifyDropWindowLocked(nullptr, 0, 0);
        mDragState.reset();
    }
}
+40 −0
Original line number Diff line number Diff line
@@ -268,7 +268,9 @@ public:

    void assertDropTargetEquals(const sp<IBinder>& targetToken) {
        std::scoped_lock lock(mLock);
        ASSERT_TRUE(mNotifyDropWindowWasCalled);
        ASSERT_EQ(targetToken, mDropTargetWindowToken);
        mNotifyDropWindowWasCalled = false;
    }

private:
@@ -290,6 +292,7 @@ private:
    std::condition_variable mNotifyAnr;

    sp<IBinder> mDropTargetWindowToken GUARDED_BY(mLock);
    bool mNotifyDropWindowWasCalled GUARDED_BY(mLock) = false;

    void notifyConfigurationChanged(nsecs_t when) override {
        std::scoped_lock lock(mLock);
@@ -403,6 +406,7 @@ private:

    void notifyDropWindow(const sp<IBinder>& token, float x, float y) override {
        std::scoped_lock lock(mLock);
        mNotifyDropWindowWasCalled = true;
        mDropTargetWindowToken = token;
    }

@@ -4951,4 +4955,40 @@ TEST_F(InputDispatcherDragTests, StylusDragAndDrop) {
    mSecondWindow->assertNoEvents();
}

TEST_F(InputDispatcherDragTests, DragAndDrop_InvalidWindow) {
    performDrag();

    // Set second window invisible.
    mSecondWindow->setVisible(false);
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {mDragWindow, mWindow, mSecondWindow}}});

    // Move on window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
                                ADISPLAY_ID_DEFAULT, {50, 50}))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
    mWindow->consumeDragEvent(false, 50, 50);
    mSecondWindow->assertNoEvents();

    // Move to another window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN,
                                ADISPLAY_ID_DEFAULT, {150, 50}))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    mDragWindow->consumeMotionMove(ADISPLAY_ID_DEFAULT);
    mWindow->consumeDragEvent(true, 150, 50);
    mSecondWindow->assertNoEvents();

    // drop to another window.
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionUp(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                             {150, 50}))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";
    mDragWindow->consumeMotionUp(ADISPLAY_ID_DEFAULT);
    mFakePolicy->assertDropTargetEquals(nullptr);
    mWindow->assertNoEvents();
    mSecondWindow->assertNoEvents();
}

} // namespace android::inputdispatcher