diff options
| author | 2023-05-08 22:35:50 -0700 | |
|---|---|---|
| committer | 2023-05-08 22:49:00 -0700 | |
| commit | afa08cc62d993eabafd8676a296f55e4c86e05bb (patch) | |
| tree | 650dcb7f4157daf059f7a4fcbe0b6f6eacd6b76c | |
| parent | 85b26eb444a954155a631763b77d4e1ad108f006 (diff) | |
Slip touch when the new window is valid
Previously, the condition for slipping touch was based on the difference
in window tokens. However, that check missed the possibility of the new
window handle being null.
In this CL, that check is returned.
To reproduce this crash, touch needs to try to slip from a slippery
window into a window that requests to drop input.
Bug: 281601168
Test: m inputflinger_tests && $ANDROID_HOST_OUT/nativetest64/inputflinger_tests/inputflinger_tests
Change-Id: I0add7ee65a6492695e9b2368c83fe553677a32f6
| -rw-r--r-- | services/inputflinger/dispatcher/InputDispatcher.cpp | 3 | ||||
| -rw-r--r-- | services/inputflinger/tests/InputDispatcher_test.cpp | 40 |
2 files changed, 42 insertions, 1 deletions
diff --git a/services/inputflinger/dispatcher/InputDispatcher.cpp b/services/inputflinger/dispatcher/InputDispatcher.cpp index 326ca87c41..f3ada8e298 100644 --- a/services/inputflinger/dispatcher/InputDispatcher.cpp +++ b/services/inputflinger/dispatcher/InputDispatcher.cpp @@ -2476,7 +2476,8 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked( newTouchedWindowHandle = nullptr; } - if (!haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) { + if (newTouchedWindowHandle != nullptr && + !haveSameToken(oldTouchedWindowHandle, newTouchedWindowHandle)) { ALOGD("Touch is slipping out of window %s into window %s in display %" PRId32, oldTouchedWindowHandle->getName().c_str(), newTouchedWindowHandle->getName().c_str(), displayId); diff --git a/services/inputflinger/tests/InputDispatcher_test.cpp b/services/inputflinger/tests/InputDispatcher_test.cpp index a6cdee5fb1..f6f02d8241 100644 --- a/services/inputflinger/tests/InputDispatcher_test.cpp +++ b/services/inputflinger/tests/InputDispatcher_test.cpp @@ -5535,6 +5535,46 @@ TEST_F(InputDispatcherTest, SlipperyWindow_SetsFlagPartiallyObscured) { AMOTION_EVENT_FLAG_WINDOW_IS_PARTIALLY_OBSCURED); } +/** + * Two windows, one on the left and another on the right. The left window is slippery. The right + * window isn't eligible to receive touch because it specifies InputConfig::DROP_INPUT. When the + * touch moves from the left window into the right window, the gesture should continue to go to the + * left window. Touch shouldn't slip because the right window can't receive touches. This test + * reproduces a crash. + */ +TEST_F(InputDispatcherTest, TouchSlippingIntoWindowThatDropsTouches) { + std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>(); + + sp<FakeWindowHandle> leftSlipperyWindow = + sp<FakeWindowHandle>::make(application, mDispatcher, "Left", ADISPLAY_ID_DEFAULT); + leftSlipperyWindow->setSlippery(true); + leftSlipperyWindow->setFrame(Rect(0, 0, 100, 100)); + + sp<FakeWindowHandle> rightDropTouchesWindow = + sp<FakeWindowHandle>::make(application, mDispatcher, "Right", ADISPLAY_ID_DEFAULT); + rightDropTouchesWindow->setFrame(Rect(100, 0, 200, 100)); + rightDropTouchesWindow->setDropInput(true); + + mDispatcher->setInputWindows( + {{ADISPLAY_ID_DEFAULT, {leftSlipperyWindow, rightDropTouchesWindow}}}); + + // Start touch in the left window + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50)) + .build()); + leftSlipperyWindow->consumeMotionDown(); + + // And move it into the right window + mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN) + .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50)) + .build()); + + // Since the right window isn't eligible to receive input, touch does not slip. + // The left window continues to receive the gesture. + leftSlipperyWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE)); + rightDropTouchesWindow->assertNoEvents(); +} + class InputDispatcherKeyRepeatTest : public InputDispatcherTest { protected: static constexpr nsecs_t KEY_REPEAT_TIMEOUT = 40 * 1000000; // 40 ms |