Add test to verify external stylus connection does not interrupt touch
Bug: 291746265
Test: atest inputflinger_tests
Change-Id: I8f183fab2862001c152ff1e8149eddb29a084688
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 477beaf..1514096 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -1356,6 +1356,7 @@
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyInputDevicesChangedWasCalled());
ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
+ mTestListener->clearNotifyDeviceResetCalls();
}
void TearDown() override {
@@ -1828,6 +1829,57 @@
ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertStylusGestureNotified(mDeviceInfo.getId()));
}
+TEST_F(TouchIntegrationTest, ExternalStylusConnectedDuringTouchGesture) {
+ ASSERT_NO_FATAL_FAILURE(
+ mTestListener->assertNotifyDeviceResetWasCalled(WithDeviceId(mDeviceInfo.getId())));
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyDeviceResetWasNotCalled());
+ const Point centerPoint = mDevice->getCenterPoint();
+
+ // Down
+ mDevice->sendSlot(FIRST_SLOT);
+ mDevice->sendTrackingId(FIRST_TRACKING_ID);
+ mDevice->sendDown(centerPoint);
+ mDevice->sendSync();
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_DOWN)));
+
+ // Move
+ mDevice->sendMove(centerPoint + Point(1, 1));
+ mDevice->sendSync();
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
+
+ // Connecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
+ auto externalStylus = createUinputDevice<UinputExternalStylus>();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
+ const auto stylusInfo = findDeviceByName(externalStylus->getName());
+ ASSERT_TRUE(stylusInfo);
+ ASSERT_NO_FATAL_FAILURE(
+ mTestListener->assertNotifyDeviceResetWasCalled(WithDeviceId(stylusInfo->getId())));
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyDeviceResetWasNotCalled());
+
+ // Move
+ mDevice->sendMove(centerPoint + Point(2, 2));
+ mDevice->sendSync();
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasCalled(
+ WithMotionAction(AMOTION_EVENT_ACTION_MOVE)));
+
+ // Disconnecting an external stylus mid-gesture should not interrupt the ongoing gesture stream.
+ externalStylus.reset();
+ ASSERT_NO_FATAL_FAILURE(mFakePolicy->assertInputDevicesChanged());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyConfigurationChangedWasCalled());
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
+
+ // Up
+ mDevice->sendUp();
+ mDevice->sendSync();
+ ASSERT_NO_FATAL_FAILURE(
+ mTestListener->assertNotifyMotionWasCalled(WithMotionAction(AMOTION_EVENT_ACTION_UP)));
+
+ ASSERT_NO_FATAL_FAILURE(mTestListener->assertNotifyMotionWasNotCalled());
+}
+
// --- StylusButtonIntegrationTest ---
// Verify the behavior of button presses reported by various kinds of styluses, including buttons
diff --git a/services/inputflinger/tests/TestInputListener.cpp b/services/inputflinger/tests/TestInputListener.cpp
index fc917dd..41e250f 100644
--- a/services/inputflinger/tests/TestInputListener.cpp
+++ b/services/inputflinger/tests/TestInputListener.cpp
@@ -57,6 +57,18 @@
"Expected notifyDeviceReset() to have been called."));
}
+void TestInputListener::clearNotifyDeviceResetCalls() {
+ std::scoped_lock<std::mutex> lock(mLock);
+ std::get<std::vector<NotifyDeviceResetArgs>>(mQueues).clear();
+}
+
+void TestInputListener::assertNotifyDeviceResetWasCalled(
+ const ::testing::Matcher<NotifyDeviceResetArgs>& matcher) {
+ NotifyDeviceResetArgs outEventArgs;
+ ASSERT_NO_FATAL_FAILURE(assertNotifyDeviceResetWasCalled(&outEventArgs));
+ ASSERT_THAT(outEventArgs, matcher);
+}
+
void TestInputListener::assertNotifyDeviceResetWasNotCalled() {
ASSERT_NO_FATAL_FAILURE(
assertNotCalled<NotifyDeviceResetArgs>("notifyDeviceReset() should not be called."));
diff --git a/services/inputflinger/tests/TestInputListener.h b/services/inputflinger/tests/TestInputListener.h
index deb6048..3c5e014 100644
--- a/services/inputflinger/tests/TestInputListener.h
+++ b/services/inputflinger/tests/TestInputListener.h
@@ -43,6 +43,10 @@
void assertNotifyConfigurationChangedWasNotCalled();
+ void clearNotifyDeviceResetCalls();
+
+ void assertNotifyDeviceResetWasCalled(const ::testing::Matcher<NotifyDeviceResetArgs>& matcher);
+
void assertNotifyDeviceResetWasCalled(NotifyDeviceResetArgs* outEventArgs = nullptr);
void assertNotifyDeviceResetWasNotCalled();
diff --git a/services/inputflinger/tests/TestInputListenerMatchers.h b/services/inputflinger/tests/TestInputListenerMatchers.h
index 020ea86..183383f 100644
--- a/services/inputflinger/tests/TestInputListenerMatchers.h
+++ b/services/inputflinger/tests/TestInputListenerMatchers.h
@@ -139,6 +139,10 @@
return mDeviceId == args.deviceId;
}
+ bool MatchAndExplain(const NotifyDeviceResetArgs& args, std::ostream*) const {
+ return mDeviceId == args.deviceId;
+ }
+
bool MatchAndExplain(const InputEvent& event, std::ostream*) const {
return mDeviceId == event.getDeviceId();
}