Don't cancel injected event when mouse event arrives

Currently, MotionEventInjector would cancel any injected gesture when
any MotionEvent arrives. For user using an external device to control
the pointer movement, it's almost impossible to perform the gestures.
Any slightly unintended movement results in the cancellation of the
gesture.

However, if MotionEventInjector keeps sending mouse movement events
when gesture is performing, dispatch logic would be confused and it
causes the gesture malfunction. Therefore, ignore movement events
from mouse when there is an ongoing gesture since click event from
mouse should be intended.

Bug: 116459737
Test: add a new test case in MotionEventInjectorTest
Test: a11y CTS & unit tests
Change-Id: I2c2be8cf565ba15d1a9cd6bc8c45b695c1309b56
This commit is contained in:
Jackal Guo
2019-03-29 17:08:39 +08:00
parent 4d4c558f6a
commit e95df8aecb
2 changed files with 32 additions and 0 deletions

View File

@@ -111,6 +111,15 @@ public class MotionEventInjector extends BaseEventStreamTransformation implement
@Override
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
// MotionEventInjector would cancel any injected gesture when any MotionEvent arrives.
// For user using an external device to control the pointer movement, it's almost
// impossible to perform the gestures. Any slightly unintended movement results in the
// cancellation of the gesture.
if ((event.isFromSource(InputDevice.SOURCE_MOUSE)
&& event.getActionMasked() == MotionEvent.ACTION_HOVER_MOVE)
&& mOpenGesturesInProgress.get(EVENT_SOURCE, false)) {
return;
}
cancelAnyPendingInjectedEvents();
sendMotionEventToNext(event, rawEvent, policyFlags);
}

View File

@@ -17,6 +17,7 @@
package com.android.server.accessibility;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_HOVER_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.WindowManagerPolicyConstants.FLAG_PASS_TO_USER;
@@ -116,6 +117,7 @@ public class MotionEventInjectorTest {
MotionEvent mClickDownEvent;
MotionEvent mClickUpEvent;
MotionEvent mHoverMoveEvent;
ArgumentCaptor<MotionEvent> mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class);
ArgumentCaptor<MotionEvent> mCaptor2 = ArgumentCaptor.forClass(MotionEvent.class);
@@ -152,6 +154,10 @@ public class MotionEventInjectorTest {
CLICK_POINT.y, 0);
mClickUpEvent.setSource(InputDevice.SOURCE_TOUCHSCREEN);
mHoverMoveEvent = MotionEvent.obtain(0, 0, ACTION_HOVER_MOVE, CLICK_POINT.x, CLICK_POINT.y,
0);
mHoverMoveEvent.setSource(InputDevice.SOURCE_MOUSE);
mIsLineStart = allOf(IS_ACTION_DOWN, isAtPoint(LINE_START), hasStandardInitialization(),
hasTimeFromDown(0));
mIsLineMiddle = allOf(IS_ACTION_MOVE, isAtPoint(LINE_END), hasStandardInitialization(),
@@ -300,6 +306,23 @@ public class MotionEventInjectorTest {
verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, false);
}
@Test
public void
testOnMotionEvents_fromMouseWithInjectedGestureInProgress_shouldNotCancelAndPassReal()
throws RemoteException {
EventStreamTransformation next = attachMockNext(mMotionEventInjector);
injectEventsSync(mLineList, mServiceInterface, LINE_SEQUENCE);
mMessageCapturingHandler.sendOneMessage(); // Send a motion event
mMotionEventInjector.onMotionEvent(mHoverMoveEvent, mHoverMoveEvent, 0);
mMessageCapturingHandler.sendAllMessages();
verify(next, times(3)).onMotionEvent(mCaptor1.capture(), mCaptor2.capture(), anyInt());
assertThat(mCaptor1.getAllValues().get(0), mIsLineStart);
assertThat(mCaptor1.getAllValues().get(1), mIsLineMiddle);
assertThat(mCaptor1.getAllValues().get(2), mIsLineEnd);
verify(mServiceInterface).onPerformGestureResult(LINE_SEQUENCE, true);
}
@Test
public void testOnMotionEvents_closedInjectedGestureInProgress_shouldOnlyNotifyAndPassReal()
throws RemoteException {