Skip to content

Commit a47969d

Browse files
committed
Add test for simultaneous mouse and touch with transfer
When transferTouch is used while both touch and mouse are active, the current behaviour is strange. Upon transfer of touch, the transfered-to window receives HOVER_EXIT, even though it never received HOVER_ENTER or HOVER_MOVE. Also, the touch gesture is transfered with ACTION_DOWN, but subsequent touch events are not delivered to the transfered-to window. In this CL a test is added to reproduce this. Bug: 382473355 Test: atest --host inputflinger_tests Flag: TEST_ONLY Change-Id: Id71415b750ba1c58b5882b87640f4dfc26b79182
1 parent c3aee78 commit a47969d

1 file changed

Lines changed: 191 additions & 0 deletions

File tree

services/inputflinger/tests/InputDispatcher_test.cpp

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14914,4 +14914,195 @@ TEST_F(InputDispatcherObscuredFlagTest, StylusHoverObscuredTest) {
1491414914
mWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_HOVER_EXIT), WithFlags(0)));
1491514915
}
1491614916

14917+
class TransferOrDontTransferFixture : public InputDispatcherTest,
14918+
public ::testing::WithParamInterface<bool> {
14919+
public:
14920+
void SetUp() override {
14921+
InputDispatcherTest::SetUp();
14922+
14923+
std::shared_ptr<FakeApplicationHandle> app = std::make_shared<FakeApplicationHandle>();
14924+
mFromWindow =
14925+
sp<FakeWindowHandle>::make(app, mDispatcher, "From", ui::LogicalDisplayId::DEFAULT);
14926+
mToWindow =
14927+
sp<FakeWindowHandle>::make(app, mDispatcher, "To", ui::LogicalDisplayId::DEFAULT);
14928+
14929+
mDispatcher->onWindowInfosChanged(
14930+
{{*mFromWindow->getInfo(), *mToWindow->getInfo()}, {}, 0, 0});
14931+
}
14932+
14933+
protected:
14934+
sp<FakeWindowHandle> mFromWindow;
14935+
sp<FakeWindowHandle> mToWindow;
14936+
};
14937+
14938+
// Start a touch gesture and then continue hovering the mouse at the same time.
14939+
// After the mouse is hovering, invoke transferTouch API. Check the events that
14940+
// are received by each of the windows.
14941+
TEST_P(TransferOrDontTransferFixture, TouchDownAndMouseHover) {
14942+
SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, false);
14943+
14944+
const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
14945+
const int32_t mouseDeviceId = 6;
14946+
const int32_t touchDeviceId = 4;
14947+
14948+
// Send touch down to the first window
14949+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
14950+
.deviceId(touchDeviceId)
14951+
.downTime(baseTime + 10)
14952+
.eventTime(baseTime + 10)
14953+
.pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
14954+
.build());
14955+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
14956+
14957+
// Send touch move to the first window
14958+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
14959+
.deviceId(touchDeviceId)
14960+
.downTime(baseTime + 10)
14961+
.eventTime(baseTime + 20)
14962+
.pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(100))
14963+
.build());
14964+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
14965+
14966+
// Start mouse hover on the first window
14967+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
14968+
.deviceId(mouseDeviceId)
14969+
.downTime(baseTime + 30)
14970+
.eventTime(baseTime + 30)
14971+
.pointer(PointerBuilder(0, ToolType::MOUSE).x(200).y(200))
14972+
.build());
14973+
14974+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
14975+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
14976+
14977+
if (GetParam()) {
14978+
// Call transferTouchGesture
14979+
const bool transferred =
14980+
mDispatcher->transferTouchGesture(mFromWindow->getToken(), mToWindow->getToken());
14981+
ASSERT_TRUE(transferred);
14982+
14983+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14984+
// b/382473355: For some reason, mToWindow also receives HOVER_EXIT first
14985+
mToWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
14986+
mToWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
14987+
14988+
// Further touch events should be delivered to mTowindow (?)
14989+
mDispatcher->notifyMotion(
14990+
MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
14991+
.deviceId(touchDeviceId)
14992+
.downTime(baseTime + 10)
14993+
.eventTime(baseTime + 40)
14994+
.pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
14995+
.build());
14996+
mDispatcher->notifyMotion(
14997+
MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
14998+
.deviceId(touchDeviceId)
14999+
.downTime(baseTime + 10)
15000+
.eventTime(baseTime + 50)
15001+
.pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
15002+
.build());
15003+
// b/382473355: Even though the window got ACTION_DOWN, it's no longer receiving the
15004+
// remainder of the touch gesture.
15005+
15006+
mFromWindow->assertNoEvents();
15007+
mToWindow->assertNoEvents();
15008+
} else {
15009+
// Don't call transferTouchGesture
15010+
15011+
// Further touch events should be dropped
15012+
mDispatcher->notifyMotion(
15013+
MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
15014+
.deviceId(touchDeviceId)
15015+
.downTime(baseTime + 10)
15016+
.eventTime(baseTime + 40)
15017+
.pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
15018+
.build());
15019+
mFromWindow->assertNoEvents();
15020+
mToWindow->assertNoEvents();
15021+
}
15022+
}
15023+
15024+
TEST_P(TransferOrDontTransferFixture, MouseAndTouchTransferSimultaneousMultiDevice) {
15025+
SCOPED_FLAG_OVERRIDE(enable_multi_device_same_window_stream, true);
15026+
15027+
const nsecs_t baseTime = systemTime(SYSTEM_TIME_MONOTONIC);
15028+
const int32_t mouseDeviceId = 6;
15029+
const int32_t touchDeviceId = 4;
15030+
15031+
// Send touch down to the 'From' window
15032+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
15033+
.deviceId(touchDeviceId)
15034+
.downTime(baseTime + 10)
15035+
.eventTime(baseTime + 10)
15036+
.pointer(PointerBuilder(0, ToolType::FINGER).x(100).y(100))
15037+
.build());
15038+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
15039+
15040+
// Send touch move to the 'From' window
15041+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
15042+
.deviceId(touchDeviceId)
15043+
.downTime(baseTime + 10)
15044+
.eventTime(baseTime + 20)
15045+
.pointer(PointerBuilder(0, ToolType::FINGER).x(110).y(100))
15046+
.build());
15047+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
15048+
15049+
// Start mouse hover on the 'From' window
15050+
mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_HOVER_MOVE, AINPUT_SOURCE_MOUSE)
15051+
.deviceId(mouseDeviceId)
15052+
.downTime(baseTime + 30)
15053+
.eventTime(baseTime + 30)
15054+
.pointer(PointerBuilder(0, ToolType::MOUSE).x(200).y(200))
15055+
.build());
15056+
15057+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_ENTER));
15058+
15059+
if (GetParam()) {
15060+
// Call transferTouchGesture
15061+
const bool transferred =
15062+
mDispatcher->transferTouchGesture(mFromWindow->getToken(), mToWindow->getToken());
15063+
ASSERT_TRUE(transferred);
15064+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_CANCEL));
15065+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_HOVER_EXIT));
15066+
mToWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
15067+
15068+
// Further touch events should be delivered to mToWindow
15069+
mDispatcher->notifyMotion(
15070+
MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
15071+
.deviceId(touchDeviceId)
15072+
.downTime(baseTime + 10)
15073+
.eventTime(baseTime + 40)
15074+
.pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
15075+
.build());
15076+
mDispatcher->notifyMotion(
15077+
MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
15078+
.deviceId(touchDeviceId)
15079+
.downTime(baseTime + 10)
15080+
.eventTime(baseTime + 50)
15081+
.pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
15082+
.build());
15083+
// b/382473355: Even though the window got ACTION_DOWN, it's receiving another DOWN!
15084+
mToWindow->consumeMotionEvent(WithMotionAction(ACTION_DOWN));
15085+
mToWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
15086+
mToWindow->consumeMotionEvent(WithMotionAction(ACTION_UP));
15087+
15088+
mFromWindow->assertNoEvents();
15089+
mToWindow->assertNoEvents();
15090+
} else {
15091+
// Don't call transferTouchGesture
15092+
15093+
mDispatcher->notifyMotion(
15094+
MotionArgsBuilder(ACTION_MOVE, AINPUT_SOURCE_TOUCHSCREEN)
15095+
.deviceId(touchDeviceId)
15096+
.downTime(baseTime + 10)
15097+
.eventTime(baseTime + 40)
15098+
.pointer(PointerBuilder(0, ToolType::FINGER).x(120).y(100))
15099+
.build());
15100+
mFromWindow->consumeMotionEvent(WithMotionAction(ACTION_MOVE));
15101+
mFromWindow->assertNoEvents();
15102+
mToWindow->assertNoEvents();
15103+
}
15104+
}
15105+
15106+
INSTANTIATE_TEST_SUITE_P(WithAndWithoutTransfer, TransferOrDontTransferFixture, testing::Bool());
15107+
1491715108
} // namespace android::inputdispatcher

0 commit comments

Comments
 (0)