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

Commit 341d0787 authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

EventHub: Track the global abs axis states for enabled devices

Similar to what we have done for the global switch and key states, we
track the state and value of all ABS axes for each fd so that we no
longer have to use ioctls to query the value when upper layers request it.

This will help ensure that the device state remains synchronized between
the kernel and userspace, as the axis info will only need to be queried
once for each axis when the fd is opened.

Bug: 290938220
Bug: 261025260
Test: Presubmit
Change-Id: I622a20f27341b694140bb454bb1c744272d73183
parent 39d60aac
Loading
Loading
Loading
Loading
+62 −51
Original line number Diff line number Diff line
@@ -625,6 +625,36 @@ void EventHub::Device::readDeviceState() {
    if (readDeviceBitMask(EVIOCGSW(0), swState) < 0) {
        ALOGD("Unable to query the global switch state for %s: %s", path.c_str(), strerror(errno));
    }

    // Read absolute axis info and values for all available axes for the device.
    populateAbsoluteAxisStates();
}

void EventHub::Device::populateAbsoluteAxisStates() {
    absState.clear();

    for (int axis = 0; axis <= ABS_MAX; axis++) {
        if (!absBitmask.test(axis)) {
            continue;
        }
        struct input_absinfo info {};
        if (ioctl(fd, EVIOCGABS(axis), &info)) {
            ALOGE("Error reading absolute controller %d for device %s fd %d: %s", axis,
                  identifier.name.c_str(), fd, strerror(errno));
            continue;
        }
        if (info.minimum == info.maximum) {
            continue;
        }
        auto& [axisInfo, value] = absState[axis];
        axisInfo.valid = true;
        axisInfo.minValue = info.minimum;
        axisInfo.maxValue = info.maximum;
        axisInfo.flat = info.flat;
        axisInfo.fuzz = info.fuzz;
        axisInfo.resolution = info.resolution;
        value = info.value;
    }
}

bool EventHub::Device::hasKeycodeLocked(int keycode) const {
@@ -762,6 +792,15 @@ void EventHub::Device::trackInputEvent(const struct input_event& event) {
                                        .code.c_str());
            break;
        }
        case EV_ABS: {
            auto it = absState.find(event.code);
            LOG_ALWAYS_FATAL_IF(!currentFrameDropped && it == absState.end(),
                                "%s: received invalid EV_ABS event code: %s", __func__,
                                InputEventLookup::getLinuxEvdevLabel(EV_ABS, event.code, 0)
                                        .code.c_str());
            it->second.value = event.value;
            break;
        }
        case EV_SYN: {
            switch (event.code) {
                case SYN_REPORT:
@@ -919,30 +958,6 @@ void EventHub::addDeviceInotify() {
                        strerror(errno));
}

void EventHub::populateDeviceAbsoluteAxisInfo(Device& device) {
    for (int axis = 0; axis <= ABS_MAX; axis++) {
        if (!device.absBitmask.test(axis)) {
            continue;
        }
        struct input_absinfo info {};
        if (ioctl(device.fd, EVIOCGABS(axis), &info)) {
            ALOGE("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
                  device.identifier.name.c_str(), device.fd, errno);
            continue;
        }
        if (info.minimum == info.maximum) {
            continue;
        }
        RawAbsoluteAxisInfo& outAxisInfo = device.rawAbsoluteAxisInfoCache[axis];
        outAxisInfo.valid = true;
        outAxisInfo.minValue = info.minimum;
        outAxisInfo.maxValue = info.maximum;
        outAxisInfo.flat = info.flat;
        outAxisInfo.fuzz = info.fuzz;
        outAxisInfo.resolution = info.resolution;
    }
}

InputDeviceIdentifier EventHub::getDeviceIdentifier(int32_t deviceId) const {
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
@@ -974,18 +989,21 @@ status_t EventHub::getAbsoluteAxisInfo(int32_t deviceId, int axis,
                                       RawAbsoluteAxisInfo* outAxisInfo) const {
    outAxisInfo->clear();
    if (axis < 0 || axis > ABS_MAX) {
        return -1;
        return NAME_NOT_FOUND;
    }
    std::scoped_lock _l(mLock);
    Device* device = getDeviceLocked(deviceId);
    const Device* device = getDeviceLocked(deviceId);
    if (device == nullptr) {
        return -1;
        return NAME_NOT_FOUND;
    }
    auto it = device->rawAbsoluteAxisInfoCache.find(axis);
    if (it == device->rawAbsoluteAxisInfoCache.end()) {
        return -1;
    // We can read the RawAbsoluteAxisInfo even if the device is disabled and doesn't have a valid
    // fd, because the info is populated once when the device is first opened, and it doesn't change
    // throughout the device lifecycle.
    auto it = device->absState.find(axis);
    if (it == device->absState.end()) {
        return NAME_NOT_FOUND;
    }
    *outAxisInfo = it->second;
    *outAxisInfo = it->second.info;
    return OK;
}

@@ -1101,24 +1119,20 @@ int32_t EventHub::getSwitchState(int32_t deviceId, int32_t sw) const {

status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t* outValue) const {
    *outValue = 0;

    if (axis >= 0 && axis <= ABS_MAX) {
        std::scoped_lock _l(mLock);

        Device* device = getDeviceLocked(deviceId);
        if (device != nullptr && device->hasValidFd() && device->absBitmask.test(axis)) {
            struct input_absinfo info;
            if (ioctl(device->fd, EVIOCGABS(axis), &info)) {
                ALOGW("Error reading absolute controller %d for device %s fd %d, errno=%d", axis,
                      device->identifier.name.c_str(), device->fd, errno);
                return -errno;
    if (axis < 0 || axis > ABS_MAX) {
        return NAME_NOT_FOUND;
    }

            *outValue = info.value;
            return OK;
    std::scoped_lock _l(mLock);
    const Device* device = getDeviceLocked(deviceId);
    if (device == nullptr || !device->hasValidFd()) {
        return NAME_NOT_FOUND;
    }
    const auto it = device->absState.find(axis);
    if (it == device->absState.end()) {
        return NAME_NOT_FOUND;
    }
    return -1;
    *outValue = it->second.value;
    return OK;
}

bool EventHub::markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
@@ -2498,9 +2512,6 @@ void EventHub::openDeviceLocked(const std::string& devicePath) {

    device->configureFd();

    // read absolute axis info for all available axes for the device
    populateDeviceAbsoluteAxisInfo(*device);

    ALOGI("New device: id=%d, fd=%d, path='%s', name='%s', classes=%s, "
          "configuration='%s', keyLayout='%s', keyCharacterMap='%s', builtinKeyboard=%s, ",
          deviceId, fd, devicePath.c_str(), device->identifier.name.c_str(),
+7 −9
Original line number Diff line number Diff line
@@ -612,7 +612,6 @@ private:

        BitArray<KEY_MAX> keyBitmask;
        BitArray<KEY_MAX> keyState;
        BitArray<ABS_MAX> absBitmask;
        BitArray<REL_MAX> relBitmask;
        BitArray<SW_MAX> swBitmask;
        BitArray<SW_MAX> swState;
@@ -620,12 +619,17 @@ private:
        BitArray<FF_MAX> ffBitmask;
        BitArray<INPUT_PROP_MAX> propBitmask;
        BitArray<MSC_MAX> mscBitmask;
        BitArray<ABS_MAX> absBitmask;
        struct AxisState {
            RawAbsoluteAxisInfo info;
            int value;
        };
        std::unordered_map<int /*axis*/, AxisState> absState;

        std::string configurationFile;
        std::unique_ptr<PropertyMap> configuration;
        std::unique_ptr<VirtualKeyMap> virtualKeyMap;
        KeyMap keyMap;
        std::unordered_map<int /*axis*/, RawAbsoluteAxisInfo> rawAbsoluteAxisInfoCache;

        bool ffEffectPlaying;
        int16_t ffEffectId; // initially -1
@@ -654,6 +658,7 @@ private:
        status_t readDeviceBitMask(unsigned long ioctlCode, BitArray<N>& bitArray);

        void configureFd();
        void populateAbsoluteAxisStates();
        bool hasKeycodeLocked(int keycode) const;
        void loadConfigurationLocked();
        bool loadVirtualKeyMapLocked();
@@ -732,13 +737,6 @@ private:
    void addDeviceInputInotify();
    void addDeviceInotify();

    /**
     * AbsoluteAxisInfo remains unchanged for the lifetime of the device, hence
     * we can read and store it with device
     * @param device target device
     */
    static void populateDeviceAbsoluteAxisInfo(Device& device);

    // Protect all internal state.
    mutable std::mutex mLock;