From 6f9ad7737cb27c4c0ec06d3c6c4c5a1f10c15263 Mon Sep 17 00:00:00 2001 From: Prabir Pradhan Date: Mon, 24 Feb 2025 22:28:09 +0000 Subject: EventHub: Process sysfs node changes from InputReader thread Before syfs node change notifications were processed by EventHub, all device openings and closings happened on the InputReader thread. The upper layer (InputReader) makes assumptions about EventHub Device states being synchronized with the notications of device additions and removals from EventHub to InputReader. The addition of sysfs node change processing moved some device openings and closings off of the InputReader thread, which can break the synchronization assumptions in InputReader. In this CL, we move sysfs node change processing to the InputReader thread. Bug: 397208968 Bug: 358694799 Test: Presubmit Flag: EXEMPT bug fix Change-Id: If6d70a12ddf74098c74b8360d31c4967ae6b3d03 --- services/inputflinger/reader/EventHub.cpp | 26 ++++++++++++++++++++++--- services/inputflinger/reader/InputReader.cpp | 1 + services/inputflinger/reader/include/EventHub.h | 7 +++++++ 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/services/inputflinger/reader/EventHub.cpp b/services/inputflinger/reader/EventHub.cpp index 08d51c32b5..784baea6f3 100644 --- a/services/inputflinger/reader/EventHub.cpp +++ b/services/inputflinger/reader/EventHub.cpp @@ -1897,6 +1897,8 @@ std::vector EventHub::getEvents(int timeoutMillis) { break; // return to the caller before we actually rescan } + handleSysfsNodeChangeNotificationsLocked(); + // Report any devices that had last been added/removed. for (auto it = mClosingDevices.begin(); it != mClosingDevices.end();) { std::unique_ptr device = std::move(*it); @@ -2669,12 +2671,25 @@ status_t EventHub::disableDevice(int32_t deviceId) { // NETLINK socket to observe UEvents. We can create similar infrastructure on Eventhub side to // directly observe UEvents instead of triggering from Java side. void EventHub::sysfsNodeChanged(const std::string& sysfsNodePath) { - std::scoped_lock _l(mLock); + mChangedSysfsNodeNotifications.emplace(sysfsNodePath); +} + +void EventHub::handleSysfsNodeChangeNotificationsLocked() { + // Use a set to de-dup any repeated notifications. + std::set changedNodes; + while (true) { + auto node = mChangedSysfsNodeNotifications.popWithTimeout(std::chrono::nanoseconds(0)); + if (!node.has_value()) break; + changedNodes.emplace(*node); + } + if (changedNodes.empty()) { + return; + } // Testing whether a sysfs node changed involves several syscalls, so use a cache to avoid // testing the same node multiple times. std::map, bool /*changed*/> testedDevices; - auto isAssociatedDeviceChanged = [&testedDevices, &sysfsNodePath](const Device& dev) { + auto isAssociatedDeviceChanged = [&testedDevices, &changedNodes](const Device& dev) { if (!dev.associatedDevice) { return false; } @@ -2683,7 +2698,12 @@ void EventHub::sysfsNodeChanged(const std::string& sysfsNodePath) { return testedIt->second; } // Cache miss - if (sysfsNodePath.find(dev.associatedDevice->sysfsRootPath.string()) == std::string::npos) { + const bool anyNodesChanged = + std::any_of(changedNodes.begin(), changedNodes.end(), [&](const std::string& node) { + return node.find(dev.associatedDevice->sysfsRootPath.string()) != + std::string::npos; + }); + if (!anyNodesChanged) { testedDevices.emplace(dev.associatedDevice, false); return false; } diff --git a/services/inputflinger/reader/InputReader.cpp b/services/inputflinger/reader/InputReader.cpp index 58df692b3e..f2f70c4a10 100644 --- a/services/inputflinger/reader/InputReader.cpp +++ b/services/inputflinger/reader/InputReader.cpp @@ -919,6 +919,7 @@ bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId di void InputReader::sysfsNodeChanged(const std::string& sysfsNodePath) { mEventHub->sysfsNodeChanged(sysfsNodePath); + mEventHub->wake(); } DeviceId InputReader::getLastUsedInputDeviceId() { diff --git a/services/inputflinger/reader/include/EventHub.h b/services/inputflinger/reader/include/EventHub.h index adbfdebfb0..913f8f8d1d 100644 --- a/services/inputflinger/reader/include/EventHub.h +++ b/services/inputflinger/reader/include/EventHub.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -775,6 +776,8 @@ private: void addDeviceInputInotify(); void addDeviceInotify(); + void handleSysfsNodeChangeNotificationsLocked() REQUIRES(mLock); + // Protect all internal state. mutable std::mutex mLock; @@ -824,6 +827,10 @@ private: size_t mPendingEventCount; size_t mPendingEventIndex; bool mPendingINotify; + + // The sysfs node change notifications that have been sent to EventHub. + // Enqueuing notifications does not require the lock to be held. + BlockingQueue mChangedSysfsNodeNotifications; }; } // namespace android -- cgit v1.2.3-59-g8ed1b