diff options
author | 2022-05-03 16:51:09 +0000 | |
---|---|---|
committer | 2022-05-03 16:51:09 +0000 | |
commit | 7092e268641fe57541a34fd34a41185bb20ee73c (patch) | |
tree | caf5f1e29db05a1b4fcbc44532033acf48721a86 | |
parent | 5d7e9601786b48e3b944c59493a8d3a982907479 (diff) |
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
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 6 | ||||
-rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 19 |
2 files changed, 23 insertions, 2 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 1cc4589eb9..5d8df5fdf0 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -1421,8 +1421,10 @@ void InputDispatcher::dispatchPointerCaptureChangedLocked( // Enable Pointer Capture. if (haveWindowWithPointerCapture && (entry->pointerCaptureRequest == mCurrentPointerCaptureRequest)) { - LOG_ALWAYS_FATAL("This request to enable Pointer Capture has already been dispatched " - "to the window."); + // This can happen if pointer capture is disabled and re-enabled before we notify the + // 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) { // This can happen if a window requests capture and immediately releases capture. diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index a167271c4d..b688898022 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -5671,6 +5671,25 @@ TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) 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 { protected: constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8; |