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

Commit 4b4a457f authored by Arpit Singh's avatar Arpit Singh
Browse files

Sync MT slots on reset and buffer overflow

At present we don't repopulate the MT slot values when a buffer overflow
occurs. This may lead to incosistent event being generate due to out of
sync Mt Slot values.
In this change we repopulate the MT slot values with EVIOCGMTSLOTS
system call after resetting the mapper. Now in case of a buffer overflow
a ongoing multitouch gesture will be cancelled and restarted.

Test: atest inputflinger_tests
Bug: b/291626046

Change-Id: I8195406ce1f9e3e704381b47e282c65463537745
parent ac9a2fa2
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -1141,6 +1141,22 @@ status_t EventHub::getAbsoluteAxisValue(int32_t deviceId, int32_t axis, int32_t*
    return OK;
}

base::Result<std::vector<int32_t>> EventHub::getMtSlotValues(int32_t deviceId, int32_t axis,
                                                             size_t slotCount) const {
    std::scoped_lock _l(mLock);
    const Device* device = getDeviceLocked(deviceId);
    if (device == nullptr || !device->hasValidFd() || !device->absBitmask.test(axis)) {
        return base::ResultError("device problem or axis not supported", NAME_NOT_FOUND);
    }
    std::vector<int32_t> outValues(slotCount + 1);
    outValues[0] = axis;
    const size_t bufferSize = outValues.size() * sizeof(int32_t);
    if (ioctl(device->fd, EVIOCGMTSLOTS(bufferSize), outValues.data()) != OK) {
        return base::ErrnoError();
    }
    return std::move(outValues);
}

bool EventHub::markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
                                     uint8_t* outFlags) const {
    std::scoped_lock _l(mLock);
+1 −1
Original line number Diff line number Diff line
@@ -350,6 +350,7 @@ std::list<NotifyArgs> InputDevice::process(const RawEvent* rawEvents, size_t cou

        if (mDropUntilNextSync) {
            if (rawEvent->type == EV_SYN && rawEvent->code == SYN_REPORT) {
                out += reset(rawEvent->when);
                mDropUntilNextSync = false;
                ALOGD_IF(debugRawEvents(), "Recovered from input event buffer overrun.");
            } else {
@@ -359,7 +360,6 @@ std::list<NotifyArgs> InputDevice::process(const RawEvent* rawEvents, size_t cou
        } else if (rawEvent->type == EV_SYN && rawEvent->code == SYN_DROPPED) {
            ALOGI("Detected input event buffer overrun for device %s.", getName().c_str());
            mDropUntilNextSync = true;
            out += reset(rawEvent->when);
        } else {
            for_each_mapper_in_subdevice(rawEvent->deviceId, [&](InputMapper& mapper) {
                out += mapper.process(rawEvent);
+6 −0
Original line number Diff line number Diff line
@@ -336,6 +336,10 @@ public:
    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
    virtual status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
                                          int32_t* outValue) const = 0;
    /* Query Multi-Touch slot values for an axis. Returns error or an 1 indexed array of size
     * (slotCount + 1). The value at the 0 index is set to queried axis. */
    virtual base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
                                                               size_t slotCount) const = 0;
    virtual int32_t getKeyCodeForKeyLocation(int32_t deviceId, int32_t locationKeyCode) const = 0;

    /*
@@ -552,6 +556,8 @@ public:
                                     int32_t locationKeyCode) const override final;
    status_t getAbsoluteAxisValue(int32_t deviceId, int32_t axis,
                                  int32_t* outValue) const override final;
    base::Result<std::vector<int32_t>> getMtSlotValues(int32_t deviceId, int32_t axis,
                                                       size_t slotCount) const override final;

    bool markSupportedKeyCodes(int32_t deviceId, const std::vector<int32_t>& keyCodes,
                               uint8_t* outFlags) const override final;
+4 −0
Original line number Diff line number Diff line
@@ -372,6 +372,10 @@ public:
    inline status_t getAbsoluteAxisValue(int32_t code, int32_t* outValue) const {
        return mEventHub->getAbsoluteAxisValue(mId, code, outValue);
    }
    inline base::Result<std::vector<int32_t>> getMtSlotValues(int32_t axis,
                                                              size_t slotCount) const {
        return mEventHub->getMtSlotValues(mId, axis, slotCount);
    }
    inline bool markSupportedKeyCodes(const std::vector<int32_t>& keyCodes,
                                      uint8_t* outFlags) const {
        return mEventHub->markSupportedKeyCodes(mId, keyCodes, outFlags);
+2 −6
Original line number Diff line number Diff line
@@ -35,12 +35,8 @@ MultiTouchInputMapper::MultiTouchInputMapper(InputDeviceContext& deviceContext,
MultiTouchInputMapper::~MultiTouchInputMapper() {}

std::list<NotifyArgs> MultiTouchInputMapper::reset(nsecs_t when) {
    // The evdev multi-touch protocol does not allow userspace applications to query the initial or
    // current state of the pointers at any time. This means if we clear our accumulated state when
    // resetting the input mapper, there's no way to rebuild the full initial state of the pointers.
    // We can only wait for updates to all the pointers and axes. Rather than clearing the state and
    // rebuilding the state from scratch, we work around this kernel API limitation by never
    // fully clearing any state specific to the multi-touch protocol.
    mPointerIdBits.clear();
    mMultiTouchMotionAccumulator.reset(mDeviceContext);
    return TouchInputMapper::reset(when);
}

Loading