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

Commit b2e47946 authored by Harry Cutts's avatar Harry Cutts
Browse files

Ignore touchpad contacts that are marked as palms

Some touchpads detect palms in their firmware but continue to report
them, just marking them as palms (e.g. with MT_TOOL_PALM). Since the
Gestures library has no mechanism for marking incoming touches as
pre-detected palms, for now just completely ignore palms reported by the
touchpad.

Bug: 270041770
Test: atest inputflinger_tests:HardwareStateConverterTest
Test: limited manual testing
Change-Id: I7d898889d4bf4e8068194d22150c02a69b59c435
parent b304b2f1
Loading
Loading
Loading
Loading
+27 −12
Original line number Diff line number Diff line
@@ -80,7 +80,17 @@ SelfContainedHardwareState HardwareStateConverter::produceHardwareState(nsecs_t
    schs.fingers.clear();
    for (size_t i = 0; i < mMotionAccumulator.getSlotCount(); i++) {
        MultiTouchMotionAccumulator::Slot slot = mMotionAccumulator.getSlot(i);
        if (slot.isInUse()) {
        if (!slot.isInUse()) {
            continue;
        }
        // Some touchpads continue to report contacts even after they've identified them as palms.
        // We want to exclude these contacts from the HardwareStates, but still need to report a
        // tracking ID of -1 if a finger turns into a palm.
        const bool isPalm = slot.getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM;
        if (isPalm && mFingerSlots.find(i) == mFingerSlots.end()) {
            continue;
        }

        FingerState& fingerState = schs.fingers.emplace_back();
        fingerState = {};
        fingerState.touch_major = slot.getTouchMajor();
@@ -91,7 +101,11 @@ SelfContainedHardwareState HardwareStateConverter::produceHardwareState(nsecs_t
        fingerState.orientation = slot.getOrientation();
        fingerState.position_x = slot.getX();
        fingerState.position_y = slot.getY();
            fingerState.tracking_id = slot.getTrackingId();
        fingerState.tracking_id = isPalm ? -1 : slot.getTrackingId();
        if (fingerState.tracking_id == -1) {
            mFingerSlots.erase(i);
        } else {
            mFingerSlots.insert(i);
        }
    }
    schs.state.fingers = schs.fingers.data();
@@ -103,6 +117,7 @@ SelfContainedHardwareState HardwareStateConverter::produceHardwareState(nsecs_t
void HardwareStateConverter::reset() {
    mCursorButtonAccumulator.reset(mDeviceContext);
    mTouchButtonAccumulator.reset();
    mFingerSlots.clear();
    mMscTimestamp = 0;
}

+2 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#pragma once

#include <optional>
#include <set>

#include <utils/Timers.h>

@@ -53,6 +54,7 @@ private:
    MultiTouchMotionAccumulator mMotionAccumulator;
    TouchButtonAccumulator mTouchButtonAccumulator;
    int32_t mMscTimestamp = 0;
    std::set<size_t> mFingerSlots;
};

} // namespace android
+62 −0
Original line number Diff line number Diff line
@@ -191,6 +191,68 @@ TEST_F(HardwareStateConverterTest, TwoFingers) {
    EXPECT_EQ(0u, finger2.flags);
}

TEST_F(HardwareStateConverterTest, OnePalm) {
    const nsecs_t time = ARBITRARY_TIME;
    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
    HardwareStateConverter conv(deviceContext);

    processAxis(conv, time, EV_ABS, ABS_MT_SLOT, 0);
    processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
    processAxis(conv, time, EV_ABS, ABS_MT_TRACKING_ID, 123);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 50);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 100);

    processAxis(conv, time, EV_KEY, BTN_TOUCH, 1);
    std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
    ASSERT_TRUE(schs.has_value());
    EXPECT_EQ(0, schs->state.finger_cnt);
}

TEST_F(HardwareStateConverterTest, OneFingerTurningIntoAPalm) {
    const nsecs_t time = ARBITRARY_TIME;
    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);
    HardwareStateConverter conv(deviceContext);

    processAxis(conv, time, EV_ABS, ABS_MT_SLOT, 0);
    processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
    processAxis(conv, time, EV_ABS, ABS_MT_TRACKING_ID, 123);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 50);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 100);

    processAxis(conv, time, EV_KEY, BTN_TOUCH, 1);

    std::optional<SelfContainedHardwareState> schs = processSync(conv, time);
    ASSERT_TRUE(schs.has_value());
    EXPECT_EQ(1, schs->state.finger_cnt);

    processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_PALM);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 51);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 99);

    schs = processSync(conv, time);
    ASSERT_TRUE(schs.has_value());
    ASSERT_EQ(1, schs->state.finger_cnt);
    EXPECT_EQ(-1, schs->state.fingers[0].tracking_id);

    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 53);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 97);

    schs = processSync(conv, time);
    ASSERT_TRUE(schs.has_value());
    EXPECT_EQ(0, schs->state.finger_cnt);

    processAxis(conv, time, EV_ABS, ABS_MT_TOOL_TYPE, MT_TOOL_FINGER);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_X, 55);
    processAxis(conv, time, EV_ABS, ABS_MT_POSITION_Y, 95);
    schs = processSync(conv, time);
    ASSERT_TRUE(schs.has_value());
    ASSERT_EQ(1, schs->state.finger_cnt);
    const FingerState& newFinger = schs->state.fingers[0];
    EXPECT_EQ(123, newFinger.tracking_id);
    EXPECT_NEAR(55, newFinger.position_x, EPSILON);
    EXPECT_NEAR(95, newFinger.position_y, EPSILON);
}

TEST_F(HardwareStateConverterTest, ButtonPressed) {
    const nsecs_t time = ARBITRARY_TIME;
    InputDeviceContext deviceContext(*mDevice, EVENTHUB_ID);