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

Commit 588d639c authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Do not assume we are in POINTER mode when canceling pointer gestures

The change in ag/19758680 made it so that we now reset TouchInputMapper
after the viewport is disabled.

When resetting, we cancel any ongoing gestures. Since the mapper is
re-configured before the gesture is canceled, this means that as the
viewport is getting disabled, the mapper (which was previously in
POINTER mode) is set to DISABLED mode. When the pointer gesture is
canceled afterwards, it is happening while the mapper is already
DISABLED.

In this CL, we allow pointer gestures to be aborted even when the mapper
is not in POINTER mode.

Bug: 257071757
Test: atest inputflinger_tests
Change-Id: I5c80a5c1c411d16f70ed4f7cce6dd97ed91e124f
Merged-In: I5c80a5c1c411d16f70ed4f7cce6dd97ed91e124f
(cherry picked from commit b80b6c0e6d9c69957fb9ffa3d0467ad626af2fbe)
parent 80dfdb87
Loading
Loading
Loading
Loading
+23 −1
Original line number Diff line number Diff line
@@ -3521,6 +3521,8 @@ void TouchInputMapper::abortPointerMouse(nsecs_t when, nsecs_t readTime, uint32_

void TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsecs_t readTime, uint32_t policyFlags,
                                             bool down, bool hovering) {
    LOG_ALWAYS_FATAL_IF(mDeviceMode != DeviceMode::POINTER,
                        "%s cannot be used when the device is not in POINTER mode.", __func__);
    int32_t metaState = getContext()->getGlobalMetaState();

    if (down || hovering) {
@@ -3643,6 +3645,10 @@ void TouchInputMapper::dispatchPointerSimple(nsecs_t when, nsecs_t readTime, uin
    if (down || hovering) {
        mPointerSimple.lastCoords.copyFrom(mPointerSimple.currentCoords);
        mPointerSimple.lastProperties.copyFrom(mPointerSimple.currentProperties);
        mPointerSimple.displayId = displayId;
        mPointerSimple.source = mSource;
        mPointerSimple.lastCursorX = xCursorPosition;
        mPointerSimple.lastCursorY = yCursorPosition;
    } else {
        mPointerSimple.reset();
    }
@@ -3652,7 +3658,23 @@ void TouchInputMapper::abortPointerSimple(nsecs_t when, nsecs_t readTime, uint32
    mPointerSimple.currentCoords.clear();
    mPointerSimple.currentProperties.clear();

    dispatchPointerSimple(when, readTime, policyFlags, false, false);
    if (mPointerSimple.down || mPointerSimple.hovering) {
        int32_t metaState = getContext()->getGlobalMetaState();
        NotifyMotionArgs args(getContext()->getNextId(), when, readTime, getDeviceId(),
                              mPointerSimple.source, mPointerSimple.displayId, policyFlags,
                              AMOTION_EVENT_ACTION_CANCEL, 0, AMOTION_EVENT_FLAG_CANCELED,
                              metaState, mLastRawState.buttonState, MotionClassification::NONE,
                              AMOTION_EVENT_EDGE_FLAG_NONE, 1, &mPointerSimple.lastProperties,
                              &mPointerSimple.lastCoords, mOrientedXPrecision, mOrientedYPrecision,
                              mPointerSimple.lastCursorX, mPointerSimple.lastCursorY,
                              mPointerSimple.downTime,
                              /* videoFrames */ {});
        getListener().notifyMotion(&args);
        if (mPointerController != nullptr) {
            mPointerController->fade(PointerControllerInterface::Transition::GRADUAL);
        }
    }
    mPointerSimple.reset();
}

void TouchInputMapper::dispatchMotion(nsecs_t when, nsecs_t readTime, uint32_t policyFlags,
+10 −0
Original line number Diff line number Diff line
@@ -714,6 +714,12 @@ private:
        // Time the pointer last went down.
        nsecs_t downTime;

        // Values reported for the last pointer event.
        uint32_t source;
        int32_t displayId;
        float lastCursorX;
        float lastCursorY;

        void reset() {
            currentCoords.clear();
            currentProperties.clear();
@@ -722,6 +728,10 @@ private:
            down = false;
            hovering = false;
            downTime = 0;
            source = 0;
            displayId = ADISPLAY_ID_NONE;
            lastCursorX = 0.f;
            lastCursorY = 0.f;
        }
    } mPointerSimple;

+56 −0
Original line number Diff line number Diff line
@@ -111,6 +111,13 @@ MATCHER_P2(WithCoords, x, y, "MotionEvent with specified action") {
    return arg.pointerCoords[0].getX() == x && arg.pointerCoords[0].getY();
}

MATCHER_P(WithToolType, toolType, "InputEvent with specified tool type") {
    const auto argToolType = arg.pointerProperties[0].toolType;
    *result_listener << "expected tool type " << motionToolTypeToString(toolType) << ", but got "
                     << motionToolTypeToString(argToolType);
    return argToolType == toolType;
}

template<typename T>
static inline T min(T a, T b) {
    return a < b ? a : b;
@@ -6812,6 +6819,55 @@ TEST_F(SingleTouchInputMapperTest, Reset_RecreatesTouchState) {
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
}

TEST_F(SingleTouchInputMapperTest, WhenViewportActiveStatusChanged_PointerGestureIsReset) {
    std::shared_ptr<FakePointerController> fakePointerController =
            std::make_shared<FakePointerController>();
    fakePointerController->setBounds(0, 0, DISPLAY_WIDTH - 1, DISPLAY_HEIGHT - 1);
    fakePointerController->setPosition(100, 200);
    fakePointerController->setButtonState(0);
    mFakePolicy->setPointerController(fakePointerController);

    addConfigurationProperty("touch.deviceType", "pointer");
    prepareDisplay(DISPLAY_ORIENTATION_0);
    prepareButtons();
    mFakeEventHub->addKey(EVENTHUB_ID, BTN_TOOL_PEN, 0, AKEYCODE_UNKNOWN, 0);
    prepareAxes(POSITION);
    SingleTouchInputMapper& mapper = addMapperAndConfigure<SingleTouchInputMapper>();
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyDeviceResetWasCalled());

    // Start a stylus gesture.
    processKey(mapper, BTN_TOOL_PEN, 1);
    processDown(mapper, 100, 200);
    processSync(mapper);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(WithAction(AMOTION_EVENT_ACTION_DOWN),
                  WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
    // TODO(b/257078296): Pointer mode generates extra event.
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(WithAction(AMOTION_EVENT_ACTION_MOVE),
                  WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());

    // Make the viewport inactive. This will put the device in disabled mode, and the ongoing stylus
    // gesture should be disabled.
    auto viewport = mFakePolicy->getDisplayViewportByType(ViewportType::INTERNAL);
    viewport->isActive = false;
    mFakePolicy->updateViewport(*viewport);
    configureDevice(InputReaderConfiguration::CHANGE_DISPLAY_INFO);
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(WithAction(AMOTION_EVENT_ACTION_CANCEL),
                  WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
    // TODO(b/257078296): Pointer mode generates extra event.
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasCalled(
            AllOf(WithAction(AMOTION_EVENT_ACTION_CANCEL),
                  WithSource(AINPUT_SOURCE_MOUSE | AINPUT_SOURCE_STYLUS),
                  WithToolType(AMOTION_EVENT_TOOL_TYPE_STYLUS))));
    ASSERT_NO_FATAL_FAILURE(mFakeListener->assertNotifyMotionWasNotCalled());
}

TEST_F(SingleTouchInputMapperTest,
       Process_WhenViewportDisplayIdChanged_TouchIsCanceledAndDeviceIsReset) {
    addConfigurationProperty("touch.deviceType", "touchScreen");