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

Commit 771a769d authored by Hu Guo's avatar Hu Guo Committed by Prabir Pradhan
Browse files

Dispatch cancel event to the correct target display

When screen recording is enabled, a virtual screen will be generated, and the cancel event will be incorrectly sent to the virtual screen. The coordinates of the cancel event are the wrong logical coordinates after being transformed by the transform of the windows of the virtual screen.

Bug: 301020008
Test: atest inputflinger_tests
Change-Id: Icf1301e5174ac61eeedda326545f2b68ef7b8af0
parent 3821b0df
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -3940,8 +3940,13 @@ void InputDispatcher::synthesizeCancelationEventsForConnectionLocked(
            << connection->getInputChannelName().c_str() << reason << LOG_ID_EVENTS;

    InputTarget target;
    sp<WindowInfoHandle> windowHandle =
            getWindowHandleLocked(connection->inputChannel->getConnectionToken());
    sp<WindowInfoHandle> windowHandle;
    if (options.displayId) {
        windowHandle = getWindowHandleLocked(connection->inputChannel->getConnectionToken(),
                                             options.displayId.value());
    } else {
        windowHandle = getWindowHandleLocked(connection->inputChannel->getConnectionToken());
    }
    if (windowHandle != nullptr) {
        const WindowInfo* windowInfo = windowHandle->getInfo();
        target.setDefaultPointerTransform(windowInfo->transform);
+54 −0
Original line number Diff line number Diff line
@@ -3977,6 +3977,60 @@ TEST_F(InputDispatcherTest, MultiplePointersWithRotatingWindow) {
    window->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
}

/**
 * When there are multiple screens, such as screen projection to TV or screen recording, if the
 * cancel event occurs, the coordinates of the cancel event should be sent to the target screen, and
 * its coordinates should be converted by the transform of the windows of target screen.
 */
TEST_F(InputDispatcherTest, WhenMultiDisplayWindowSameToken_DispatchCancelToTargetDisplay) {
    // This case will create a window and a spy window on the default display and mirror
    //  window on the second display. cancel event is sent through spy  window pilferPointers
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();

    sp<FakeWindowHandle> spyWindowDefaultDisplay =
            sp<FakeWindowHandle>::make(application, mDispatcher, "Spy", ADISPLAY_ID_DEFAULT);
    spyWindowDefaultDisplay->setTrustedOverlay(true);
    spyWindowDefaultDisplay->setSpy(true);

    sp<FakeWindowHandle> windowDefaultDisplay =
            sp<FakeWindowHandle>::make(application, mDispatcher, "DefaultDisplay",
                                       ADISPLAY_ID_DEFAULT);
    windowDefaultDisplay->setWindowTransform(1, 0, 0, 1);

    sp<FakeWindowHandle> windowSecondDisplay = windowDefaultDisplay->clone(SECOND_DISPLAY_ID);
    windowSecondDisplay->setWindowTransform(2, 0, 0, 2);

    // Add the windows to the dispatcher
    mDispatcher->onWindowInfosChanged(
            {{*spyWindowDefaultDisplay->getInfo(), *windowDefaultDisplay->getInfo(),
              *windowSecondDisplay->getInfo()},
             {},
             0,
             0});

    // Send down to ADISPLAY_ID_DEFAULT
    ASSERT_EQ(InputEventInjectionResult::SUCCEEDED,
              injectMotionDown(*mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               {100, 100}))
            << "Inject motion event should return InputEventInjectionResult::SUCCEEDED";

    spyWindowDefaultDisplay->consumeMotionDown();
    windowDefaultDisplay->consumeMotionDown();

    EXPECT_EQ(OK, mDispatcher->pilferPointers(spyWindowDefaultDisplay->getToken()));

    // windowDefaultDisplay gets cancel
    MotionEvent* event = windowDefaultDisplay->consumeMotion();
    EXPECT_EQ(AMOTION_EVENT_ACTION_CANCEL, event->getAction());

    // The cancel event is sent to windowDefaultDisplay of the ADISPLAY_ID_DEFAULT display, so the
    // coordinates of the cancel are converted by windowDefaultDisplay's transform, the x and y
    // coordinates are both 100, otherwise if the cancel event is sent to windowSecondDisplay of
    // SECOND_DISPLAY_ID, the x and y coordinates are 200
    EXPECT_EQ(100, event->getX(0));
    EXPECT_EQ(100, event->getY(0));
}

/**
 * Ensure the correct coordinate spaces are used by InputDispatcher.
 *