Loading libs/ui/Region.cpp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -224,6 +224,11 @@ Region& Region::operator = (const Region& rhs) validate(*this, "this->operator="); validate(*this, "this->operator="); validate(rhs, "rhs.operator="); validate(rhs, "rhs.operator="); #endif #endif if (this == &rhs) { // Already equal to itself return *this; } mStorage.clear(); mStorage.clear(); mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); return *this; return *this; Loading libs/ui/tests/Region_test.cpp +15 −0 Original line number Original line Diff line number Diff line Loading @@ -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 }; // namespace android services/inputflinger/tests/InputDispatcher_test.cpp +62 −11 Original line number Original line Diff line number Diff line Loading @@ -805,13 +805,15 @@ static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t } } static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source, static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source, int32_t displayId, int32_t x = 100, int32_t y = 200) { int32_t displayId, const PointF& location = {100, 200}) { return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y); return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x, location.y); } } static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source, static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source, int32_t displayId, int32_t x = 100, int32_t y = 200) { int32_t displayId, const PointF& location = {100, 200}) { return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y); 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) { static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) { Loading Loading @@ -875,6 +877,55 @@ TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) { window->consumeMotionDown(ADISPLAY_ID_DEFAULT); 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. // The foreground window should receive the first touch down event. TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) { TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) { sp<FakeApplicationHandle> application = new FakeApplicationHandle(); sp<FakeApplicationHandle> application = new FakeApplicationHandle(); Loading Loading @@ -1816,7 +1867,6 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT); new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT); mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); mFocusedWindowTouchPoint = 60; // Set focused application. // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); Loading @@ -1837,15 +1887,16 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { protected: protected: sp<FakeWindowHandle> mUnfocusedWindow; sp<FakeWindowHandle> mUnfocusedWindow; sp<FakeWindowHandle> mFocusedWindow; 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 // 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 // DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received // the onPointerDownOutsideFocus callback. // the onPointerDownOutsideFocus callback. TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) { TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) { ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20)) injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {20, 20})) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mUnfocusedWindow->consumeMotionDown(); mUnfocusedWindow->consumeMotionDown(); Loading @@ -1857,8 +1908,8 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Succe // DOWN on the window that doesn't have focus. Ensure no window received the // DOWN on the window that doesn't have focus. Ensure no window received the // onPointerDownOutsideFocus callback. // onPointerDownOutsideFocus callback. TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) { TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) { ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20)) injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20})) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mFocusedWindow->consumeMotionDown(); mFocusedWindow->consumeMotionDown(); Loading @@ -1884,7 +1935,7 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) { OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) { ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mFocusedWindowTouchPoint, mFocusedWindowTouchPoint)) FOCUSED_WINDOW_TOUCH_POINT)) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mFocusedWindow->consumeMotionDown(); mFocusedWindow->consumeMotionDown(); Loading Loading
libs/ui/Region.cpp +5 −0 Original line number Original line Diff line number Diff line Loading @@ -224,6 +224,11 @@ Region& Region::operator = (const Region& rhs) validate(*this, "this->operator="); validate(*this, "this->operator="); validate(rhs, "rhs.operator="); validate(rhs, "rhs.operator="); #endif #endif if (this == &rhs) { // Already equal to itself return *this; } mStorage.clear(); mStorage.clear(); mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); mStorage.insert(mStorage.begin(), rhs.mStorage.begin(), rhs.mStorage.end()); return *this; return *this; Loading
libs/ui/tests/Region_test.cpp +15 −0 Original line number Original line Diff line number Diff line Loading @@ -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 }; // namespace android
services/inputflinger/tests/InputDispatcher_test.cpp +62 −11 Original line number Original line Diff line number Diff line Loading @@ -805,13 +805,15 @@ static int32_t injectMotionEvent(const sp<InputDispatcher>& dispatcher, int32_t } } static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source, static int32_t injectMotionDown(const sp<InputDispatcher>& dispatcher, int32_t source, int32_t displayId, int32_t x = 100, int32_t y = 200) { int32_t displayId, const PointF& location = {100, 200}) { return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, x, y); return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_DOWN, source, displayId, location.x, location.y); } } static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source, static int32_t injectMotionUp(const sp<InputDispatcher>& dispatcher, int32_t source, int32_t displayId, int32_t x = 100, int32_t y = 200) { int32_t displayId, const PointF& location = {100, 200}) { return injectMotionEvent(dispatcher, AMOTION_EVENT_ACTION_UP, source, displayId, x, y); 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) { static NotifyKeyArgs generateKeyArgs(int32_t action, int32_t displayId = ADISPLAY_ID_NONE) { Loading Loading @@ -875,6 +877,55 @@ TEST_F(InputDispatcherTest, SetInputWindow_SingleWindowTouch) { window->consumeMotionDown(ADISPLAY_ID_DEFAULT); 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. // The foreground window should receive the first touch down event. TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) { TEST_F(InputDispatcherTest, SetInputWindow_MultiWindowsTouch) { sp<FakeApplicationHandle> application = new FakeApplicationHandle(); sp<FakeApplicationHandle> application = new FakeApplicationHandle(); Loading Loading @@ -1816,7 +1867,6 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT); new FakeWindowHandle(application, mDispatcher, "Second", ADISPLAY_ID_DEFAULT); mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); mFocusedWindow->setFrame(Rect(50, 50, 100, 100)); mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); mFocusedWindow->setLayoutParamFlags(InputWindowInfo::FLAG_NOT_TOUCH_MODAL); mFocusedWindowTouchPoint = 60; // Set focused application. // Set focused application. mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); Loading @@ -1837,15 +1887,16 @@ class InputDispatcherOnPointerDownOutsideFocus : public InputDispatcherTest { protected: protected: sp<FakeWindowHandle> mUnfocusedWindow; sp<FakeWindowHandle> mUnfocusedWindow; sp<FakeWindowHandle> mFocusedWindow; 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 // 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 // DOWN on the window that doesn't have focus. Ensure the window that didn't have focus received // the onPointerDownOutsideFocus callback. // the onPointerDownOutsideFocus callback. TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) { TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Success) { ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, 20, 20)) injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {20, 20})) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mUnfocusedWindow->consumeMotionDown(); mUnfocusedWindow->consumeMotionDown(); Loading @@ -1857,8 +1908,8 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_Succe // DOWN on the window that doesn't have focus. Ensure no window received the // DOWN on the window that doesn't have focus. Ensure no window received the // onPointerDownOutsideFocus callback. // onPointerDownOutsideFocus callback. TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) { TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_NonPointerSource) { ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, 20, 20)) injectMotionDown(mDispatcher, AINPUT_SOURCE_TRACKBALL, ADISPLAY_ID_DEFAULT, {20, 20})) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mFocusedWindow->consumeMotionDown(); mFocusedWindow->consumeMotionDown(); Loading @@ -1884,7 +1935,7 @@ TEST_F(InputDispatcherOnPointerDownOutsideFocus, OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) { OnPointerDownOutsideFocus_OnAlreadyFocusedWindow) { ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, ASSERT_EQ(INPUT_EVENT_INJECTION_SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, mFocusedWindowTouchPoint, mFocusedWindowTouchPoint)) FOCUSED_WINDOW_TOUCH_POINT)) << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; << "Inject motion event should return INPUT_EVENT_INJECTION_SUCCEEDED"; mFocusedWindow->consumeMotionDown(); mFocusedWindow->consumeMotionDown(); Loading