diff options
2 files changed, 60 insertions, 1 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java index 9538110189c8..755c06aa4be8 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -221,6 +221,8 @@ public class TouchExplorer extends BaseEventStreamTransformation mSendTouchInteractionEndDelayed.cancel(); // Clear the gesture detector mGestureDetector.clear(); + // Clear the offset data by long pressing. + mDispatcher.clear(); // Go to initial state. mState.clear(); mAms.onTouchInteractionEnd(); diff --git a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java index c18cad42b494..13587bc70b24 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/gestures/TouchExplorerTest.java @@ -16,6 +16,8 @@ package com.android.server.accessibility.gestures; +import static android.view.ViewConfiguration.getDoubleTapTimeout; + import static com.android.server.accessibility.gestures.TouchState.STATE_CLEAR; import static com.android.server.accessibility.gestures.TouchState.STATE_DELEGATING; import static com.android.server.accessibility.gestures.TouchState.STATE_DRAGGING; @@ -23,6 +25,7 @@ import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_E import static org.hamcrest.MatcherAssert.assertThat; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.content.Context; @@ -53,6 +56,8 @@ import java.util.List; public class TouchExplorerTest { private static final String LOG_TAG = "TouchExplorerTest"; + // The constant of mDetermineUserIntentTimeout. + private static final int USER_INTENT_TIMEOUT = getDoubleTapTimeout(); private static final int FLAG_1FINGER = 0x8000; private static final int FLAG_2FINGERS = 0x0100; private static final int FLAG_3FINGERS = 0x0200; @@ -94,7 +99,9 @@ public class TouchExplorerTest { public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) { mEvents.add(0, event.copy()); // LastEvent may not match if we're clearing the state - if (mLastEvent != null) { + // The last event becomes ACTION_UP event when sending the ACTION_CANCEL event, + // so ignoring the ACTION_CANCEL event checking. + if (mLastEvent != null && rawEvent.getActionMasked() != MotionEvent.ACTION_CANCEL) { MotionEventMatcher lastEventMatcher = new MotionEventMatcher(mLastEvent); assertThat(rawEvent, lastEventMatcher); } @@ -121,6 +128,43 @@ public class TouchExplorerTest { mTouchExplorer.setNext(mCaptor); } + /** + * Test the case where the event location is correct when clicking after the following + * situation happened: entering the delegate state through doubleTapAndHold gesture and + * receiving a cancel event to return the clear state. + */ + @Test + public void testClick_afterCanceledDoubleTapAndHold_eventLocationIsCorrect() + throws InterruptedException { + // Generates the click position by this click operation, otherwise the offset used + // while delegating could not be set. + send(downEvent(DEFAULT_X + 10, DEFAULT_Y + 10)); + // Waits for transition to touch exploring state. + Thread.sleep(2 * USER_INTENT_TIMEOUT); + send(upEvent()); + + // Simulates detecting the doubleTapAndHold gesture and enters the delegate state. + final MotionEvent sendEvent = + fromTouchscreen(downEvent(DEFAULT_X + 100, DEFAULT_Y + 100)); + mTouchExplorer.onDoubleTapAndHold(sendEvent, sendEvent, 0); + assertState(STATE_DELEGATING); + + send(cancelEvent()); + + // Generates the click operation, and checks the event location of the ACTION_HOVER_ENTER + // event is correct. + send(downEvent()); + // Waits for transition to touch exploring state. + Thread.sleep(2 * USER_INTENT_TIMEOUT); + send(upEvent()); + + final List<MotionEvent> events = getCapturedEvents(); + assertTrue(events.stream().anyMatch( + motionEvent -> motionEvent.getActionMasked() == MotionEvent.ACTION_HOVER_ENTER + && motionEvent.getX() == DEFAULT_X + && motionEvent.getY() == DEFAULT_Y)); + } + @Test public void testTwoFingersMove_shouldDelegatingAndInjectActionDownPointerDown() { goFromStateClearTo(STATE_MOVING_2FINGERS); @@ -294,6 +338,19 @@ public class TouchExplorerTest { return ((EventCaptor) mCaptor).mEvents; } + private MotionEvent cancelEvent() { + mLastDownTime = SystemClock.uptimeMillis(); + return fromTouchscreen( + MotionEvent.obtain(mLastDownTime, mLastDownTime, MotionEvent.ACTION_CANCEL, + DEFAULT_X, DEFAULT_Y, 0)); + } + + private MotionEvent downEvent(float x, float y) { + mLastDownTime = SystemClock.uptimeMillis(); + return fromTouchscreen( + MotionEvent.obtain(mLastDownTime, mLastDownTime, MotionEvent.ACTION_DOWN, x, y, 0)); + } + private MotionEvent downEvent() { mLastDownTime = SystemClock.uptimeMillis(); return fromTouchscreen( |