summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Prabir Pradhan <prabirmsp@google.com> 2022-05-03 16:51:09 +0000
committer Prabir Pradhan <prabirmsp@google.com> 2022-05-03 16:51:09 +0000
commit7092e268641fe57541a34fd34a41185bb20ee73c (patch)
treecaf5f1e29db05a1b4fcbc44532033acf48721a86
parent5d7e9601786b48e3b944c59493a8d3a982907479 (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.cpp6
-rw-r--r--services/inputflinger/tests/InputDispatcher_test.cpp19
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;