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

Commit 421eb1c2 authored by Arthur Hung's avatar Arthur Hung
Browse files

Touch cancellation handling

Cancel motion event that are accidental touches when a user is holding
the device and a touch stream is in progress.

- Process MT_TOOL_PALM and cancel touch when sent from firmware.

Bug: 117933934
Test: atest inputflinger_tests
Test: atest InputProcessTest
Change-Id: I80ba8b462572e5214dd1073ef0568886f71e21c9
parent 0f67b9fa
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -793,6 +793,8 @@ enum {
    AMOTION_EVENT_TOOL_TYPE_MOUSE = 3,
    /** eraser */
    AMOTION_EVENT_TOOL_TYPE_ERASER = 4,
    /** palm */
    AMOTION_EVENT_TOOL_TYPE_PALM = 5,
};

/**
+10 −0
Original line number Diff line number Diff line
@@ -209,6 +209,8 @@ int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
                return AMOTION_EVENT_TOOL_TYPE_FINGER;
            case MT_TOOL_PEN:
                return AMOTION_EVENT_TOOL_TYPE_STYLUS;
            case MT_TOOL_PALM:
                return AMOTION_EVENT_TOOL_TYPE_PALM;
        }
    }
    return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
@@ -247,6 +249,14 @@ void MultiTouchInputMapper::syncTouch(nsecs_t when, RawState* outState) {
            continue;
        }

        if (inSlot->getToolType() == AMOTION_EVENT_TOOL_TYPE_PALM) {
            if (!mCurrentMotionAborted) {
                ALOGI("Canceling touch gesture from device %s because the palm event was detected",
                      getDeviceName().c_str());
                cancelTouch(when);
            }
        }

        if (outCount >= MAX_POINTERS) {
#if DEBUG_POINTERS
            ALOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
+91 −0
Original line number Diff line number Diff line
@@ -6798,4 +6798,95 @@ TEST_F(MultiTouchInputMapperTest, Viewports_SurfaceRange) {
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
}

TEST_F(MultiTouchInputMapperTest, Process_ShouldHandleSingleTouch) {
    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
    addConfigurationProperty("touch.deviceType", "touchScreen");
    prepareDisplay(DISPLAY_ORIENTATION_0);
    prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
    addMapperAndConfigure(mapper);

    NotifyMotionArgs motionArgs;

    constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
    // finger down
    processId(mapper, 1);
    processPosition(mapper, x1, y1);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);

    // finger move
    processId(mapper, 1);
    processPosition(mapper, x2, y2);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_MOVE, motionArgs.action);
    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);

    // finger up.
    processId(mapper, -1);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_UP, motionArgs.action);
    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);

    // new finger down
    processId(mapper, 1);
    processPosition(mapper, x3, y3);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
}

/**
 * Test touch should be canceled when received the MT_TOOL_PALM event, and the following MOVE and
 * UP events should be ignored.
 */
TEST_F(MultiTouchInputMapperTest, Process_ShouldHandlePalmToolType) {
    MultiTouchInputMapper* mapper = new MultiTouchInputMapper(mDevice);
    addConfigurationProperty("touch.deviceType", "touchScreen");
    prepareDisplay(DISPLAY_ORIENTATION_0);
    prepareAxes(POSITION | ID | SLOT | TOOL_TYPE);
    addMapperAndConfigure(mapper);

    NotifyMotionArgs motionArgs;

    // default tool type is finger
    constexpr int32_t x1 = 100, y1 = 200, x2 = 120, y2 = 220, x3 = 140, y3 = 240;
    processId(mapper, 1);
    processPosition(mapper, x1, y1);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);

    // Tool changed to MT_TOOL_PALM expect sending the cancel event.
    processToolType(mapper, MT_TOOL_PALM);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_CANCEL, motionArgs.action);

    // Ignore the following MOVE and UP events if had detect a palm event.
    processId(mapper, 1);
    processPosition(mapper, x2, y2);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());

    // finger up.
    processId(mapper, -1);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());

    // new finger down
    processToolType(mapper, MT_TOOL_FINGER);
    processId(mapper, 1);
    processPosition(mapper, x3, y3);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(&motionArgs));
    ASSERT_EQ(AMOTION_EVENT_ACTION_DOWN, motionArgs.action);
    ASSERT_EQ(AMOTION_EVENT_TOOL_TYPE_FINGER, motionArgs.pointerProperties[0].toolType);
}

} // namespace android