diff options
-rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 10 | ||||
-rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 23 |
2 files changed, 32 insertions, 1 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index fbbb38835a..7bac534536 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -662,7 +662,15 @@ std::vector<TouchedWindow> getHoveringWindowsLocked(const TouchState* oldState, } else { // This pointer was already sent to the window. Use ACTION_HOVER_MOVE. if (CC_UNLIKELY(maskedAction != AMOTION_EVENT_ACTION_HOVER_MOVE)) { - LOG(FATAL) << "Expected ACTION_HOVER_MOVE instead of " << entry.getDescription(); + android::base::LogSeverity severity = android::base::LogSeverity::FATAL; + if (entry.flags & AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT) { + // The Accessibility injected touch exploration event stream + // has known inconsistencies, so log ERROR instead of + // crashing the device with FATAL. + // TODO(b/286037469): Move a11y severity back to FATAL. + severity = android::base::LogSeverity::ERROR; + } + LOG(severity) << "Expected ACTION_HOVER_MOVE instead of " << entry.getDescription(); } touchedWindow.targetFlags = InputTarget::Flags::DISPATCH_AS_IS; } diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index 017f10baf8..6ff420d951 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -3604,6 +3604,29 @@ TEST_F(InputDispatcherTest, HoverExitIsSentToRemovedWindow) { } /** + * Test that invalid HOVER events sent by accessibility do not cause a fatal crash. + */ +TEST_F(InputDispatcherTest, InvalidA11yHoverStreamDoesNotCrash) { + 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, 1200, 800)); + mDispatcher->setFocusedApplication(ADISPLAY_ID_DEFAULT, application); + mDispatcher->setInputWindows({{ADISPLAY_ID_DEFAULT, {window}}}); + + MotionEventBuilder hoverEnterBuilder = + MotionEventBuilder(AMOTION_EVENT_ACTION_HOVER_ENTER, AINPUT_SOURCE_MOUSE) + .pointer(PointerBuilder(0, ToolType::MOUSE).x(300).y(400)) + .addFlag(AMOTION_EVENT_FLAG_IS_ACCESSIBILITY_EVENT); + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, hoverEnterBuilder.build())); + ASSERT_EQ(InputEventInjectionResult::SUCCEEDED, + injectMotionEvent(mDispatcher, hoverEnterBuilder.build())); + window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)); + window->consumeMotionEvent(WithMotionAction(AMOTION_EVENT_ACTION_HOVER_ENTER)); +} + +/** * If mouse is hovering when the touch goes down, the hovering should be stopped via HOVER_EXIT. */ TEST_F(InputDispatcherTest, TouchDownAfterMouseHover) { |