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

Commit 7092e268 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Address Pointer Capture crash during rapid toggles

If an app has pointer capture enabled, and it rapidly toggles capture
off and on, there is a high likelihood for a system crash. We can
deterministically reproduce this case in the tests, so we address that
use case here.

Bug: 230850070
Test: atest inputflinger_tests
Change-Id: I1ecacf468d48b3def30fd5844d2e25128569e289
parent 5d7e9601
Loading
Loading
Loading
Loading
+4 −2
Original line number Original line Diff line number Diff line
@@ -1421,8 +1421,10 @@ void InputDispatcher::dispatchPointerCaptureChangedLocked(
        // Enable Pointer Capture.
        // Enable Pointer Capture.
        if (haveWindowWithPointerCapture &&
        if (haveWindowWithPointerCapture &&
            (entry->pointerCaptureRequest == mCurrentPointerCaptureRequest)) {
            (entry->pointerCaptureRequest == mCurrentPointerCaptureRequest)) {
            LOG_ALWAYS_FATAL("This request to enable Pointer Capture has already been dispatched "
            // This can happen if pointer capture is disabled and re-enabled before we notify the
                             "to the window.");
            // app of the state change, so there is no need to notify the app.
            ALOGI("Skipping dispatch of Pointer Capture being enabled: no state change.");
            return;
        }
        }
        if (!mCurrentPointerCaptureRequest.enable) {
        if (!mCurrentPointerCaptureRequest.enable) {
            // This can happen if a window requests capture and immediately releases capture.
            // This can happen if a window requests capture and immediately releases capture.
+19 −0
Original line number Original line Diff line number Diff line
@@ -5671,6 +5671,25 @@ TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers)
    mWindow->consumeCaptureEvent(true);
    mWindow->consumeCaptureEvent(true);
}
}


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

    // App toggles pointer capture off and on.
    mDispatcher->requestPointerCapture(mWindow->getToken(), false);
    mFakePolicy->assertSetPointerCaptureCalled(false);

    mDispatcher->requestPointerCapture(mWindow->getToken(), true);
    auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);

    // InputReader notifies that the latest "enable" request was processed, while skipping over the
    // preceding "disable" request.
    notifyPointerCaptureChanged(enableRequest);

    // Since pointer capture was never disabled during the rapid toggle, the window does not receive
    // any notifications.
    mWindow->assertNoEvents();
}

class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
protected:
protected:
    constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;
    constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;