diff options
| -rw-r--r-- | services/inputflinger/TEST_MAPPING | 2 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 15 | ||||
| -rw-r--r-- | services/inputflinger/dispatcher/TouchState.cpp | 3 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 72 | ||||
| -rw-r--r-- | services/inputflinger/tests/TestInputListenerMatchers.h | 3 |
5 files changed, 88 insertions, 7 deletions
diff --git a/services/inputflinger/TEST_MAPPING b/services/inputflinger/TEST_MAPPING index 4a0f2ec304..b3b4fb1d5e 100644 --- a/services/inputflinger/TEST_MAPPING +++ b/services/inputflinger/TEST_MAPPING @@ -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" } ] @@ -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" } ] diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 87a4ff4f35..eb938c84f8 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -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, " @@ -2502,6 +2503,10 @@ Failed: } } + if (tempTouchState.windows.empty()) { + mTouchStatesByDisplay.erase(displayId); + } + // Update hover state. mLastHoverWindowHandle = newHoverWindowHandle; diff --git a/services/inputflinger/dispatcher/TouchState.cpp b/services/inputflinger/dispatcher/TouchState.cpp index ee7da93975..114e0bf130 100644 --- a/services/inputflinger/dispatcher/TouchState.cpp +++ b/services/inputflinger/dispatcher/TouchState.cpp @@ -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++) { diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index aaf50ce5ed..689fe5c73b 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -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> @@ -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; @@ -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 { @@ -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) { @@ -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>(); diff --git a/services/inputflinger/tests/TestInputListenerMatchers.h b/services/inputflinger/tests/TestInputListenerMatchers.h index 8721bd8fb0..9db34227f5 100644 --- a/services/inputflinger/tests/TestInputListenerMatchers.h +++ b/services/inputflinger/tests/TestInputListenerMatchers.h @@ -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; } |