From 5ed20a7782be8c1f38053a1a3c2b41fae07d9c2c Mon Sep 17 00:00:00 2001 From: Jackal Guo Date: Fri, 29 Mar 2019 17:08:39 +0800 Subject: 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 Merged-In: I2c2be8cf565ba15d1a9cd6bc8c45b695c1309b56 --- .../server/accessibility/MotionEventInjector.java | 9 +++++++++ .../accessibility/MotionEventInjectorTest.java | 23 ++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java index 46e3226bb751..7b6a12822faa 100644 --- a/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java +++ b/services/accessibility/java/com/android/server/accessibility/MotionEventInjector.java @@ -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); } diff --git a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java index 2cba9d022866..2977414fb302 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/MotionEventInjectorTest.java @@ -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 mCaptor1 = ArgumentCaptor.forClass(MotionEvent.class); ArgumentCaptor 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 { -- cgit v1.2.3-59-g8ed1b