@@ -5357,6 +5357,72 @@ TEST_F(InputDispatcherTest, SplittableAndNonSplittableWindows) {
53575357 rightWindow->assertNoEvents();
53585358}
53595359
5360+ /**
5361+ * Two windows: left and right. The left window has PREVENT_SPLITTING input config. Device A sends a
5362+ * down event to the right window. Device B sends a down event to the left window, and then a
5363+ * POINTER_DOWN event to the right window. However, since the left window prevents splitting, the
5364+ * POINTER_DOWN event should only go to the left window, and not to the right window.
5365+ * This test attempts to reproduce a crash.
5366+ */
5367+ TEST_F(InputDispatcherTest, MultiDeviceTwoWindowsPreventSplitting) {
5368+ std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
5369+ sp<FakeWindowHandle> leftWindow =
5370+ sp<FakeWindowHandle>::make(application, mDispatcher, "Left window (prevent splitting)",
5371+ ui::LogicalDisplayId::DEFAULT);
5372+ leftWindow->setFrame(Rect(0, 0, 100, 100));
5373+ leftWindow->setPreventSplitting(true);
5374+
5375+ sp<FakeWindowHandle> rightWindow =
5376+ sp<FakeWindowHandle>::make(application, mDispatcher, "Right window",
5377+ ui::LogicalDisplayId::DEFAULT);
5378+ rightWindow->setFrame(Rect(100, 0, 200, 100));
5379+
5380+ mDispatcher->onWindowInfosChanged(
5381+ {{*leftWindow->getInfo(), *rightWindow->getInfo()}, {}, 0, 0});
5382+
5383+ const DeviceId deviceA = 9;
5384+ const DeviceId deviceB = 3;
5385+ // Touch the right window with device A
5386+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5387+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5388+ .deviceId(deviceA)
5389+ .build());
5390+ rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceA)));
5391+ // Touch the left window with device B
5392+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5393+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5394+ .deviceId(deviceB)
5395+ .build());
5396+ leftWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_DOWN), WithDeviceId(deviceB)));
5397+ // Send a second pointer from device B to the right window. It shouldn't go to the right window
5398+ // because the left window prevents splitting.
5399+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_DOWN, AINPUT_SOURCE_TOUCHSCREEN)
5400+ .deviceId(deviceB)
5401+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5402+ .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5403+ .build());
5404+ leftWindow->consumeMotionPointerDown(1, WithDeviceId(deviceB));
5405+
5406+ // Finish the gesture for both devices
5407+ mDispatcher->notifyMotion(MotionArgsBuilder(POINTER_1_UP, AINPUT_SOURCE_TOUCHSCREEN)
5408+ .deviceId(deviceB)
5409+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5410+ .pointer(PointerBuilder(1, ToolType::FINGER).x(120).y(120))
5411+ .build());
5412+ leftWindow->consumeMotionPointerUp(1, WithDeviceId(deviceB));
5413+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5414+ .pointer(PointerBuilder(0, ToolType::FINGER).x(50).y(50))
5415+ .deviceId(deviceB)
5416+ .build());
5417+ leftWindow->consumeMotionEvent(
5418+ AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceB), WithPointerId(0, 0)));
5419+ mDispatcher->notifyMotion(MotionArgsBuilder(ACTION_UP, AINPUT_SOURCE_TOUCHSCREEN)
5420+ .pointer(PointerBuilder(0, ToolType::FINGER).x(150).y(50))
5421+ .deviceId(deviceA)
5422+ .build());
5423+ rightWindow->consumeMotionEvent(AllOf(WithMotionAction(ACTION_UP), WithDeviceId(deviceA)));
5424+ }
5425+
53605426TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
53615427 std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
53625428 sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",
0 commit comments