Skip to content

Commit 2a795df

Browse files
Treehugger RobotAndroid (Google) Code Review
authored andcommitted
Merge "Handle non-split pointers for multi-device case" into aosp-main-future
2 parents 346a37f + 27fc9f1 commit 2a795df

4 files changed

Lines changed: 103 additions & 4 deletions

File tree

services/inputflinger/dispatcher/InputDispatcher.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2705,6 +2705,9 @@ std::vector<InputTarget> InputDispatcher::findTouchedWindowTargetsLocked(
27052705
if (mDragState && mDragState->dragWindow == touchedWindow.windowHandle) {
27062706
continue;
27072707
}
2708+
if (!touchedWindow.hasTouchingPointers(entry.deviceId)) {
2709+
continue;
2710+
}
27082711
touchedWindow.addTouchingPointers(entry.deviceId, touchingPointers);
27092712
}
27102713
}

services/inputflinger/tests/FakeWindows.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,13 @@ class FakeWindowHandle : public gui::WindowInfoHandle {
304304
WithFlags(expectedFlags)));
305305
}
306306

307+
inline void consumeMotionPointerDown(int32_t pointerIdx,
308+
const ::testing::Matcher<MotionEvent>& matcher) {
309+
const int32_t action = AMOTION_EVENT_ACTION_POINTER_DOWN |
310+
(pointerIdx << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
311+
consumeMotionEvent(testing::AllOf(WithMotionAction(action), matcher));
312+
}
313+
307314
inline void consumeMotionPointerUp(int32_t pointerIdx,
308315
const ::testing::Matcher<MotionEvent>& matcher) {
309316
const int32_t action = AMOTION_EVENT_ACTION_POINTER_UP |

services/inputflinger/tests/InputDispatcher_test.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
53605426
TEST_F(InputDispatcherTest, TouchpadThreeFingerSwipeOnlySentToTrustedOverlays) {
53615427
std::shared_ptr<FakeApplicationHandle> application = std::make_shared<FakeApplicationHandle>();
53625428
sp<FakeWindowHandle> window = sp<FakeWindowHandle>::make(application, mDispatcher, "Window",

services/inputflinger/tests/TestEventMatchers.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -609,10 +609,33 @@ MATCHER_P(WithRepeatCount, repeatCount, "KeyEvent with specified repeat count")
609609
return arg.getRepeatCount() == repeatCount;
610610
}
611611

612-
MATCHER_P2(WithPointerId, index, id, "MotionEvent with specified pointer ID for pointer index") {
613-
const auto argPointerId = arg.pointerProperties[index].id;
614-
*result_listener << "expected pointer with index " << index << " to have ID " << argPointerId;
615-
return argPointerId == id;
612+
class WithPointerIdMatcher {
613+
public:
614+
using is_gtest_matcher = void;
615+
explicit WithPointerIdMatcher(size_t index, int32_t pointerId)
616+
: mIndex(index), mPointerId(pointerId) {}
617+
618+
bool MatchAndExplain(const NotifyMotionArgs& args, std::ostream*) const {
619+
return args.pointerProperties[mIndex].id == mPointerId;
620+
}
621+
622+
bool MatchAndExplain(const MotionEvent& event, std::ostream*) const {
623+
return event.getPointerId(mIndex) == mPointerId;
624+
}
625+
626+
void DescribeTo(std::ostream* os) const {
627+
*os << "with pointer[" << mIndex << "] id = " << mPointerId;
628+
}
629+
630+
void DescribeNegationTo(std::ostream* os) const { *os << "wrong pointerId"; }
631+
632+
private:
633+
const size_t mIndex;
634+
const int32_t mPointerId;
635+
};
636+
637+
inline WithPointerIdMatcher WithPointerId(size_t index, int32_t pointerId) {
638+
return WithPointerIdMatcher(index, pointerId);
616639
}
617640

618641
MATCHER_P2(WithCursorPosition, x, y, "InputEvent with specified cursor position") {

0 commit comments

Comments
 (0)