diff options
author | 2025-02-24 22:28:09 +0000 | |
---|---|---|
committer | 2025-03-18 19:37:13 +0000 | |
commit | 6f9ad7737cb27c4c0ec06d3c6c4c5a1f10c15263 (patch) | |
tree | 3c18622738897852732a54a8c00816c750b0ef26 | |
parent | 727cbc09e054a64b639a878b60c7c288b4bb2d1e (diff) |
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
-rw-r--r-- | services/inputflinger/reader/EventHub.cpp | 26 | ||||
-rw-r--r-- | services/inputflinger/reader/InputReader.cpp | 1 | ||||
-rw-r--r-- | 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<RawEvent> 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> 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<std::string> 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<std::shared_ptr<const AssociatedDevice>, 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 <batteryservice/BatteryService.h> #include <ftl/flags.h> +#include <input/BlockingQueue.h> #include <input/Input.h> #include <input/InputDevice.h> #include <input/KeyCharacterMap.h> @@ -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<std::string> mChangedSysfsNodeNotifications; }; } // namespace android |