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

Commit fb9fcdae authored by Siarhei Vishniakou's avatar Siarhei Vishniakou
Browse files

Add test to call setInputWindows twice

Currently, I'm observing some strange behaviour, where calling
setInputWindows twice results in the touchable region becoming empty.
Add this test to R to see what's going on, and potentially bisect on
this.

Bug: 143459140
Test: atest inputflinger_tests
Change-Id: Ia0acef5d4ee4acc29d20174fe44c9f94172ccd96
parent 58dc474b
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -224,6 +224,11 @@ Region& Region::operator = (const Region& rhs)
    validate(*this, "this->operator=");
    validate(rhs, "rhs.operator=");
#endif
    if (this == &rhs) {
        // Already equal to itself
        return *this;
    }

    mStorage.clear();
    mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end());
    return *this;
+15 −0
Original line number Diff line number Diff line
@@ -152,5 +152,20 @@ TEST_F(RegionTest, Random_TJunction) {
    }
}

TEST_F(RegionTest, EqualsToSelf) {
    Region touchableRegion;
    touchableRegion.orSelf(Rect(0, 0, 100, 100));

    ASSERT_TRUE(touchableRegion.contains(50, 50));

    // Compiler prevents us from directly calling 'touchableRegion = touchableRegion'
    Region& referenceTouchableRegion = touchableRegion;
    touchableRegion = referenceTouchableRegion;

    ASSERT_FALSE(touchableRegion.isEmpty());

    ASSERT_TRUE(touchableRegion.contains(50, 50));
}

}; // namespace android
+62 −11
Original line number Diff line number Diff line
@@ -811,13 +811,15 @@ static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t
}

static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source,
                                int32_t displayId, int32_t x = 100, int32_t y = 200) {
    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y);
                                int32_t displayId, const PointF& location = {100, 200}) {
    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x,
                             location.y);
}

static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source,
                              int32_t displayId, int32_t x = 100, int32_t y = 200) {
    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y);
                              int32_t displayId, const PointF& location = {100, 200}) {
    return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, location.x,
                             location.y);
}

static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) {
@@ -881,6 +883,55 @@ TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) {
    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
}

/**
 * Calling setInputWindows once with FLAG_NOT_TOUCH_MODAL should not cause any issues.
 * To ensure that window receives only events that were directly inside of it, add
 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
 * when finding touched windows.
 * This test serves as a sanity check for the next test, where setInputWindows is
 * called twice.
 */
TEST_F(InputDispatcherTest, SetInputWindowOnce_SingleWindowTouch) {
    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
    sp<FakeWindowHandle> window =
            new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
    window->setFrame(Rect(0, 0, 100, 100));
    window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);

    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               {50, 50}))
            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";

    // Window should receive motion event.
    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
}

/**
 * Calling setInputWindows twice, with the same info, should not cause any issues.
 * To ensure that window receives only events that were directly inside of it, add
 * FLAG_NOT_TOUCH_MODAL. This will enforce using the touchableRegion of the input
 * when finding touched windows.
 */
TEST_F(InputDispatcherTest, SetInputWindowTwice_SingleWindowTouch) {
    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
    sp<FakeWindowHandle> window =
            new FakeWindowHandle(application, mDispatcher, "Fake Window", ADISPLAY_ID_DEFAULT);
    window->setFrame(Rect(0, 0, 100, 100));
    window->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);

    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
    mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}});
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               {50, 50}))
            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";

    // Window should receive motion event.
    window->consumeMotionDown(ADISPLAY_ID_DEFAULT);
}

// The foreground window should receive the first touch down event.
TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) {
    sp<FakeApplicationHandle> application = new FakeApplicationHandle();
@@ -1822,7 +1873,6 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
                new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT);
        mFocusedWindow->setFrame(Rect(50, 50, 100, 100));
        mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL);
        mFocusedWindowTouchPoint = 60;

        // Set focused application.
        mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application);
@@ -1843,15 +1893,16 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest {
protected:
    sp<FakeWindowHandle> mUnfocusedWindow;
    sp<FakeWindowHandle> mFocusedWindow;
    int32_t mFocusedWindowTouchPoint;
    static constexpr PointF FOCUSED_WINDOW_TOUCH_POINT = {60, 60};
};

// Have two windows, one with focus. Inject MotionEvent with source TOUCHSCREEN and action
// DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received
// the onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) {
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
            AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20))
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               {20, 20}))
            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
    mUnfocusedWindow->consumeMotionDown();

@@ -1863,8 +1914,8 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Succe
// DOWN on the window that doesn't have focus. Ensure no window received the
// onPointerDownOutsideFocus callback.
TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) {
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher,
            AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20))
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20}))
            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
    mFocusedWindow->consumeMotionDown();

@@ -1890,7 +1941,7 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus,
        OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) {
    ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED,
              injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT,
                               mFocusedWindowTouchPoint, mFocusedWindowTouchPoint))
                               FOCUSED_WINDOW_TOUCH_POINT))
            << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED";
    mFocusedWindow->consumeMotionDown();