Add associated function to physical keyboard
The function keys (HOME/BACK/DPAD...) may not always be virtual keys,
so we need provide a static input mapping mechanism to the physical
keyboard to make sure key events can dispatch to the corresponding
display.
- Find the associated viewport for keyboard when display info changed
and has an associated display port specified.
- Should disable the input device when an associated port specified but
no display viewport found.
- Changed getAssociatedDisplay -> getAssociatedDisplayId.
- Add test cases to test input device and keyboard associated mapping.
Bug: 137693244
Test: atest -a libinput_tests inputflinger_tests
Change-Id: If218f55645a78a4b50cec92b35b0dbae641dd1a1
diff --git a/services/inputflinger/InputReader.cpp b/services/inputflinger/InputReader.cpp
index 4631bec..1cbf78e 100644
--- a/services/inputflinger/InputReader.cpp
+++ b/services/inputflinger/InputReader.cpp
@@ -819,14 +819,19 @@
}
InputDevice* device = mDevices.valueAt(deviceIndex);
- std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplay();
+ if (!device->isEnabled()) {
+ ALOGW("Ignoring disabled device %s", device->getName().c_str());
+ return false;
+ }
+
+ std::optional<int32_t> associatedDisplayId = device->getAssociatedDisplayId();
// No associated display. By default, can dispatch to all displays.
if (!associatedDisplayId) {
return true;
}
if (*associatedDisplayId == ADISPLAY_ID_NONE) {
- ALOGW("Device has associated, but no associated display id.");
+ ALOGW("Device %s is associated with display ADISPLAY_ID_NONE.", device->getName().c_str());
return true;
}
@@ -1002,6 +1007,13 @@
}
void InputDevice::setEnabled(bool enabled, nsecs_t when) {
+ if (enabled && mAssociatedDisplayPort && !mAssociatedViewport) {
+ ALOGW("Cannot enable input device %s because it is associated with port %" PRIu8 ", "
+ "but the corresponding viewport is not found",
+ getName().c_str(), *mAssociatedDisplayPort);
+ enabled = false;
+ }
+
if (isEnabled() == enabled) {
return;
}
@@ -1103,6 +1115,7 @@
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
// In most situations, no port will be specified.
mAssociatedDisplayPort = std::nullopt;
+ mAssociatedViewport = std::nullopt;
// Find the display port that corresponds to the current input port.
const std::string& inputPort = mIdentifier.location;
if (!inputPort.empty()) {
@@ -1112,6 +1125,23 @@
mAssociatedDisplayPort = std::make_optional(displayPort->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
+ // explicitly disabled, then enable/disable the device based on whether we can find the
+ // corresponding viewport.
+ bool enabled = (config->disabledDevices.find(mId) == config->disabledDevices.end());
+ if (mAssociatedDisplayPort) {
+ mAssociatedViewport = config->getDisplayViewportByPort(*mAssociatedDisplayPort);
+ if (!mAssociatedViewport) {
+ ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
+ "but the corresponding viewport is not found.",
+ getName().c_str(), *mAssociatedDisplayPort);
+ enabled = false;
+ }
+ }
+
+ setEnabled(enabled, when);
}
for (InputMapper* mapper : mMappers) {
@@ -1276,9 +1306,15 @@
mContext->getListener()->notifyDeviceReset(&args);
}
-std::optional<int32_t> InputDevice::getAssociatedDisplay() {
+std::optional<int32_t> InputDevice::getAssociatedDisplayId() {
+ // Check if we had associated to the specific display.
+ if (mAssociatedViewport) {
+ return mAssociatedViewport->displayId;
+ }
+
+ // No associated display port, check if some InputMapper is associated.
for (InputMapper* mapper : mMappers) {
- std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplay();
+ std::optional<int32_t> associatedDisplayId = mapper->getAssociatedDisplayId();
if (associatedDisplayId) {
return associatedDisplayId;
}
@@ -2229,6 +2265,22 @@
dump += StringPrintf(INDENT3 "DownTime: %" PRId64 "\n", mDownTime);
}
+std::optional<DisplayViewport> KeyboardInputMapper::findViewport(
+ nsecs_t when, const InputReaderConfiguration* config) {
+ const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
+ if (displayPort) {
+ // Find the viewport that contains the same port
+ return mDevice->getAssociatedViewport();
+ }
+
+ // No associated display defined, try to find default display if orientationAware.
+ if (mParameters.orientationAware) {
+ return config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
+ }
+
+ return std::nullopt;
+}
+
void KeyboardInputMapper::configure(nsecs_t when,
const InputReaderConfiguration* config, uint32_t changes) {
InputMapper::configure(when, config, changes);
@@ -2239,9 +2291,7 @@
}
if (!changes || (changes & InputReaderConfiguration::CHANGE_DISPLAY_INFO)) {
- if (mParameters.orientationAware) {
- mViewport = config->getDisplayViewportByType(ViewportType::VIEWPORT_INTERNAL);
- }
+ mViewport = findViewport(when, config);
}
}
@@ -2521,6 +2571,12 @@
}
}
+std::optional<int32_t> KeyboardInputMapper::getAssociatedDisplayId() {
+ if (mViewport) {
+ return std::make_optional(mViewport->displayId);
+ }
+ return std::nullopt;
+}
// --- CursorInputMapper ---
@@ -2935,7 +2991,7 @@
}
}
-std::optional<int32_t> CursorInputMapper::getAssociatedDisplay() {
+std::optional<int32_t> CursorInputMapper::getAssociatedDisplayId() {
if (mParameters.hasAssociatedDisplay) {
if (mParameters.mode == Parameters::MODE_POINTER) {
return std::make_optional(mPointerController->getDisplayId());
@@ -3467,15 +3523,10 @@
const std::optional<uint8_t> displayPort = mDevice->getAssociatedDisplayPort();
if (displayPort) {
// Find the viewport that contains the same port
- std::optional<DisplayViewport> v = mConfig.getDisplayViewportByPort(*displayPort);
- if (!v) {
- ALOGW("Input device %s should be associated with display on port %" PRIu8 ", "
- "but the corresponding viewport is not found.",
- getDeviceName().c_str(), *displayPort);
- }
- return v;
+ return mDevice->getAssociatedViewport();
}
+ // Check if uniqueDisplayId is specified in idc file.
if (!mParameters.uniqueDisplayId.empty()) {
return mConfig.getDisplayViewportByUniqueId(mParameters.uniqueDisplayId);
}
@@ -3499,6 +3550,7 @@
return viewport;
}
+ // No associated display, return a non-display viewport.
DisplayViewport newViewport;
// Raw width and height in the natural orientation.
int32_t rawWidth = mRawPointerAxes.getRawWidth();
@@ -6508,7 +6560,7 @@
if (mDeviceMode == DEVICE_MODE_POINTER) {
mPointerController->getPosition(&xCursorPosition, &yCursorPosition);
}
- const int32_t displayId = getAssociatedDisplay().value_or(ADISPLAY_ID_NONE);
+ const int32_t displayId = getAssociatedDisplayId().value_or(ADISPLAY_ID_NONE);
const int32_t deviceId = getDeviceId();
std::vector<TouchVideoFrame> frames = mDevice->getEventHub()->getVideoFrames(deviceId);
std::for_each(frames.begin(), frames.end(),
@@ -6817,7 +6869,7 @@
return true;
}
-std::optional<int32_t> TouchInputMapper::getAssociatedDisplay() {
+std::optional<int32_t> TouchInputMapper::getAssociatedDisplayId() {
if (mParameters.hasAssociatedDisplay) {
if (mDeviceMode == DEVICE_MODE_POINTER) {
return std::make_optional(mPointerController->getDisplayId());