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

Commit b60b1dcf authored by Prabir Pradhan's avatar Prabir Pradhan
Browse files

Add tests for WATCH_OUTSIDE_TOUCH and touches outside windows

These tests document the current behavior on InputDispatcher.

Bug: 214087836
Test: atest inputflinger_tests
Change-Id: Icfa3cab08b117073028156f5535d0f2ea8e82e78
parent 7038a115
Loading
Loading
Loading
Loading
+50 −3
Original line number Diff line number Diff line
@@ -55,6 +55,8 @@ static constexpr int32_t SECOND_DISPLAY_ID = 1;

static constexpr int32_t POINTER_1_DOWN =
        AMOTION_EVENT_ACTION_POINTER_DOWN | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr int32_t POINTER_2_DOWN =
        AMOTION_EVENT_ACTION_POINTER_DOWN | (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
static constexpr int32_t POINTER_1_UP =
        AMOTION_EVENT_ACTION_POINTER_UP | (1 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);

@@ -2180,6 +2182,53 @@ TEST_F(InputDispatcherTest, NotifyDeviceReset_CancelsMotionStream) {
                         0 /*expectedFlags*/);
}

/**
 * This test documents the behavior of WATCH_OUTSIDE_TOUCH. The window will get ACTION_OUTSIDE when
 * a another pointer causes ACTION_DOWN to be sent to another window for the first time. Only one
 * ACTION_OUTSIDE event is sent per gesture.
 */
TEST_F(InputDispatcherTest, ActionOutsideSentOnlyWhenAWindowIsTouched) {
    // There are three windows that do not overlap. `window` wants to WATCH_OUTSIDE_TOUCH.
    std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
    sp<FakeWindowHandle> window =
            new FakeWindowHandle(application, mDispatcher, "First Window", ADISPLAY_ID_DEFAULT);
    window->setWatchOutsideTouch(true);
    window->setFrame(Rect{0, 0, 100, 100});
    sp<FakeWindowHandle> secondWindow =
            new FakeWindowHandle(application, mDispatcher, "Second Window", ADISPLAY_ID_DEFAULT);
    secondWindow->setFrame(Rect{100, 100, 200, 200});
    sp<FakeWindowHandle> thirdWindow =
            new FakeWindowHandle(application, mDispatcher, "Third Window", ADISPLAY_ID_DEFAULT);
    thirdWindow->setFrame(Rect{200, 200, 300, 300});
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window, secondWindow, thirdWindow}}});

    // First pointer lands outside all windows. `window` does not get ACTION_OUTSIDE.
    NotifyMotionArgs motionArgs =
            generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN,
                               ADISPLAY_ID_DEFAULT, {PointF{-10, -10}});
    mDispatcher->notifyMotion(&motionArgs);
    window->assertNoEvents();
    secondWindow->assertNoEvents();

    // The second pointer lands inside `secondWindow`, which should receive a DOWN event.
    // Now, `window` should get ACTION_OUTSIDE.
    motionArgs = generateMotionArgs(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                                    {PointF{-10, -10}, PointF{105, 105}});
    mDispatcher->notifyMotion(&motionArgs);
    window->consumeMotionOutside();
    secondWindow->consumeMotionDown();
    thirdWindow->assertNoEvents();

    // The third pointer lands inside `thirdWindow`, which should receive a DOWN event. There is
    // no ACTION_OUTSIDE sent to `window` because one has already been sent for this gesture.
    motionArgs = generateMotionArgs(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                                    {PointF{-10, -10}, PointF{105, 105}, PointF{205, 205}});
    mDispatcher->notifyMotion(&motionArgs);
    window->assertNoEvents();
    secondWindow->consumeMotionMove();
    thirdWindow->consumeMotionDown();
}

/**
 * Ensure the correct coordinate spaces are used by InputDispatcher.
 *
@@ -6570,9 +6619,7 @@ TEST_F(InputDispatcherSpyWindowTest, ContinuesToReceiveGestureAfterPilfer) {

    // Third finger goes down outside all windows, so injection should fail.
    const MotionEvent thirdFingerDownEvent =
            MotionEventBuilder(AMOTION_EVENT_ACTION_POINTER_DOWN |
                                       (2 << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT),
                               AINPUT_SOURCE_TOUCHSCREEN)
            MotionEventBuilder(POINTER_2_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
                    .displayId(ADISPLAY_ID_DEFAULT)
                    .eventTime(systemTime(SYSTEM_TIME_MONOTONIC))
                    .pointer(PointerBuilder(/* id */ 0, AMOTION_EVENT_TOOL_TYPE_FINGER)