Reconfigure device in TouchInputMapper when the type is changed.
A race condition may occur where the device type change is only
propagated after the device is created. In this case the device
should be fully reconfigured.
BUG: 262887935
Test: CtsHardwareTestCases:android.hardware.input.cts.tests.VirtualNavigationTouchpadTest
Change-Id: Iced2e2c5af2a6f33c1299f2d0d1c30ca36a62e3c
(cherry picked from commit 1588a2e58751a357b32102ab013a7e2ab996efad)
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 6fd4ff3..9fe652c 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -277,7 +277,11 @@
mHasMic = mClasses.test(InputDeviceClass::MIC);
if (!isIgnored()) {
- if (!changes) { // first time only
+ // Full configuration should happen the first time configure is called
+ // and when the device type is changed. Changing a device type can
+ // affect various other parameters so should result in a
+ // reconfiguration.
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_TYPE)) {
mConfiguration.clear();
for_each_subdevice([this](InputDeviceContext& context) {
PropertyMap configuration;
diff --git a/services/inputflinger/reader/mapper/TouchInputMapper.cpp b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
index 3ba6cd0..509c2e8 100644
--- a/services/inputflinger/reader/mapper/TouchInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/TouchInputMapper.cpp
@@ -293,7 +293,10 @@
mConfig = *config;
- if (!changes) { // first time only
+ // Full configuration should happen the first time configure is called and
+ // when the device type is changed. Changing a device type can affect
+ // various other parameters so should result in a reconfiguration.
+ if (!changes || (changes & InputReaderConfiguration::CHANGE_DEVICE_TYPE)) {
// Configure basic parameters.
configureParameters();
@@ -328,7 +331,8 @@
InputReaderConfiguration::CHANGE_POINTER_CAPTURE |
InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT |
InputReaderConfiguration::CHANGE_SHOW_TOUCHES |
- InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE))) {
+ InputReaderConfiguration::CHANGE_EXTERNAL_STYLUS_PRESENCE |
+ InputReaderConfiguration::CHANGE_DEVICE_TYPE))) {
// Configure device sources, display dimensions, orientation and
// scaling factors.
configureInputDevice(when, &resetNeeded);
diff --git a/services/inputflinger/tests/InputMapperTest.cpp b/services/inputflinger/tests/InputMapperTest.cpp
index a02ef05..ae30006 100644
--- a/services/inputflinger/tests/InputMapperTest.cpp
+++ b/services/inputflinger/tests/InputMapperTest.cpp
@@ -54,7 +54,8 @@
if (!changes ||
(changes &
(InputReaderConfiguration::CHANGE_DISPLAY_INFO |
- InputReaderConfiguration::CHANGE_POINTER_CAPTURE))) {
+ InputReaderConfiguration::CHANGE_POINTER_CAPTURE |
+ InputReaderConfiguration::CHANGE_DEVICE_TYPE))) {
mReader->requestRefreshConfiguration(changes);
mReader->loopOnce();
}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index fe7af80..1119f73 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -6724,6 +6724,29 @@
ASSERT_FALSE(fakePointerController->isPointerShown());
}
+TEST_F(SingleTouchInputMapperTest, WhenDeviceTypeIsChangedToTouchNavigation_updatesDeviceType) {
+ // Initialize the device without setting device source to touch navigation.
+ addConfigurationProperty("touch.deviceType", "touchScreen");
+ prepareDisplay(ui::ROTATION_0);
+ prepareButtons();
+ prepareAxes(POSITION);
+ SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
+
+ // Ensure that the device is created as a touchscreen, not touch navigation.
+ ASSERT_EQ(AINPUT_SOURCE_TOUCHSCREEN, mapper.getSources());
+
+ // Add device type association after the device was created.
+ mFakePolicy->addDeviceTypeAssociation(DEVICE_LOCATION, "touchNavigation");
+
+ // Send update to the mapper.
+ std::list<NotifyArgs> unused2 =
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::CHANGE_DEVICE_TYPE /*changes*/);
+
+ // Check whether device type update was successful.
+ ASSERT_EQ(AINPUT_SOURCE_TOUCH_NAVIGATION, mDevice->getSources());
+}
+
// --- TouchDisplayProjectionTest ---
class TouchDisplayProjectionTest : public SingleTouchInputMapperTest {