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

Commit 167e6d9e authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

InputDispatcher: Fix crash with out-of-order pointer capture requests

One of the conditions being tested in a LOG_ALWAYS_FATAL call was
incorrect, causing a crash when Pointer Capture requests happened in a
certain order.

This CL adds a test that exposes the sequence of events that caused the
crash, and changes the condition in the LOG_ALWAYS_FATAL check to the
correct condition, thereby fixing the crash.

Bug: 179303721
Test: atest inputflinger_tests
Change-Id: I145c71609572b6c6714b8932889cd48523c91511
parent cf1509d0
Loading
Loading
Loading
Loading
+4 −3
Original line number Diff line number Diff line
@@ -1247,9 +1247,10 @@ void InputDispatcher::dispatchPointerCaptureChangedLocked(
        nsecs_t currentTime, const std::shared_ptr<PointerCaptureChangedEntry>& entry,
        DropReason& dropReason) {
    const bool haveWindowWithPointerCapture = mWindowTokenWithPointerCapture != nullptr;
    if (entry->pointerCaptureEnabled == haveWindowWithPointerCapture) {
        LOG_ALWAYS_FATAL_IF(mFocusedWindowRequestedPointerCapture,
                            "The Pointer Capture state has already been dispatched to the window.");
    if (entry->pointerCaptureEnabled && haveWindowWithPointerCapture) {
        LOG_ALWAYS_FATAL("Pointer Capture has already been enabled for the window.");
    }
    if (!entry->pointerCaptureEnabled && !haveWindowWithPointerCapture) {
        // Pointer capture was already forcefully disabled because of focus change.
        dropReason = DropReason::NOT_DROPPED;
        return;
+23 −0
Original line number Diff line number Diff line
@@ -4215,4 +4215,27 @@ TEST_F(InputDispatcherPointerCaptureTests, UnexpectedStateChangeDisablesPointerC
    mWindow->assertNoEvents();
}

TEST_F(InputDispatcherPointerCaptureTests, OutOfOrderRequests) {
    requestAndVerifyPointerCapture(mWindow, true);

    // The first window loses focus.
    setFocusedWindow(mSecondWindow);
    mFakePolicy->waitForSetPointerCapture(false);
    mWindow->consumeCaptureEvent(false);

    // Request Pointer Capture from the second window before the notification from InputReader
    // arrives.
    mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
    mFakePolicy->waitForSetPointerCapture(true);

    // InputReader notifies Pointer Capture was disabled (because of the focus change).
    notifyPointerCaptureChanged(false);

    // InputReader notifies Pointer Capture was enabled (because of mSecondWindow's request).
    notifyPointerCaptureChanged(true);

    mSecondWindow->consumeFocusEvent(true);
    mSecondWindow->consumeCaptureEvent(true);
}

} // namespace android::inputdispatcher