Use input token in PointerCaptureRequest
Instead of sending boolean to indicate the capture state,
InputDispatcher now sends an input window token that requests a
pointer capture, or nullptr otherwise.
This is useful for some InputReader implementations.
Also, this token can be used to verify if a pointer capture changed
event from a reader is valid.
Bug: 259346762
Bug: 301628662
Test: inputflinger_tests
Test: android.view.cts.PointerCaptureTest WindowFocusTests#testPointerCapture
Change-Id: Ie8343db6744dc2080f7f1dcff5a630be5c87fa3e
diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp
index 60d598f..55d5f13 100644
--- a/services/inputflinger/tests/InputDispatcher_test.cpp
+++ b/services/inputflinger/tests/InputDispatcher_test.cpp
@@ -308,17 +308,22 @@
"signal";
}
- PointerCaptureRequest assertSetPointerCaptureCalled(bool enabled) {
+ PointerCaptureRequest assertSetPointerCaptureCalled(const sp<WindowInfoHandle>& window,
+ bool enabled) {
std::unique_lock lock(mLock);
base::ScopedLockAssertion assumeLocked(mLock);
- if (!mPointerCaptureChangedCondition.wait_for(lock, 100ms,
- [this, enabled]() REQUIRES(mLock) {
- return mPointerCaptureRequest->enable ==
- enabled;
- })) {
- ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << enabled
- << ") to be called.";
+ if (!mPointerCaptureChangedCondition
+ .wait_for(lock, 100ms, [this, enabled, window]() REQUIRES(mLock) {
+ if (enabled) {
+ return mPointerCaptureRequest->isEnable() &&
+ mPointerCaptureRequest->window == window->getToken();
+ } else {
+ return !mPointerCaptureRequest->isEnable();
+ }
+ })) {
+ ADD_FAILURE() << "Timed out waiting for setPointerCapture(" << window->getName() << ", "
+ << enabled << ") to be called.";
return {};
}
auto request = *mPointerCaptureRequest;
@@ -333,7 +338,7 @@
if (mPointerCaptureChangedCondition.wait_for(lock, 100ms) != std::cv_status::timeout) {
FAIL() << "Expected setPointerCapture(request) to not be called, but was called. "
"enabled = "
- << std::to_string(mPointerCaptureRequest->enable);
+ << std::to_string(mPointerCaptureRequest->isEnable());
}
mPointerCaptureRequest.reset();
}
@@ -9888,7 +9893,7 @@
PointerCaptureRequest requestAndVerifyPointerCapture(const sp<FakeWindowHandle>& window,
bool enabled) {
mDispatcher->requestPointerCapture(window->getToken(), enabled);
- auto request = mFakePolicy->assertSetPointerCaptureCalled(enabled);
+ auto request = mFakePolicy->assertSetPointerCaptureCalled(window, enabled);
notifyPointerCaptureChanged(request);
window->consumeCaptureEvent(enabled);
return request;
@@ -9921,7 +9926,7 @@
mWindow->consumeCaptureEvent(false);
mWindow->consumeFocusEvent(false);
mSecondWindow->consumeFocusEvent(true);
- mFakePolicy->assertSetPointerCaptureCalled(false);
+ mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
// Ensure that additional state changes from InputReader are not sent to the window.
notifyPointerCaptureChanged({});
@@ -9940,7 +9945,7 @@
notifyPointerCaptureChanged(request);
// Ensure that Pointer Capture is disabled.
- mFakePolicy->assertSetPointerCaptureCalled(false);
+ mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
mWindow->consumeCaptureEvent(false);
mWindow->assertNoEvents();
}
@@ -9950,13 +9955,13 @@
// The first window loses focus.
setFocusedWindow(mSecondWindow);
- mFakePolicy->assertSetPointerCaptureCalled(false);
+ mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
mWindow->consumeCaptureEvent(false);
// Request Pointer Capture from the second window before the notification from InputReader
// arrives.
mDispatcher->requestPointerCapture(mSecondWindow->getToken(), true);
- auto request = mFakePolicy->assertSetPointerCaptureCalled(true);
+ auto request = mFakePolicy->assertSetPointerCaptureCalled(mSecondWindow, true);
// InputReader notifies Pointer Capture was disabled (because of the focus change).
notifyPointerCaptureChanged({});
@@ -9971,11 +9976,11 @@
TEST_F(InputDispatcherPointerCaptureTests, EnableRequestFollowsSequenceNumbers) {
// App repeatedly enables and disables capture.
mDispatcher->requestPointerCapture(mWindow->getToken(), true);
- auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
+ auto firstRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
mDispatcher->requestPointerCapture(mWindow->getToken(), false);
- mFakePolicy->assertSetPointerCaptureCalled(false);
+ mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
mDispatcher->requestPointerCapture(mWindow->getToken(), true);
- auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
+ auto secondRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
// InputReader notifies that PointerCapture has been enabled for the first request. Since the
// first request is now stale, this should do nothing.
@@ -9992,10 +9997,10 @@
// App toggles pointer capture off and on.
mDispatcher->requestPointerCapture(mWindow->getToken(), false);
- mFakePolicy->assertSetPointerCaptureCalled(false);
+ mFakePolicy->assertSetPointerCaptureCalled(mWindow, false);
mDispatcher->requestPointerCapture(mWindow->getToken(), true);
- auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(true);
+ auto enableRequest = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
// InputReader notifies that the latest "enable" request was processed, while skipping over the
// preceding "disable" request.
@@ -10047,6 +10052,26 @@
mWindow->assertNoEvents();
}
+using InputDispatcherPointerCaptureDeathTest = InputDispatcherPointerCaptureTests;
+
+TEST_F(InputDispatcherPointerCaptureDeathTest,
+ NotifyPointerCaptureChangedWithWrongTokenAbortsDispatcher) {
+ testing::GTEST_FLAG(death_test_style) = "threadsafe";
+ ScopedSilentDeath _silentDeath;
+
+ mDispatcher->requestPointerCapture(mWindow->getToken(), true);
+ auto request = mFakePolicy->assertSetPointerCaptureCalled(mWindow, true);
+
+ // Dispatch a pointer changed event with a wrong token.
+ request.window = mSecondWindow->getToken();
+ ASSERT_DEATH(
+ {
+ notifyPointerCaptureChanged(request);
+ mSecondWindow->consumeCaptureEvent(true);
+ },
+ "Unexpected requested window for Pointer Capture.");
+}
+
class InputDispatcherUntrustedTouchesTest : public InputDispatcherTest {
protected:
constexpr static const float MAXIMUM_OBSCURING_OPACITY = 0.8;