Check if input devices are opening
If input devices are opening, but not yet open, they will be sitting in
mOpeningDevices list and not in mDevices map.
Therefore, when pairing a video device, we should check both places.
This is needed because of a recent behaviour change where device can
only be in 1 place at a given time.
Bug: 165554458
Test: adb shell dumpsys input
Change-Id: Id44a2d7a6f8246dec26cb33c6d073d7f0c39e507
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp
index 76b9419..dda19c6 100644
--- a/services/inputflinger/reader/EventHub.cpp
+++ b/services/inputflinger/reader/EventHub.cpp
@@ -979,18 +979,30 @@
mNeedToSendFinishedDeviceScan = true;
}
- for (auto it = mOpeningDevices.begin(); it != mOpeningDevices.end();) {
- std::unique_ptr<Device> device = std::move(*it);
+ while (!mOpeningDevices.empty()) {
+ std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
+ mOpeningDevices.pop_back();
ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
event->when = now;
event->deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
event->type = DEVICE_ADDED;
event += 1;
- auto [dev_it, insert] = mDevices.insert_or_assign(device->id, std::move(device));
- if (!insert) {
+
+ // Try to find a matching video device by comparing device names
+ for (auto it = mUnattachedVideoDevices.begin(); it != mUnattachedVideoDevices.end();
+ it++) {
+ std::unique_ptr<TouchVideoDevice>& videoDevice = *it;
+ if (tryAddVideoDevice(*device, videoDevice)) {
+ // videoDevice was transferred to 'device'
+ it = mUnattachedVideoDevices.erase(it);
+ break;
+ }
+ }
+
+ auto [dev_it, inserted] = mDevices.insert_or_assign(device->id, std::move(device));
+ if (!inserted) {
ALOGW("Device id %d exists, replaced.", device->id);
}
- it = mOpeningDevices.erase(it);
mNeedToSendFinishedDeviceScan = true;
if (--capacity == 0) {
break;
@@ -1536,21 +1548,6 @@
device->setLedForControllerLocked();
}
- // Find a matching video device by comparing device names
- // This should be done before registerDeviceForEpollLocked, so that both fds are added to epoll
- for (std::unique_ptr<TouchVideoDevice>& videoDevice : mUnattachedVideoDevices) {
- if (device->identifier.name == videoDevice->getName()) {
- device->videoDevice = std::move(videoDevice);
- break;
- }
- }
- mUnattachedVideoDevices
- .erase(std::remove_if(mUnattachedVideoDevices.begin(), mUnattachedVideoDevices.end(),
- [](const std::unique_ptr<TouchVideoDevice>& videoDevice) {
- return videoDevice == nullptr;
- }),
- mUnattachedVideoDevices.end());
-
if (registerDeviceForEpollLocked(*device) != OK) {
return -1;
}
@@ -1576,12 +1573,8 @@
}
// Transfer ownership of this video device to a matching input device
for (const auto& [id, device] : mDevices) {
- if (videoDevice->getName() == device->identifier.name) {
- device->videoDevice = std::move(videoDevice);
- if (device->enabled) {
- registerVideoDeviceForEpollLocked(*device->videoDevice);
- }
- return;
+ if (tryAddVideoDevice(*device, videoDevice)) {
+ return; // 'device' now owns 'videoDevice'
}
}
@@ -1592,6 +1585,18 @@
mUnattachedVideoDevices.push_back(std::move(videoDevice));
}
+bool EventHub::tryAddVideoDevice(EventHub::Device& device,
+ std::unique_ptr<TouchVideoDevice>& videoDevice) {
+ if (videoDevice->getName() != device.identifier.name) {
+ return false;
+ }
+ device.videoDevice = std::move(videoDevice);
+ if (device.enabled) {
+ registerVideoDeviceForEpollLocked(*device.videoDevice);
+ }
+ return true;
+}
+
bool EventHub::isDeviceEnabled(int32_t deviceId) {
AutoMutex _l(mLock);
Device* device = getDeviceLocked(deviceId);
diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h
index ff12d98..fb0f19e 100644
--- a/services/inputflinger/reader/include/EventHub.h
+++ b/services/inputflinger/reader/include/EventHub.h
@@ -460,6 +460,14 @@
status_t openDeviceLocked(const std::string& devicePath);
void openVideoDeviceLocked(const std::string& devicePath);
+ /**
+ * Try to associate a video device with an input device. If the association succeeds,
+ * the videoDevice is moved into the input device. 'videoDevice' will become null if this
+ * happens.
+ * Return true if the association succeeds.
+ * Return false otherwise.
+ */
+ bool tryAddVideoDevice(Device& device, std::unique_ptr<TouchVideoDevice>& videoDevice);
void createVirtualKeyboardLocked();
void addDeviceLocked(std::unique_ptr<Device> device);
void assignDescriptorLocked(InputDeviceIdentifier& identifier);