Loading services/inputflinger/TEST_MAPPING +2 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ "include-filter": "android.view.cts.input", "include-filter": "android.view.cts.MotionEventTest", "include-filter": "android.view.cts.PointerCaptureTest", "include-filter": "android.view.cts.TooltipTest", "include-filter": "android.view.cts.VerifyInputEventTest" } ] Loading Loading @@ -128,6 +129,7 @@ { "include-filter": "android.view.cts.MotionEventTest", "include-filter": "android.view.cts.PointerCaptureTest", "include-filter": "android.view.cts.TooltipTest", "include-filter": "android.view.cts.VerifyInputEventTest" } ] Loading services/inputflinger/dispatcher/InputDispatcher.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -1769,15 +1769,16 @@ void InputDispatcher::dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<Dr void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry& entry) { if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%" PRId32 ", policyFlags=0x%x, " "action=%s, actionButton=0x%x, flags=0x%x, " "metaState=0x%x, buttonState=0x%x," "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64, prefix, entry.eventTime, entry.deviceId, entry.source, entry.displayId, entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(), entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.edgeFlags, entry.xPrecision, entry.yPrecision, entry.downTime); prefix, entry.eventTime, entry.deviceId, inputEventSourceToString(entry.source).c_str(), entry.displayId, entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(), entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.edgeFlags, entry.xPrecision, entry.yPrecision, entry.downTime); for (uint32_t i = 0; i < entry.pointerCount; i++) { ALOGD(" Pointer %d: id=%d, toolType=%d, " Loading Loading @@ -2502,6 +2503,10 @@ Failed: } } if (tempTouchState.windows.empty()) { mTouchStatesByDisplay.erase(displayId); } // Update hover state. mLastHoverWindowHandle = newHoverWindowHandle; Loading services/inputflinger/dispatcher/TouchState.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -148,7 +148,8 @@ bool TouchState::isDown() const { std::string TouchState::dump() const { std::string out; out += StringPrintf("deviceId=%d, source=0x%08x\n", deviceId, source); out += StringPrintf("deviceId=%d, source=%s\n", deviceId, inputEventSourceToString(source).c_str()); if (!windows.empty()) { out += " Windows:\n"; for (size_t i = 0; i < windows.size(); i++) { Loading services/inputflinger/tests/InputDispatcher_test.cpp +72 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <android-base/thread_annotations.h> #include <binder/Binder.h> #include <fcntl.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <input/Input.h> #include <linux/input.h> Loading @@ -43,6 +44,7 @@ using android::os::InputEventInjectionSync; namespace android::inputdispatcher { using namespace ftl::flag_operators; using testing::AllOf; // An arbitrary time value. static constexpr nsecs_t ARBITRARY_TIME = 1234; Loading Loading @@ -102,6 +104,28 @@ static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) { << MotionEvent::actionToString(receivedAction); } MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") { bool matches = action == arg.getAction(); if (!matches) { *result_listener << "expected action " << MotionEvent::actionToString(action) << ", but got " << MotionEvent::actionToString(arg.getAction()); } if (action == AMOTION_EVENT_ACTION_CANCEL) { if (!matches) { *result_listener << "; "; } *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set"; matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0; } return matches; } MATCHER_P(WithSource, source, "InputEvent with specified source") { *result_listener << "expected source " << inputEventSourceToString(source) << ", but got " << inputEventSourceToString(arg.getSource()); return arg.getSource() == source; } // --- FakeInputDispatcherPolicy --- class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface { Loading Loading @@ -1205,6 +1229,12 @@ public: mInputReceiver->consumeCaptureEvent(hasCapture); } void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) { MotionEvent* motionEvent = consumeMotion(); ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event"; ASSERT_THAT(*motionEvent, matcher); } void consumeEvent(int32_t expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { Loading Loading @@ -2207,6 +2237,48 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) { ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */); } /** * Inject a mouse hover event followed by a tap from touchscreen. * In the current implementation, the tap does not cause a HOVER_EXIT event. */ TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); window->setFrame(Rect(0, 0, 100, 100)); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); // Inject a hover_move from mouse. NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT, {{50, 50}}); motionArgs.xCursorPosition = 50; motionArgs.yCursorPosition = 50; mDispatcher->notifyMotion(&motionArgs); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)))); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)))); // Tap on the window motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {{10, 10}}); mDispatcher->notifyMotion(&motionArgs); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)))); motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {{10, 10}}); mDispatcher->notifyMotion(&motionArgs); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)))); } TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); Loading services/inputflinger/tests/TestInputListenerMatchers.h +2 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ MATCHER_P(WithKeyAction, action, "KeyEvent with specified action") { } MATCHER_P(WithSource, source, "InputEvent with specified source") { *result_listener << "expected source " << source << ", but got " << arg.source; *result_listener << "expected source " << inputEventSourceToString(source) << ", but got " << inputEventSourceToString(arg.source); return arg.source == source; } Loading Loading
services/inputflinger/TEST_MAPPING +2 −0 Original line number Diff line number Diff line Loading @@ -41,6 +41,7 @@ "include-filter": "android.view.cts.input", "include-filter": "android.view.cts.MotionEventTest", "include-filter": "android.view.cts.PointerCaptureTest", "include-filter": "android.view.cts.TooltipTest", "include-filter": "android.view.cts.VerifyInputEventTest" } ] Loading Loading @@ -128,6 +129,7 @@ { "include-filter": "android.view.cts.MotionEventTest", "include-filter": "android.view.cts.PointerCaptureTest", "include-filter": "android.view.cts.TooltipTest", "include-filter": "android.view.cts.VerifyInputEventTest" } ] Loading
services/inputflinger/dispatcher/InputDispatcher.cpp +10 −5 Original line number Diff line number Diff line Loading @@ -1769,15 +1769,16 @@ void InputDispatcher::dispatchDragLocked(nsecs_t currentTime, std::shared_ptr<Dr void InputDispatcher::logOutboundMotionDetails(const char* prefix, const MotionEntry& entry) { if (DEBUG_OUTBOUND_EVENT_DETAILS) { ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=0x%x, displayId=%" PRId32 ALOGD("%seventTime=%" PRId64 ", deviceId=%d, source=%s, displayId=%" PRId32 ", policyFlags=0x%x, " "action=%s, actionButton=0x%x, flags=0x%x, " "metaState=0x%x, buttonState=0x%x," "edgeFlags=0x%x, xPrecision=%f, yPrecision=%f, downTime=%" PRId64, prefix, entry.eventTime, entry.deviceId, entry.source, entry.displayId, entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(), entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.edgeFlags, entry.xPrecision, entry.yPrecision, entry.downTime); prefix, entry.eventTime, entry.deviceId, inputEventSourceToString(entry.source).c_str(), entry.displayId, entry.policyFlags, MotionEvent::actionToString(entry.action).c_str(), entry.actionButton, entry.flags, entry.metaState, entry.buttonState, entry.edgeFlags, entry.xPrecision, entry.yPrecision, entry.downTime); for (uint32_t i = 0; i < entry.pointerCount; i++) { ALOGD(" Pointer %d: id=%d, toolType=%d, " Loading Loading @@ -2502,6 +2503,10 @@ Failed: } } if (tempTouchState.windows.empty()) { mTouchStatesByDisplay.erase(displayId); } // Update hover state. mLastHoverWindowHandle = newHoverWindowHandle; Loading
services/inputflinger/dispatcher/TouchState.cpp +2 −1 Original line number Diff line number Diff line Loading @@ -148,7 +148,8 @@ bool TouchState::isDown() const { std::string TouchState::dump() const { std::string out; out += StringPrintf("deviceId=%d, source=0x%08x\n", deviceId, source); out += StringPrintf("deviceId=%d, source=%s\n", deviceId, inputEventSourceToString(source).c_str()); if (!windows.empty()) { out += " Windows:\n"; for (size_t i = 0; i < windows.size(); i++) { Loading
services/inputflinger/tests/InputDispatcher_test.cpp +72 −0 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ #include <android-base/thread_annotations.h> #include <binder/Binder.h> #include <fcntl.h> #include <gmock/gmock.h> #include <gtest/gtest.h> #include <input/Input.h> #include <linux/input.h> Loading @@ -43,6 +44,7 @@ using android::os::InputEventInjectionSync; namespace android::inputdispatcher { using namespace ftl::flag_operators; using testing::AllOf; // An arbitrary time value. static constexpr nsecs_t ARBITRARY_TIME = 1234; Loading Loading @@ -102,6 +104,28 @@ static void assertMotionAction(int32_t expectedAction, int32_t receivedAction) { << MotionEvent::actionToString(receivedAction); } MATCHER_P(WithMotionAction, action, "MotionEvent with specified action") { bool matches = action == arg.getAction(); if (!matches) { *result_listener << "expected action " << MotionEvent::actionToString(action) << ", but got " << MotionEvent::actionToString(arg.getAction()); } if (action == AMOTION_EVENT_ACTION_CANCEL) { if (!matches) { *result_listener << "; "; } *result_listener << "expected FLAG_CANCELED to be set with ACTION_CANCEL, but was not set"; matches &= (arg.getFlags() & AMOTION_EVENT_FLAG_CANCELED) != 0; } return matches; } MATCHER_P(WithSource, source, "InputEvent with specified source") { *result_listener << "expected source " << inputEventSourceToString(source) << ", but got " << inputEventSourceToString(arg.getSource()); return arg.getSource() == source; } // --- FakeInputDispatcherPolicy --- class FakeInputDispatcherPolicy : public InputDispatcherPolicyInterface { Loading Loading @@ -1205,6 +1229,12 @@ public: mInputReceiver->consumeCaptureEvent(hasCapture); } void consumeMotionEvent(const ::testing::Matcher<MotionEvent>& matcher) { MotionEvent* motionEvent = consumeMotion(); ASSERT_NE(nullptr, motionEvent) << "Did not get a motion event"; ASSERT_THAT(*motionEvent, matcher); } void consumeEvent(int32_t expectedEventType, int32_t expectedAction, std::optional<int32_t> expectedDisplayId, std::optional<int32_t> expectedFlags) { Loading Loading @@ -2207,6 +2237,48 @@ TEST_F(InputDispatcherTest, HoverEnterMouseClickAndHoverExit) { ADISPLAY_ID_DEFAULT, 0 /* expectedFlag */); } /** * Inject a mouse hover event followed by a tap from touchscreen. * In the current implementation, the tap does not cause a HOVER_EXIT event. */ TEST_F(InputDispatcherTest, MouseHoverAndTouchTap) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window", ADISPLAY_ID_DEFAULT); window->setFrame(Rect(0, 0, 100, 100)); mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); // Inject a hover_move from mouse. NotifyMotionArgs motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE, ADISPLAY_ID_DEFAULT, {{50, 50}}); motionArgs.xCursorPosition = 50; motionArgs.yCursorPosition = 50; mDispatcher->notifyMotion(&motionArgs); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER), WithSource(AINPUT_SOURCE_MOUSE)))); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_MOVE), WithSource(AINPUT_SOURCE_MOUSE)))); // Tap on the window motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {{10, 10}}); mDispatcher->notifyMotion(&motionArgs); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_DOWN), WithSource(AINPUT_SOURCE_TOUCHSCREEN)))); motionArgs = generateMotionArgs(AMOTION_EVENT_ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN, ADISPLAY_ID_DEFAULT, {{10, 10}}); mDispatcher->notifyMotion(&motionArgs); ASSERT_NO_FATAL_FAILURE( window->consumeMotionEvent(AllOf(WithMotionAction(AMOTION_EVENT_ACTION_UP), WithSource(AINPUT_SOURCE_TOUCHSCREEN)))); } TEST_F(InputDispatcherTest, DispatchMouseEventsUnderCursor) { std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); Loading
services/inputflinger/tests/TestInputListenerMatchers.h +2 −1 Original line number Diff line number Diff line Loading @@ -46,7 +46,8 @@ MATCHER_P(WithKeyAction, action, "KeyEvent with specified action") { } MATCHER_P(WithSource, source, "InputEvent with specified source") { *result_listener << "expected source " << source << ", but got " << arg.source; *result_listener << "expected source " << inputEventSourceToString(source) << ", but got " << inputEventSourceToString(arg.source); return arg.source == source; } Loading