Loading services/inputflinger/dispatcher/InputDispatcher.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -6299,4 +6299,19 @@ void InputDispatcher::DispatcherWindowListener::onWindowInfosChanged( mDispatcher.onWindowInfosChanged(windowInfos, displayInfos); } void InputDispatcher::cancelCurrentTouch() { { std::scoped_lock _l(mLock); ALOGD("Canceling all ongoing pointer gestures on all displays."); CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "cancel current touch"); synthesizeCancelationEventsForAllConnectionsLocked(options); mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); } // Wake up poll loop since there might be work to do. mLooper->wake(); } } // namespace android::inputdispatcher services/inputflinger/dispatcher/InputDispatcher.h +2 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,8 @@ public: void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>& windowInfos, const std::vector<android::gui::DisplayInfo>& displayInfos); void cancelCurrentTouch() override; private: enum class DropReason { NOT_DROPPED, Loading services/inputflinger/dispatcher/include/InputDispatcherInterface.h +5 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,11 @@ public: * Called when a display has been removed from the system. */ virtual void displayRemoved(int32_t displayId) = 0; /* * Abort the current touch stream. */ virtual void cancelCurrentTouch() = 0; }; } // namespace android Loading services/inputflinger/tests/InputDispatcher_test.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -3796,6 +3796,49 @@ TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT); } TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) { FakeMonitorReceiver monitorInPrimary = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT); FakeMonitorReceiver monitorInSecondary = FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID); // Test touch down on primary display. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT); monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT); // Test touch down on second display. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID)) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID); monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID); // Trigger cancel touch. mDispatcher->cancelCurrentTouch(); windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT); monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT); windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID); monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID); // Test inject a move motion event, no window/monitor should receive the event. ASSERT_EQ(InputEventInjectionResult::FAILED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {110, 200})) << "Inject motion event should return InputEventInjectionResult::FAILED"; windowInPrimary->assertNoEvents(); monitorInPrimary.assertNoEvents(); ASSERT_EQ(InputEventInjectionResult::FAILED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {110, 200})) << "Inject motion event should return InputEventInjectionResult::FAILED"; windowInSecondary->assertNoEvents(); monitorInSecondary.assertNoEvents(); } class InputFilterTest : public InputDispatcherTest { protected: void testNotifyMotion(int32_t displayId, bool expectToBeFiltered, Loading Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +15 −0 Original line number Diff line number Diff line Loading @@ -6299,4 +6299,19 @@ void InputDispatcher::DispatcherWindowListener::onWindowInfosChanged( mDispatcher.onWindowInfosChanged(windowInfos, displayInfos); } void InputDispatcher::cancelCurrentTouch() { { std::scoped_lock _l(mLock); ALOGD("Canceling all ongoing pointer gestures on all displays."); CancelationOptions options(CancelationOptions::CANCEL_POINTER_EVENTS, "cancel current touch"); synthesizeCancelationEventsForAllConnectionsLocked(options); mTouchStatesByDisplay.clear(); mLastHoverWindowHandle.clear(); } // Wake up poll loop since there might be work to do. mLooper->wake(); } } // namespace android::inputdispatcher
services/inputflinger/dispatcher/InputDispatcher.h +2 −0 Original line number Diff line number Diff line Loading @@ -146,6 +146,8 @@ public: void onWindowInfosChanged(const std::vector<android::gui::WindowInfo>& windowInfos, const std::vector<android::gui::DisplayInfo>& displayInfos); void cancelCurrentTouch() override; private: enum class DropReason { NOT_DROPPED, Loading
services/inputflinger/dispatcher/include/InputDispatcherInterface.h +5 −0 Original line number Diff line number Diff line Loading @@ -211,6 +211,11 @@ public: * Called when a display has been removed from the system. */ virtual void displayRemoved(int32_t displayId) = 0; /* * Abort the current touch stream. */ virtual void cancelCurrentTouch() = 0; }; } // namespace android Loading
services/inputflinger/tests/InputDispatcher_test.cpp +43 −0 Original line number Diff line number Diff line Loading @@ -3796,6 +3796,49 @@ TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CanFocusWindowOnUnfocusedDisplay) secondWindowInPrimary->consumeKeyDown(ADISPLAY_ID_DEFAULT); } TEST_F(InputDispatcherFocusOnTwoDisplaysTest, CancelTouch_MultiDisplay) { FakeMonitorReceiver monitorInPrimary = FakeMonitorReceiver(mDispatcher, "M_1", ADISPLAY_ID_DEFAULT); FakeMonitorReceiver monitorInSecondary = FakeMonitorReceiver(mDispatcher, "M_2", SECOND_DISPLAY_ID); // Test touch down on primary display. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT)) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; windowInPrimary->consumeMotionDown(ADISPLAY_ID_DEFAULT); monitorInPrimary.consumeMotionDown(ADISPLAY_ID_DEFAULT); // Test touch down on second display. ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, injectMotionDown(mDispatcher, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID)) << "Inject motion event should return InputEventInjectionResult::SUCCEEDED"; windowInSecondary->consumeMotionDown(SECOND_DISPLAY_ID); monitorInSecondary.consumeMotionDown(SECOND_DISPLAY_ID); // Trigger cancel touch. mDispatcher->cancelCurrentTouch(); windowInPrimary->consumeMotionCancel(ADISPLAY_ID_DEFAULT); monitorInPrimary.consumeMotionCancel(ADISPLAY_ID_DEFAULT); windowInSecondary->consumeMotionCancel(SECOND_DISPLAY_ID); monitorInSecondary.consumeMotionCancel(SECOND_DISPLAY_ID); // Test inject a move motion event, no window/monitor should receive the event. ASSERT_EQ(InputEventInjectionResult::FAILED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {110, 200})) << "Inject motion event should return InputEventInjectionResult::FAILED"; windowInPrimary->assertNoEvents(); monitorInPrimary.assertNoEvents(); ASSERT_EQ(InputEventInjectionResult::FAILED, injectMotionEvent(mDispatcher, AMOTION_EVENT_ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN, SECOND_DISPLAY_ID, {110, 200})) << "Inject motion event should return InputEventInjectionResult::FAILED"; windowInSecondary->assertNoEvents(); monitorInSecondary.assertNoEvents(); } class InputFilterTest : public InputDispatcherTest { protected: void testNotifyMotion(int32_t displayId, bool expectToBeFiltered, Loading