summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Prabir Pradhan <prabirmsp@google.com> 2025-02-24 22:28:09 +0000
committer Prabir Pradhan <prabirmsp@google.com> 2025-03-18 19:37:13 +0000
commit6f9ad7737cb27c4c0ec06d3c6c4c5a1f10c15263 (patch)
tree3c18622738897852732a54a8c00816c750b0ef26
parent727cbc09e054a64b639a878b60c7c288b4bb2d1e (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.cpp26
-rw-r--r--services/inputflinger/reader/InputReader.cpp1
-rw-r--r--services/inputflinger/reader/include/EventHub.h7
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