Add dynamic display id associations for keyboards
Bug: 184615313
Test: atest -a inputflinger_tests and atest -a libinput_tests
Change-Id: I96eb6af186e001ff37d90db2436c7d60a269d4bf
diff --git a/services/inputflinger/include/InputReaderBase.h b/services/inputflinger/include/InputReaderBase.h
index 3bf212a..19abfd9 100644
--- a/services/inputflinger/include/InputReaderBase.h
+++ b/services/inputflinger/include/InputReaderBase.h
@@ -198,6 +198,10 @@
// Used to determine which DisplayViewport should be tied to which InputDevice.
std::unordered_map<std::string, uint8_t> portAssociations;
+ // The associations between input device names and display unique ids.
+ // Used to determine which DisplayViewport should be tied to which InputDevice.
+ std::unordered_map<std::string, std::string> uniqueIdAssociations;
+
// The suggested display ID to show the cursor.
int32_t defaultPointerDisplayId;
diff --git a/services/inputflinger/reader/InputDevice.cpp b/services/inputflinger/reader/InputDevice.cpp
index 8f75d22..ad503fd 100644
--- a/services/inputflinger/reader/InputDevice.cpp
+++ b/services/inputflinger/reader/InputDevice.cpp
@@ -103,6 +103,12 @@
} else {
dump += "<none>\n";
}
+ dump += StringPrintf(INDENT2 "AssociatedDisplayUniqueId: ");
+ if (mAssociatedDisplayUniqueId) {
+ dump += StringPrintf("%s\n", mAssociatedDisplayUniqueId->c_str());
+ } else {
+ dump += "<none>\n";
+ }
dump += StringPrintf(INDENT2 "HasMic: %s\n", toString(mHasMic));
dump += StringPrintf(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
dump += StringPrintf(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
@@ -293,8 +299,9 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- // In most situations, no port will be specified.
+ // In most situations, no port or name will be specified.
mAssociatedDisplayPort = std::nullopt;
+ mAssociatedDisplayUniqueId = std::nullopt;
mAssociatedViewport = std::nullopt;
// Find the display port that corresponds to the current input port.
const std::string& inputPort = mIdentifier.location;
@@ -305,6 +312,13 @@
mAssociatedDisplayPort = std::make_optional(displayPort->second);
}
}
+ const std::string& inputDeviceName = mIdentifier.name;
+ const std::unordered_map<std::string, std::string>& names =
+ config->uniqueIdAssociations;
+ const auto& displayUniqueId = names.find(inputDeviceName);
+ if (displayUniqueId != names.end()) {
+ mAssociatedDisplayUniqueId = displayUniqueId->second;
+ }
// If the device was explicitly disabled by the user, it would be present in the
// "disabledDevices" list. If it is associated with a specific display, and it was not
@@ -319,6 +333,15 @@
getName().c_str(), *mAssociatedDisplayPort);
enabled = false;
}
+ } else if (mAssociatedDisplayUniqueId != std::nullopt) {
+ mAssociatedViewport =
+ config->getDisplayViewportByUniqueId(*mAssociatedDisplayUniqueId);
+ if (!mAssociatedViewport) {
+ ALOGW("Input device %s should be associated with display %s but the "
+ "corresponding viewport cannot be found",
+ inputDeviceName.c_str(), mAssociatedDisplayUniqueId->c_str());
+ enabled = false;
+ }
}
if (changes) {
diff --git a/services/inputflinger/reader/include/InputDevice.h b/services/inputflinger/reader/include/InputDevice.h
index b2b23e5..291f105 100644
--- a/services/inputflinger/reader/include/InputDevice.h
+++ b/services/inputflinger/reader/include/InputDevice.h
@@ -169,6 +169,7 @@
uint32_t mSources;
bool mIsExternal;
std::optional<uint8_t> mAssociatedDisplayPort;
+ std::optional<std::string> mAssociatedDisplayUniqueId;
std::optional<DisplayViewport> mAssociatedViewport;
bool mHasMic;
bool mDropUntilNextSync;
diff --git a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
index 2c5a576..104d087 100644
--- a/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
+++ b/services/inputflinger/reader/mapper/KeyboardInputMapper.cpp
@@ -132,9 +132,7 @@
std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
nsecs_t when, const InputReaderConfiguration* config) {
- const std::optional<uint8_t> displayPort = getDeviceContext().getAssociatedDisplayPort();
- if (displayPort) {
- // Find the viewport that contains the same port
+ if (getDeviceContext().getAssociatedViewport()) {
return getDeviceContext().getAssociatedViewport();
}
diff --git a/services/inputflinger/tests/InputReader_test.cpp b/services/inputflinger/tests/InputReader_test.cpp
index 0e721e9..5eaca71 100644
--- a/services/inputflinger/tests/InputReader_test.cpp
+++ b/services/inputflinger/tests/InputReader_test.cpp
@@ -269,6 +269,11 @@
mConfig.portAssociations.insert({inputPort, displayPort});
}
+ void addInputUniqueIdAssociation(const std::string& inputUniqueId,
+ const std::string& displayUniqueId) {
+ mConfig.uniqueIdAssociations.insert({inputUniqueId, displayUniqueId});
+ }
+
void addDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.insert(deviceId); }
void removeDisabledDevice(int32_t deviceId) { mConfig.disabledDevices.erase(deviceId); }
@@ -2621,6 +2626,41 @@
ASSERT_FALSE(mDevice->isEnabled());
}
+TEST_F(InputDeviceTest, Configure_AssignsDisplayUniqueId) {
+ // Device should be enabled by default.
+ mFakePolicy->clearViewports();
+ mDevice->addMapper<FakeInputMapper>(EVENTHUB_ID, AINPUT_SOURCE_KEYBOARD);
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(), 0);
+ ASSERT_TRUE(mDevice->isEnabled());
+
+ // Device should be disabled because it is associated with a specific display, but the
+ // corresponding display is not found.
+ const std::string DISPLAY_UNIQUE_ID = "displayUniqueId";
+ mFakePolicy->addInputUniqueIdAssociation(DEVICE_NAME, DISPLAY_UNIQUE_ID);
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ ASSERT_FALSE(mDevice->isEnabled());
+
+ // Device should be enabled when a display is found.
+ mFakePolicy->addDisplayViewport(SECONDARY_DISPLAY_ID, DISPLAY_WIDTH, DISPLAY_HEIGHT,
+ DISPLAY_ORIENTATION_0, /* isActive= */ true, DISPLAY_UNIQUE_ID,
+ NO_PORT, ViewportType::INTERNAL);
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ ASSERT_TRUE(mDevice->isEnabled());
+
+ // Device should be disabled after set disable.
+ mFakePolicy->addDisabledDevice(mDevice->getId());
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::CHANGE_ENABLED_STATE);
+ ASSERT_FALSE(mDevice->isEnabled());
+
+ // Device should still be disabled even found the associated display.
+ mDevice->configure(ARBITRARY_TIME, mFakePolicy->getReaderConfiguration(),
+ InputReaderConfiguration::CHANGE_DISPLAY_INFO);
+ ASSERT_FALSE(mDevice->isEnabled());
+}
+
// --- InputMapperTest ---
class InputMapperTest : public testing::Test {
@@ -7853,8 +7893,6 @@
ASSERT_EQ(SECONDARY_DISPLAY_ID, args.displayId);
}
-
-
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
addConfigurationProperty("touch.deviceType", "touchScreen");
prepareDisplay(DISPLAY_ORIENTATION_0);