@@ -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