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

Commit 72382399 authored by Prabir Pradhan's avatar Prabir Pradhan Committed by Android (Google) Code Review
Browse files

Merge changes from topic "getSysfsRootPath" into main

* changes:
  EventHub: Re-open Devices serially when AssociatedDevice changes
  InputReader: Add getter API for the sysfs node path of an InputDevice
parents 026a1676 a8f88542
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -443,6 +443,9 @@ public:
    /* Get the Bluetooth address of an input device, if known. */
    virtual std::optional<std::string> getBluetoothAddress(int32_t deviceId) const = 0;

    /* Gets the sysfs root path for this device. Returns an empty path if there is none. */
    virtual std::filesystem::path getSysfsRootPath(int32_t deviceId) const = 0;

    /* Sysfs node change reported. Recreate device if required to incorporate the new sysfs nodes */
    virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;

+106 −61
Original line number Diff line number Diff line
@@ -246,7 +246,7 @@ static nsecs_t processEventTimestamp(const struct input_event& event) {
/**
 * Returns the sysfs root path of the input device.
 */
static std::optional<std::filesystem::path> getSysfsRootPath(const char* devicePath) {
static std::optional<std::filesystem::path> getSysfsRootForEvdevDevicePath(const char* devicePath) {
    std::error_code errorCode;

    // Stat the device path to get the major and minor number of the character file
@@ -1619,7 +1619,7 @@ void EventHub::assignDescriptorLocked(InputDeviceIdentifier& identifier) {
std::shared_ptr<const EventHub::AssociatedDevice> EventHub::obtainAssociatedDeviceLocked(
        const std::filesystem::path& devicePath, const std::shared_ptr<PropertyMap>& config) const {
    const std::optional<std::filesystem::path> sysfsRootPathOpt =
            getSysfsRootPath(devicePath.c_str());
            getSysfsRootForEvdevDevicePath(devicePath.c_str());
    if (!sysfsRootPathOpt) {
        return nullptr;
    }
@@ -1899,10 +1899,31 @@ std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {

        handleSysfsNodeChangeNotificationsLocked();

        // Use a do-while loop to ensure that we drain the closing and opening devices loop
        // at least once, even if there are no devices to re-open.
        do {
            if (!mDeviceIdsToReopen.empty()) {
                // If there are devices that need to be re-opened, ensure that we re-open them
                // one at a time to send the DEVICE_REMOVED and DEVICE_ADDED notifications for
                // each before moving on to the next. This is to avoid notifying all device
                // removals and additions in one batch, which could cause additional unnecessary
                // device added/removed notifications for merged InputDevices from InputReader.
                const int32_t deviceId = mDeviceIdsToReopen.back();
                mDeviceIdsToReopen.erase(mDeviceIdsToReopen.end() - 1);
                if (auto it = mDevices.find(deviceId); it != mDevices.end()) {
                    ALOGI("Reopening input device: id=%d, name=%s", it->second->id,
                          it->second->identifier.name.c_str());
                    const auto path = it->second->path;
                    closeDeviceLocked(*it->second);
                    openDeviceLocked(path);
                }
            }

            // 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);
            ALOGV("Reporting device closed: id=%d, name=%s\n", device->id, device->path.c_str());
                ALOGV("Reporting device closed: id=%d, name=%s\n", device->id,
                      device->path.c_str());
                const int32_t deviceId = (device->id == mBuiltInKeyboardId)
                        ? ReservedInputDeviceId::BUILT_IN_KEYBOARD_ID
                        : device->id;
@@ -1925,7 +1946,8 @@ std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
            while (!mOpeningDevices.empty()) {
                std::unique_ptr<Device> device = std::move(*mOpeningDevices.rbegin());
                mOpeningDevices.pop_back();
            ALOGV("Reporting device opened: id=%d, name=%s\n", device->id, device->path.c_str());
                ALOGV("Reporting device opened: id=%d, name=%s\n", device->id,
                      device->path.c_str());
                const int32_t deviceId = device->id == mBuiltInKeyboardId ? 0 : device->id;
                events.push_back({
                        .when = now,
@@ -1953,6 +1975,13 @@ std::vector<RawEvent> EventHub::getEvents(int timeoutMillis) {
                }
            }

            // Perform this loop of re-opening devices so that we re-open one device at a time.
        } while (!mDeviceIdsToReopen.empty());

        if (events.size() == EVENT_BUFFER_SIZE) {
            break;
        }

        // Grab the next input event.
        bool deviceChanged = false;
        while (mPendingEventIndex < mPendingEventCount) {
@@ -2666,6 +2695,18 @@ status_t EventHub::disableDevice(int32_t deviceId) {
    return device->disable();
}

std::filesystem::path EventHub::getSysfsRootPath(int32_t deviceId) const {
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    if (device == nullptr) {
        ALOGE("Invalid device id=%" PRId32 " provided to %s", deviceId, __func__);
        return {};
    }

    return device->associatedDevice ? device->associatedDevice->sysfsRootPath
                                    : std::filesystem::path{};
}

// TODO(b/274755573): Shift to uevent handling on native side and remove this method
// Currently using Java UEventObserver to trigger this which uses UEvent infrastructure that uses a
// NETLINK socket to observe UEvents. We can create similar infrastructure on Eventhub side to
@@ -2688,8 +2729,10 @@ void EventHub::handleSysfsNodeChangeNotificationsLocked() {

    // Testing whether a sysfs node changed involves several syscalls, so use a cache to avoid
    // testing the same node multiple times.
    // TODO(b/281822656): Notify InputReader separately when an AssociatedDevice changes,
    //  instead of needing to re-open all of Devices that are associated with it.
    std::map<std::shared_ptr<const AssociatedDevice>, bool /*changed*/> testedDevices;
    auto isAssociatedDeviceChanged = [&testedDevices, &changedNodes](const Device& dev) {
    auto shouldReopenDevice = [&testedDevices, &changedNodes](const Device& dev) {
        if (!dev.associatedDevice) {
            return false;
        }
@@ -2710,31 +2753,33 @@ void EventHub::handleSysfsNodeChangeNotificationsLocked() {
        auto reloadedDevice = AssociatedDevice(dev.associatedDevice->sysfsRootPath,
                                               dev.associatedDevice->baseDevConfig);
        const bool changed = *dev.associatedDevice != reloadedDevice;
        if (changed) {
            ALOGI("sysfsNodeChanged: Identified change in sysfs nodes for device: %s",
                  dev.identifier.name.c_str());
        }
        testedDevices.emplace(dev.associatedDevice, changed);
        return changed;
    };

    std::set<Device*> devicesToReopen;

    // Check in opening devices.
    // Check in opening devices. These can be re-opened directly because we have not yet notified
    // the Reader about these devices.
    for (const auto& dev : mOpeningDevices) {
        if (isAssociatedDeviceChanged(*dev)) {
            devicesToReopen.emplace(dev.get());
        if (shouldReopenDevice(*dev)) {
            ALOGI("Reopening input device from mOpeningDevices: id=%d, name=%s", dev->id,
                  dev->identifier.name.c_str());
            const auto path = dev->path;
            closeDeviceLocked(*dev); // The Device object is deleted by this function.
            openDeviceLocked(path);
        }
    }

    // Check in already added devices.
    // Check in already added devices. Add them to the re-opening list so they can be
    // re-opened serially.
    for (const auto& [id, dev] : mDevices) {
        if (isAssociatedDeviceChanged(*dev)) {
            devicesToReopen.emplace(dev.get());
        if (shouldReopenDevice(*dev)) {
            mDeviceIdsToReopen.emplace_back(dev->id);
        }
    }

    for (auto* device : devicesToReopen) {
        const auto path = device->path;
        closeDeviceLocked(*device); // The Device object is deleted by this function.
        openDeviceLocked(path);
    }
}

void EventHub::createVirtualKeyboardLocked() {
+6 −0
Original line number Diff line number Diff line
@@ -136,6 +136,8 @@ void InputDevice::dump(std::string& dump, const std::string& eventHubDevStr) {
    } else {
        dump += "<none>\n";
    }
    dump += StringPrintf(INDENT2 "SysfsRootPath:     %s\n",
                         mSysfsRootPath.empty() ? "<none>" : mSysfsRootPath.c_str());
    dump += StringPrintf(INDENT2 "HasMic:     %s\n", toString(mHasMic));
    dump += StringPrintf(INDENT2 "Sources: %s\n",
                         inputEventSourceToString(deviceInfo.getSources()).c_str());
@@ -195,6 +197,10 @@ void InputDevice::addEmptyEventHubDevice(int32_t eventHubId) {
    DevicePair& devicePair = mDevices[eventHubId];
    devicePair.second = createMappers(*devicePair.first, readerConfig);

    if (mSysfsRootPath.empty()) {
        mSysfsRootPath = devicePair.first->getSysfsRootPath();
    }

    // Must change generation to flag this device as changed
    bumpGeneration();
    return out;
+10 −0
Original line number Diff line number Diff line
@@ -917,6 +917,16 @@ bool InputReader::canDispatchToDisplay(int32_t deviceId, ui::LogicalDisplayId di
    return *associatedDisplayId == displayId;
}

std::filesystem::path InputReader::getSysfsRootPath(int32_t deviceId) const {
    std::scoped_lock _l(mLock);

    const InputDevice* device = findInputDeviceLocked(deviceId);
    if (!device) {
        return {};
    }
    return device->getSysfsRootPath();
}

void InputReader::sysfsNodeChanged(const std::string& sysfsNodePath) {
    mEventHub->sysfsNodeChanged(sysfsNodePath);
    mEventHub->wake();
+6 −0
Original line number Diff line number Diff line
@@ -399,6 +399,9 @@ public:
    /* Disable an input device. Closes file descriptor to that device. */
    virtual status_t disableDevice(int32_t deviceId) = 0;

    /* Gets the sysfs root path for this device. Returns an empty path if there is none. */
    virtual std::filesystem::path getSysfsRootPath(int32_t deviceId) const = 0;

    /* Sysfs node changed. Reopen the Eventhub device if any new Peripheral like Light, Battery,
     * etc. is detected. */
    virtual void sysfsNodeChanged(const std::string& sysfsNodePath) = 0;
@@ -614,6 +617,8 @@ public:

    status_t disableDevice(int32_t deviceId) override final;

    std::filesystem::path getSysfsRootPath(int32_t deviceId) const override final;

    void sysfsNodeChanged(const std::string& sysfsNodePath) override final;

    bool setKernelWakeEnabled(int32_t deviceId, bool enabled) override final;
@@ -810,6 +815,7 @@ private:
    bool mNeedToReopenDevices;
    bool mNeedToScanDevices;
    std::vector<std::string> mExcludedDevices;
    std::vector<int32_t> mDeviceIdsToReopen;

    int mEpollFd;
    int mINotifyFd;
Loading