From 5edb7968334b42b150dd223cae1d4116c2485f1e Mon Sep 17 00:00:00 2001 From: Ameer Armaly Date: Fri, 7 Jun 2019 13:08:45 -0700 Subject: [PATCH] Add STATE_CLEAR and STATE_TOUCH_INTERACTING to TouchExplorer. STATE_CLEAR represents an initial state where no fingers are down. STATE_TOUCH_INTERACTING is where we try to detect the user's intent. Bug: 136131815 Test: atest CtsAccessibilityServiceTestCases FrameworksServicesTests:TouchExplorerTest Change-Id: Ifac5ab2556d5d16e6326fec1f92064cb6987b519 --- .../accessibility/gestures/TouchExplorer.java | 294 +++++++++++------- .../accessibility/gestures/TouchState.java | 92 ++++-- .../gestures/TouchExplorerTest.java | 49 ++- 3 files changed, 265 insertions(+), 170 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 d8b7e3a25e04b..a338b901d24c6 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchExplorer.java @@ -66,12 +66,6 @@ public class TouchExplorer extends BaseEventStreamTransformation // Tag for logging received events. private static final String LOG_TAG = "TouchExplorer"; - // States this explorer can be in. - private static final int STATE_TOUCH_EXPLORING = 0x00000001; - private static final int STATE_DRAGGING = 0x00000002; - private static final int STATE_DELEGATING = 0x00000004; - private static final int STATE_GESTURE_DETECTING = 0x00000005; - // The maximum of the cosine between the vectors of two moving // pointers so they can be considered moving in the same direction. private static final float MAX_DRAGGING_ANGLE_COS = 0.525321989f; // cos(pi/4) @@ -248,7 +242,13 @@ public class TouchExplorer extends BaseEventStreamTransformation return; } - if (mState.isTouchExploring()) { + // TODO: extract the below functions into separate handlers for each state. + // Right now the number of functions and number of states make the code messy. + if (mState.isClear()) { + handleMotionEventStateClear(event, rawEvent, policyFlags); + } else if (mState.isTouchInteracting()) { + handleMotionEventStateTouchInteracting(event, rawEvent, policyFlags); + } else if (mState.isTouchExploring()) { handleMotionEventStateTouchExploring(event, rawEvent, policyFlags); } else if (mState.isDragging()) { handleMotionEventStateDragging(event, policyFlags); @@ -286,8 +286,8 @@ public class TouchExplorer extends BaseEventStreamTransformation @Override public void onDoubleTapAndHold(MotionEvent event, int policyFlags) { - // Ignore the event if we aren't touch exploring. - if (!mState.isTouchExploring()) { + // Ignore the event if we aren't touch interacting. + if (!mState.isTouchInteracting()) { return; } @@ -304,8 +304,7 @@ public class TouchExplorer extends BaseEventStreamTransformation @Override public boolean onDoubleTap(MotionEvent event, int policyFlags) { - // Ignore the event if we aren't touch exploring. - if (!mState.isTouchExploring()) { + if (!mState.isTouchInteracting()) { return false; } @@ -379,6 +378,94 @@ public class TouchExplorer extends BaseEventStreamTransformation return false; } + /** + * Handles a motion event in the clear state i.e. no fingers are touching the screen. + */ + private void handleMotionEventStateClear( + MotionEvent event, MotionEvent rawEvent, int policyFlags) { + switch (event.getActionMasked()) { + // The only way to leave the clear state is for a pointer to go down. + case MotionEvent.ACTION_DOWN: + handleActionDown(event, policyFlags); + break; + default: + // Some other nonsensical event. + break; + } + } + + /** + * Handles ACTION_DOWN while in the clear or touch interacting states. This event represents the + * first finger touching the screen. + */ + private void handleActionDown(MotionEvent event, int policyFlags) { + mAms.onTouchInteractionStart(); + + // If we still have not notified the user for the last + // touch, we figure out what to do. If were waiting + // we resent the delayed callback and wait again. + mSendHoverEnterAndMoveDelayed.cancel(); + mSendHoverExitDelayed.cancel(); + + // If a touch exploration gesture is in progress send events for its end. + if (mState.isTouchExploring()) { + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); + } + + // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double + // tap. + if (!mGestureDetector.firstTapDetected() && mState.isClear()) { + mSendTouchExplorationEndDelayed.forceSendAndRemove(); + mSendTouchInteractionEndDelayed.forceSendAndRemove(); + sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START); + } else { + // Let gesture to handle to avoid duplicated TYPE_TOUCH_INTERACTION_END event. + mSendTouchInteractionEndDelayed.cancel(); + } + + if (!mGestureDetector.firstTapDetected() && !mState.isTouchExploring()) { + if (!mSendHoverEnterAndMoveDelayed.isPending()) { + // Queue a delayed transition to STATE_TOUCH_EXPLORING. + // If we do not detect that this is a gesture, delegation or drag the transition + // will fire by default. + // The idea is to avoid getting stuck in STATE_TOUCH_INTERACTING + final int pointerId = mReceivedPointerTracker.getPrimaryPointerId(); + final int pointerIdBits = (1 << pointerId); + mSendHoverEnterAndMoveDelayed.post(event, pointerIdBits, policyFlags); + } else { + // Cache the event until we discern exploration from gesturing. + mSendHoverEnterAndMoveDelayed.addEvent(event); + } + } + } + + /** + * Handles a motion event in touch interacting state. + * + * @param event The event to be handled. + * @param rawEvent The raw (unmodified) motion event. + * @param policyFlags The policy flags associated with the event. + */ + private void handleMotionEventStateTouchInteracting( + MotionEvent event, MotionEvent rawEvent, int policyFlags) { + switch (event.getActionMasked()) { + case MotionEvent.ACTION_DOWN: + // Continue the previous interaction. + mSendTouchInteractionEndDelayed.cancel(); + handleActionDown(event, policyFlags); + break; + case MotionEvent.ACTION_POINTER_DOWN: + handleActionPointerDown(); + break; + case MotionEvent.ACTION_MOVE: + handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags); + break; + case MotionEvent.ACTION_UP: + handleActionUp(event, policyFlags); + break; + } + } + /** * Handles a motion event in touch exploring state. * @@ -390,60 +477,19 @@ public class TouchExplorer extends BaseEventStreamTransformation MotionEvent event, MotionEvent rawEvent, int policyFlags) { switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: - handleActionDownStateTouchExploring(event, policyFlags); + // We should have already received ACTION_DOWN. Ignore. break; case MotionEvent.ACTION_POINTER_DOWN: - handleActionPointerDownStateTouchExploring(); + handleActionPointerDown(); break; case MotionEvent.ACTION_MOVE: handleActionMoveStateTouchExploring(event, rawEvent, policyFlags); break; case MotionEvent.ACTION_UP: - handleActionUpStateTouchExploring(event, policyFlags); + handleActionUp(event, policyFlags); + break; + default: break; - } - } - - /** - * Handles ACTION_DOWN while in the default touch exploring state. This event represents the - * first finger touching the screen. - */ - private void handleActionDownStateTouchExploring(MotionEvent event, int policyFlags) { - mAms.onTouchInteractionStart(); - - // If we still have not notified the user for the last - // touch, we figure out what to do. If were waiting - // we resent the delayed callback and wait again. - mSendHoverEnterAndMoveDelayed.cancel(); - mSendHoverExitDelayed.cancel(); - - // If a touch exploration gesture is in progress send events for its end. - if (mState.isTouchExplorationInProgress()) { - sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); - } - - // Avoid duplicated TYPE_TOUCH_INTERACTION_START event when 2nd tap of double - // tap. - if (!mGestureDetector.firstTapDetected()) { - mSendTouchExplorationEndDelayed.forceSendAndRemove(); - mSendTouchInteractionEndDelayed.forceSendAndRemove(); - sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_START); - } else { - // Let gesture to handle to avoid duplicated TYPE_TOUCH_INTERACTION_END event. - mSendTouchInteractionEndDelayed.cancel(); - } - - if (!mGestureDetector.firstTapDetected() && !mState.isTouchExplorationInProgress()) { - if (!mSendHoverEnterAndMoveDelayed.isPending()) { - // Deliver hover enter with a delay to have a chance - // to detect what the user is trying to do. - final int pointerId = mReceivedPointerTracker.getPrimaryPointerId(); - final int pointerIdBits = (1 << pointerId); - mSendHoverEnterAndMoveDelayed.post(event, true, pointerIdBits, policyFlags); - } else { - // Cache the event until we discern exploration from gesturing. - mSendHoverEnterAndMoveDelayed.addEvent(event); - } } } @@ -451,7 +497,7 @@ public class TouchExplorer extends BaseEventStreamTransformation * Handles ACTION_POINTER_DOWN when in the touch exploring state. This event represents an * additional finger touching the screen. */ - private void handleActionPointerDownStateTouchExploring() { + private void handleActionPointerDown() { // Another finger down means that if we have not started to deliver // hover events, we will not have to. The code for ACTION_MOVE will // decide what we will actually do next. @@ -459,10 +505,10 @@ public class TouchExplorer extends BaseEventStreamTransformation mSendHoverExitDelayed.cancel(); } /** - * Handles ACTION_MOVE while in the initial touch exploring state. This is where transitions to + * Handles ACTION_MOVE while in the touch interacting state. This is where transitions to * delegating and dragging states are handled. */ - private void handleActionMoveStateTouchExploring( + private void handleActionMoveStateTouchInteracting( MotionEvent event, MotionEvent rawEvent, int policyFlags) { final int pointerId = mReceivedPointerTracker.getPrimaryPointerId(); final int pointerIndex = event.findPointerIndex(pointerId); @@ -474,41 +520,14 @@ public class TouchExplorer extends BaseEventStreamTransformation if (mSendHoverEnterAndMoveDelayed.isPending()) { // Cache the event until we discern exploration from gesturing. mSendHoverEnterAndMoveDelayed.addEvent(event); - } else if (mState.isTouchExplorationInProgress()) { - sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags); - sendMotionEvent( - event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags); } break; case 2: + // Make sure we don't have any pending transitions to touch exploration + mSendHoverEnterAndMoveDelayed.cancel(); + mSendHoverExitDelayed.cancel(); // More than one pointer so the user is not touch exploring // and now we have to decide whether to delegate or drag. - if (mSendHoverEnterAndMoveDelayed.isPending()) { - // We have not started sending events so cancel - // scheduled sending events. - mSendHoverEnterAndMoveDelayed.cancel(); - mSendHoverExitDelayed.cancel(); - } else if (mState.isTouchExplorationInProgress()) { - // If the user is touch exploring the second pointer may be - // performing a double tap to activate an item without need - // for the user to lift his exploring finger. - // It is *important* to use the distance traveled by the pointers - // on the screen which may or may not be magnified. - final float deltaX = - mReceivedPointerTracker.getReceivedPointerDownX(pointerId) - - rawEvent.getX(pointerIndex); - final float deltaY = - mReceivedPointerTracker.getReceivedPointerDownY(pointerId) - - rawEvent.getY(pointerIndex); - final double moveDelta = Math.hypot(deltaX, deltaY); - if (moveDelta < mDoubleTapSlop) { - break; - } - // We are sending events so send exit and gesture - // end since we transition to another state. - sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); - } - // Remove move history before send injected non-move events event = MotionEvent.obtainNoHistory(event); if (isDraggingGesture(event)) { @@ -525,19 +544,6 @@ public class TouchExplorer extends BaseEventStreamTransformation } break; default: - // More than one pointer so the user is not touch exploring - // and now we have to decide whether to delegate or drag. - if (mSendHoverEnterAndMoveDelayed.isPending()) { - // We have not started sending events so cancel - // scheduled sending events. - mSendHoverEnterAndMoveDelayed.cancel(); - mSendHoverExitDelayed.cancel(); - } else { - // We are sending events so send exit and gesture - // end since we transition to another state. - sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); - } - // More than two pointers are delegated to the view hierarchy. mState.startDelegating(); event = MotionEvent.obtainNoHistory(event); @@ -547,14 +553,13 @@ public class TouchExplorer extends BaseEventStreamTransformation } /** - * Handles ACTION_UP while in the initial touch exploring state. This event represents all - * fingers being lifted from the screen. + * Handles ACTION_UP while in the touch interacting state. This event represents all fingers + * being lifted from the screen. */ - private void handleActionUpStateTouchExploring(MotionEvent event, int policyFlags) { + private void handleActionUp(MotionEvent event, int policyFlags) { mAms.onTouchInteractionEnd(); final int pointerId = event.getPointerId(event.getActionIndex()); final int pointerIdBits = (1 << pointerId); - if (mSendHoverEnterAndMoveDelayed.isPending()) { // If we have not delivered the enter schedule an exit. mSendHoverExitDelayed.post(event, pointerIdBits, policyFlags); @@ -562,12 +567,68 @@ public class TouchExplorer extends BaseEventStreamTransformation // The user is touch exploring so we send events for end. sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); } - if (!mSendTouchInteractionEndDelayed.isPending()) { mSendTouchInteractionEndDelayed.post(); } } + /** + * Handles move events while touch exploring. this is also where we drag or delegate based on + * the number of fingers moving on the screen. + */ + private void handleActionMoveStateTouchExploring( + MotionEvent event, MotionEvent rawEvent, int policyFlags) { + final int pointerId = mReceivedPointerTracker.getPrimaryPointerId(); + final int pointerIdBits = (1 << pointerId); + final int pointerIndex = event.findPointerIndex(pointerId); + switch (event.getPointerCount()) { + case 1: + // Touch exploration. + sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags); + sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags); + break; + case 2: + if (mSendHoverEnterAndMoveDelayed.isPending()) { + // We have not started sending events so cancel + // scheduled sending events. + mSendHoverEnterAndMoveDelayed.cancel(); + mSendHoverExitDelayed.cancel(); + } + // If the user is touch exploring the second pointer may be + // performing a double tap to activate an item without need + // for the user to lift his exploring finger. + // It is *important* to use the distance traveled by the pointers + // on the screen which may or may not be magnified. + final float deltaX = + mReceivedPointerTracker.getReceivedPointerDownX(pointerId) + - rawEvent.getX(pointerIndex); + final float deltaY = + mReceivedPointerTracker.getReceivedPointerDownY(pointerId) + - rawEvent.getY(pointerIndex); + final double moveDelta = Math.hypot(deltaX, deltaY); + if (moveDelta > mDoubleTapSlop) { + // The user is trying to either delegate or drag. + handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags); + } else { + // Otherwise the double tap will be handled by the gesture detector. + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); + } + break; + default: + // Three or more fingers is something other than touch exploration. + if (mSendHoverEnterAndMoveDelayed.isPending()) { + // We have not started sending events so cancel + // scheduled sending events. + mSendHoverEnterAndMoveDelayed.cancel(); + mSendHoverExitDelayed.cancel(); + } else { + sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); + } + handleActionMoveStateTouchInteracting(event, rawEvent, policyFlags); + break; + } + } + /** * Handles a motion event in dragging state. * @@ -670,7 +731,6 @@ public class TouchExplorer extends BaseEventStreamTransformation // Send an event to the end of the drag gesture. sendMotionEvent(event, MotionEvent.ACTION_UP, pointerIdBits, policyFlags); } - mState.startTouchExploring(); } break; } } @@ -697,7 +757,6 @@ public class TouchExplorer extends BaseEventStreamTransformation mAms.onTouchInteractionEnd(); sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END); - mState.startTouchExploring(); } break; default: { // Deliver the event. @@ -717,7 +776,6 @@ public class TouchExplorer extends BaseEventStreamTransformation } mExitGestureDetectionModeDelayed.cancel(); - mState.startTouchExploring(); } /** @@ -731,8 +789,13 @@ public class TouchExplorer extends BaseEventStreamTransformation AccessibilityEvent event = AccessibilityEvent.obtain(type); event.setWindowId(mAms.getActiveWindowId()); accessibilityManager.sendAccessibilityEvent(event); - mState.onInjectedAccessibilityEvent(type); + if (DEBUG) { + Slog.d( + LOG_TAG, + "Sending accessibility event" + AccessibilityEvent.eventTypeToString(type)); + } } + mState.onInjectedAccessibilityEvent(type); } /** @@ -915,6 +978,10 @@ public class TouchExplorer extends BaseEventStreamTransformation MAX_DRAGGING_ANGLE_COS); } + public TouchState getState() { + return mState; + } + /** * Class for delayed exiting from gesture detecting mode. */ @@ -947,8 +1014,7 @@ public class TouchExplorer extends BaseEventStreamTransformation private int mPointerIdBits; private int mPolicyFlags; - public void post(MotionEvent event, boolean touchExplorationInProgress, - int pointerIdBits, int policyFlags) { + public void post(MotionEvent event, int pointerIdBits, int policyFlags) { cancel(); addEvent(event); mPointerIdBits = pointerIdBits; diff --git a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java index 820c1a7946351..17e969a1aa49e 100644 --- a/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java +++ b/services/accessibility/java/com/android/server/accessibility/gestures/TouchState.java @@ -41,20 +41,33 @@ public class TouchState { public static final int ALL_POINTER_ID_BITS = 0xFFFFFFFF; // States that the touch explorer can be in. - public static final int STATE_TOUCH_EXPLORING = 0x00000001; - public static final int STATE_DRAGGING = 0x00000002; - public static final int STATE_DELEGATING = 0x00000003; - public static final int STATE_GESTURE_DETECTING = 0x00000004; + // In the clear state the user is not touching the screen. + public static final int STATE_CLEAR = 0; + // The user is touching the screen and we are trying to figure out their intent. + // This state gets its name from the TYPE_TOUCH_INTERACTION start and end accessibility events. + public static final int STATE_TOUCH_INTERACTING = 1; + // The user is explicitly exploring the screen. + public static final int STATE_TOUCH_EXPLORING = 2; + // the user is dragging with two fingers. + public static final int STATE_DRAGGING = 3; + // The user is performing some other two finger gesture which we pass through to the view + // hierarchy as a one-finger gesture e.g. two-finger scrolling. + public static final int STATE_DELEGATING = 4; + // The user is performing something that might be a gesture. + public static final int STATE_GESTURE_DETECTING = 5; - @IntDef({STATE_TOUCH_EXPLORING, STATE_DRAGGING, STATE_DELEGATING, STATE_GESTURE_DETECTING}) + @IntDef({ + STATE_CLEAR, + STATE_TOUCH_INTERACTING, + STATE_TOUCH_EXPLORING, + STATE_DRAGGING, + STATE_DELEGATING, + STATE_GESTURE_DETECTING + }) public @interface State {} // The current state of the touch explorer. - private int mState = STATE_TOUCH_EXPLORING; - // Whether touch exploration is in progress. - // TODO: Add separate states to represent intend detection and actual touch exploration so that - // only one variable describes the state. - private boolean mTouchExplorationInProgress; + private int mState = STATE_CLEAR; // Helper class to track received pointers. // Todo: collapse or hide this class so multiple classes don't modify it. private final ReceivedPointerTracker mReceivedPointerTracker; @@ -69,8 +82,7 @@ public class TouchState { /** Clears the internal shared state. */ public void clear() { - mState = STATE_TOUCH_EXPLORING; - mTouchExplorationInProgress = false; + setState(STATE_CLEAR); // Reset the pointer trackers. mReceivedPointerTracker.clear(); mInjectedPointerTracker.clear(); @@ -94,18 +106,33 @@ public class TouchState { mReceivedPointerTracker.onMotionEvent(rawEvent); } - /** - * Updates the state in response to an accessibility event being sent from TouchExplorer. - * - * @param type The event type. - */ public void onInjectedAccessibilityEvent(int type) { + // The below state transitions go here because the related events are often sent on a + // delay. + // This allows state to accurately reflect the state in the moment. + // TODO: replaced the delayed event senders with delayed state transitions + // so that state transitions trigger events rather than events triggering state + // transitions. switch (type) { + case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START: + startTouchInteracting(); + break; + case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END: + clear(); + break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: - mTouchExplorationInProgress = true; + startTouchExploring(); break; case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: - mTouchExplorationInProgress = false; + startTouchInteracting(); + break; + case AccessibilityEvent.TYPE_GESTURE_DETECTION_START: + startGestureDetecting(); + break; + case AccessibilityEvent.TYPE_GESTURE_DETECTION_END: + startTouchInteracting(); + break; + default: break; } } @@ -117,6 +144,7 @@ public class TouchState { /** Transitions to a new state. */ public void setState(@State int state) { + if (mState == state) return; if (DEBUG) { Slog.i(LOG_TAG, getStateSymbolicName(mState) + "->" + getStateSymbolicName(state)); } @@ -159,26 +187,32 @@ public class TouchState { setState(STATE_DRAGGING); } - public boolean isTouchExplorationInProgress() { - return mTouchExplorationInProgress; + public boolean isTouchInteracting() { + return mState == STATE_TOUCH_INTERACTING; } - public void setTouchExplorationInProgress(boolean touchExplorationInProgress) { - mTouchExplorationInProgress = touchExplorationInProgress; + /** + * Transitions to the touch interacting state, where we attempt to figure out what the user is + * doing. + */ + public void startTouchInteracting() { + setState(STATE_TOUCH_INTERACTING); } + public boolean isClear() { + return mState == STATE_CLEAR; + } /** Returns a string representation of the current state. */ public String toString() { - return "TouchState { " - + "mState: " - + getStateSymbolicName(mState) - + ", mTouchExplorationInProgress" - + mTouchExplorationInProgress - + " }"; + return "TouchState { " + "mState: " + getStateSymbolicName(mState) + " }"; } /** Returns a string representation of the specified state. */ public static String getStateSymbolicName(int state) { switch (state) { + case STATE_CLEAR: + return "STATE_CLEAR"; + case STATE_TOUCH_INTERACTING: + return "STATE_TOUCH_INTERACTING"; case STATE_TOUCH_EXPLORING: return "STATE_TOUCH_EXPLORING"; case STATE_DRAGGING: 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 274ca368baa1c..104aacb5ef794 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,15 +16,18 @@ package com.android.server.accessibility.gestures; +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; +import static com.android.server.accessibility.gestures.TouchState.STATE_TOUCH_EXPLORING; + import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.mockito.Mockito.mock; import android.content.Context; import android.graphics.PointF; import android.os.SystemClock; import android.testing.DexmakerShareClassLoaderRule; -import android.util.DebugUtils; import android.view.InputDevice; import android.view.MotionEvent; @@ -46,10 +49,6 @@ import java.util.List; @RunWith(AndroidJUnit4.class) public class TouchExplorerTest { - public static final int STATE_TOUCH_EXPLORING = 0x00000001; - public static final int STATE_DRAGGING = 0x00000002; - public static final int STATE_DELEGATING = 0x00000004; - private static final int FLAG_1FINGER = 0x8000; private static final int FLAG_2FINGERS = 0x0100; private static final int FLAG_3FINGERS = 0x0200; @@ -112,7 +111,7 @@ public class TouchExplorerTest { @Test public void testTwoFingersMove_shouldDelegatingAndInjectActionDownPointerDown() { - goFromStateIdleTo(STATE_MOVING_2FINGERS); + goFromStateClearTo(STATE_MOVING_2FINGERS); assertState(STATE_DELEGATING); assertCapturedEvents( @@ -123,7 +122,7 @@ public class TouchExplorerTest { @Test public void testTwoFingersDrag_shouldDraggingAndActionDown() { - goFromStateIdleTo(STATE_DRAGGING_2FINGERS); + goFromStateClearTo(STATE_DRAGGING_2FINGERS); assertState(STATE_DRAGGING); assertCapturedEvents(MotionEvent.ACTION_DOWN); @@ -133,7 +132,7 @@ public class TouchExplorerTest { @Test public void testTwoFingersNotDrag_shouldDelegatingAndActionUpDownPointerDown() { // only from dragging state, and withMoveHistory no dragging - goFromStateIdleTo(STATE_PINCH_2FINGERS); + goFromStateClearTo(STATE_PINCH_2FINGERS); assertState(STATE_DELEGATING); assertCapturedEvents( @@ -146,7 +145,7 @@ public class TouchExplorerTest { @Test public void testThreeFingersMove_shouldDelegatingAnd3ActionPointerDown() { - goFromStateIdleTo(STATE_MOVING_3FINGERS); + goFromStateClearTo(STATE_MOVING_3FINGERS); assertState(STATE_DELEGATING); assertCapturedEvents( @@ -165,52 +164,47 @@ public class TouchExplorerTest { return new PointF(x, y); } - private static String stateToString(int state) { - return DebugUtils.valueToString(TouchExplorerTest.class, "STATE_", state); - } - - private void goFromStateIdleTo(int state) { + private void goFromStateClearTo(int state) { try { switch (state) { - case STATE_TOUCH_EXPLORING: { + case STATE_CLEAR: { mTouchExplorer.onDestroy(); } break; case STATE_TOUCH_EXPLORING_1FINGER: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING); send(downEvent()); } break; case STATE_TOUCH_EXPLORING_2FINGER: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_1FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_1FINGER); send(pointerDownEvent()); } break; case STATE_TOUCH_EXPLORING_3FINGER: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER); send(thirdPointerDownEvent()); } break; case STATE_MOVING_2FINGERS: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER); moveEachPointers(mLastEvent, p(10, 0), p(5, 10)); send(mLastEvent); } break; case STATE_DRAGGING_2FINGERS: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_2FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_2FINGER); moveEachPointers(mLastEvent, p(10, 0), p(10, 0)); send(mLastEvent); } break; case STATE_PINCH_2FINGERS: { - goFromStateIdleTo(STATE_DRAGGING_2FINGERS); + goFromStateClearTo(STATE_DRAGGING_2FINGERS); moveEachPointers(mLastEvent, p(10, 0), p(-10, 1)); send(mLastEvent); } break; case STATE_MOVING_3FINGERS: { - goFromStateIdleTo(STATE_TOUCH_EXPLORING_3FINGER); + goFromStateClearTo(STATE_TOUCH_EXPLORING_3FINGER); moveEachPointers(mLastEvent, p(1, 0), p(1, 0), p(1, 0)); send(mLastEvent); } @@ -219,7 +213,8 @@ public class TouchExplorerTest { throw new IllegalArgumentException("Illegal state: " + state); } } catch (Throwable t) { - throw new RuntimeException("Failed to go to state " + stateToString(state), t); + throw new RuntimeException("Failed to go to state " + + TouchState.getStateSymbolicName(state), t); } } @@ -234,9 +229,9 @@ public class TouchExplorerTest { } private void assertState(int expect) { - final String expectState = "STATE_" + stateToString(expect); - assertTrue(String.format("Expect state: %s, but: %s", expectState, mTouchExplorer), - mTouchExplorer.toString().contains(expectState)); + assertEquals( + TouchState.getStateSymbolicName(expect), + TouchState.getStateSymbolicName(mTouchExplorer.getState().getState())); } private void assertCapturedEvents(int... actionsInOrder) {