diff options
author | 2020-05-04 14:59:19 -0700 | |
---|---|---|
committer | 2020-05-06 21:25:31 -0700 | |
commit | fb9fcdae2f67ebef2ab6522fd2b49a57f9c28dd2 (patch) | |
tree | 3abc0f411a98c65fc7a2cfba7338194949fa6fdf | |
parent | 58dc474b3d5fbc5a34388789bc79b39254f84d73 (diff) |
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
-rw-r--r-- | libs/ui/Region.cpp | 5 | ||||
-rw-r--r-- | libs/ui/tests/Region_test.cpp | 15 | ||||
-rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 73 |
3 files changed, 82 insertions, 11 deletions
diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 82ce757d5a..e01309b679 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -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; diff --git a/libs/ui/tests/Region_test.cpp b/libs/ui/tests/Region_test.cpp index b104a46364..c6b826d66e 100644 --- a/libs/ui/tests/Region_test.cpp +++ b/libs/ui/tests/Region_test.cpp @@ -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 diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 365d43dd16..e94737ff96 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -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(); |