diff options
-rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 69 | ||||
-rw-r--r-- | services/inputflinger/reader/include/EventHub.h | 1 |
2 files changed, 44 insertions, 26 deletions
diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index cc105bdf24..3c8b6f54c1 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -1654,10 +1654,6 @@ EventHub::AssociatedDevice::AssociatedDevice(const std::filesystem::path& sysfsR lightInfos(readLightsConfiguration(sysfsRootPath)), layoutInfo(readLayoutConfiguration(sysfsRootPath)) {} -bool EventHub::AssociatedDevice::isChanged() const { - return AssociatedDevice(sysfsRootPath) != *this; -} - std::string EventHub::AssociatedDevice::dump() const { return StringPrintf("path=%s, numBatteries=%zu, numLight=%zu", sysfsRootPath.c_str(), batteryInfos.size(), lightInfos.size()); @@ -2652,33 +2648,56 @@ status_t EventHub::disableDevice(int32_t deviceId) { void EventHub::sysfsNodeChanged(const std::string& sysfsNodePath) { std::scoped_lock _l(mLock); - // Check in opening devices - for (auto it = mOpeningDevices.begin(); it != mOpeningDevices.end(); it++) { - std::unique_ptr<Device>& device = *it; - if (device->associatedDevice && - sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) != - std::string::npos && - device->associatedDevice->isChanged()) { - it = mOpeningDevices.erase(it); - openDeviceLocked(device->path); + // Testing whether a sysfs node changed involves several syscalls, so use a cache to avoid + // testing the same node multiple times. + std::map<std::shared_ptr<const AssociatedDevice>, bool /*changed*/> testedDevices; + auto isAssociatedDeviceChanged = [&testedDevices, &sysfsNodePath](const Device& dev) { + if (!dev.associatedDevice) { + return false; } - } + if (auto testedIt = testedDevices.find(dev.associatedDevice); + testedIt != testedDevices.end()) { + return testedIt->second; + } + // Cache miss + if (sysfsNodePath.find(dev.associatedDevice->sysfsRootPath.string()) == std::string::npos) { + testedDevices.emplace(dev.associatedDevice, false); + return false; + } + auto reloadedDevice = AssociatedDevice(dev.associatedDevice->sysfsRootPath); + const bool changed = *dev.associatedDevice != reloadedDevice; + testedDevices.emplace(dev.associatedDevice, changed); + return changed; + }; - // Check in already added device - std::vector<Device*> devicesToReopen; - for (const auto& [id, device] : mDevices) { - if (device->associatedDevice && - sysfsNodePath.find(device->associatedDevice->sysfsRootPath.string()) != - std::string::npos && - device->associatedDevice->isChanged()) { - devicesToReopen.push_back(device.get()); + std::set<Device*> devicesToClose; + std::set<std::string /*path*/> devicesToOpen; + + // Check in opening devices. If its associated device changed, + // the device should be removed from mOpeningDevices and needs to be opened again. + std::erase_if(mOpeningDevices, [&](const auto& dev) { + if (isAssociatedDeviceChanged(*dev)) { + devicesToOpen.emplace(dev->path); + return true; + } + return false; + }); + + // Check in already added device. If its associated device changed, + // the device needs to be re-opened. + for (const auto& [id, dev] : mDevices) { + if (isAssociatedDeviceChanged(*dev)) { + devicesToOpen.emplace(dev->path); + devicesToClose.emplace(dev.get()); } } - for (const auto& device : devicesToReopen) { + + for (auto* device : devicesToClose) { closeDeviceLocked(*device); - openDeviceLocked(device->path); } - devicesToReopen.clear(); + for (const auto& path : devicesToOpen) { + openDeviceLocked(path); + } } void EventHub::createVirtualKeyboardLocked() { diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index 8109dae715..31ac63f31e 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -626,7 +626,6 @@ private: std::unordered_map<int32_t /*lightId*/, RawLightInfo> lightInfos; std::optional<RawLayoutInfo> layoutInfo; - bool isChanged() const; bool operator==(const AssociatedDevice&) const = default; bool operator!=(const AssociatedDevice&) const = default; std::string dump() const; |