Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6f9ad773 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

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
parent 727cbc09
Loading
Loading
Loading
Loading
+23 −3
Original line number Diff line number Diff line
@@ -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;
        }
+1 −0
Original line number Diff line number Diff line
@@ -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() {
+7 −0
Original line number Diff line number Diff line
@@ -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