Loading services/accessibility/java/com/android/server/accessibility/TouchExplorer.java +42 −114 Original line number Diff line number Diff line Loading @@ -112,12 +112,6 @@ class TouchExplorer implements EventStreamTransformation { // Timeout before trying to decide what the user is trying to do. private final int mDetermineUserIntentTimeout; // Timeout within which we try to detect a tap. private final int mTapTimeout; // Slop between the down and up tap to be a tap. private final int mTouchSlop; // Slop between the first and second tap to be a double tap. private final int mDoubleTapSlop; Loading @@ -142,9 +136,6 @@ class TouchExplorer implements EventStreamTransformation { // Command for delayed sending of touch interaction end events. private final SendAccessibilityEventDelayed mSendTouchInteractionEndDelayed; // Command for delayed sending of a long press. private final PerformLongPressDelayed mPerformLongPressDelayed; // Command for exiting gesture detection mode after a timeout. private final ExitGestureDetectionModeDelayed mExitGestureDetectionModeDelayed; Loading Loading @@ -173,9 +164,6 @@ class TouchExplorer implements EventStreamTransformation { // Handle to the accessibility manager service. private final AccessibilityManagerService mAms; // Temporary rectangle to avoid instantiation. private final Rect mTempRect = new Rect(); // Temporary point to avoid instantiation. private final Point mTempPoint = new Point(); Loading Loading @@ -226,12 +214,9 @@ class TouchExplorer implements EventStreamTransformation { mAms = service; mReceivedPointerTracker = new ReceivedPointerTracker(); mInjectedPointerTracker = new InjectedPointerTracker(); mTapTimeout = ViewConfiguration.getTapTimeout(); mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout(); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop(); mHandler = new Handler(context.getMainLooper()); mPerformLongPressDelayed = new PerformLongPressDelayed(); mExitGestureDetectionModeDelayed = new ExitGestureDetectionModeDelayed(); mGestureLibrary = GestureLibraries.fromRawResource(context, R.raw.accessibility_gestures); mGestureLibrary.setOrientationStyle(8); Loading Loading @@ -299,7 +284,6 @@ class TouchExplorer implements EventStreamTransformation { // Remove all pending callbacks. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); mExitGestureDetectionModeDelayed.cancel(); mSendTouchExplorationEndDelayed.cancel(); mSendTouchInteractionEndDelayed.cancel(); Loading Loading @@ -437,7 +421,6 @@ class TouchExplorer implements EventStreamTransformation { // we resent the delayed callback and wait again. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); if (mSendTouchExplorationEndDelayed.isPending()) { mSendTouchExplorationEndDelayed.forceSendAndRemove(); Loading @@ -447,18 +430,7 @@ class TouchExplorer implements EventStreamTransformation { mSendTouchInteractionEndDelayed.forceSendAndRemove(); } // If we have the first tap, schedule a long press and break // since we do not want to schedule hover enter because // the delayed callback will kick in before the long click. // This would lead to a state transition resulting in long // pressing the item below the double taped area which is // not necessary where accessibility focus is. if (mDoubleTapDetector.firstTapDetected()) { // We got a tap now post a long press action. mPerformLongPressDelayed.post(event, policyFlags); break; } if (!mTouchExplorationInProgress) { if (!mDoubleTapDetector.firstTapDetected() && !mTouchExplorationInProgress) { if (!mSendHoverEnterAndMoveDelayed.isPending()) { // Deliver hover enter with a delay to have a chance // to detect what the user is trying to do. Loading @@ -478,7 +450,6 @@ class TouchExplorer implements EventStreamTransformation { // decide what we will actually do next. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); } break; case MotionEvent.ACTION_MOVE: { final int pointerId = receivedTracker.getPrimaryPointerId(); Loading Loading @@ -521,7 +492,6 @@ class TouchExplorer implements EventStreamTransformation { mVelocityTracker.clear(); mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); mExitGestureDetectionModeDelayed.post(); // Send accessibility event to announce the start // of gesture recognition. Loading @@ -532,28 +502,12 @@ class TouchExplorer implements EventStreamTransformation { // exploring so start sending events. mSendHoverEnterAndMoveDelayed.forceSendAndRemove(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags); } break; } } else { // Cancel the long press if pending and the user // moved more than the slop. if (mPerformLongPressDelayed.isPending()) { final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId) - rawEvent.getX(pointerIndex); final float deltaY = receivedTracker.getReceivedPointerDownY(pointerId) - rawEvent.getY(pointerIndex); final double moveDelta = Math.hypot(deltaX, deltaY); // The user has moved enough for us to decide. if (moveDelta > mTouchSlop) { mPerformLongPressDelayed.cancel(); } } if (mTouchExplorationInProgress) { sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags); sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, Loading @@ -569,9 +523,7 @@ class TouchExplorer implements EventStreamTransformation { // scheduled sending events. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); } else { mPerformLongPressDelayed.cancel(); if (mTouchExplorationInProgress) { // If the user is touch exploring the second pointer may be // performing a double tap to activate an item without need Loading Loading @@ -620,9 +572,7 @@ class TouchExplorer implements EventStreamTransformation { // scheduled sending events. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); } else { mPerformLongPressDelayed.cancel(); // We are sending events so send exit and gesture // end since we transition to another state. sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); Loading @@ -643,7 +593,6 @@ class TouchExplorer implements EventStreamTransformation { final int pointerId = event.getPointerId(event.getActionIndex()); final int pointerIdBits = (1 << pointerId); mPerformLongPressDelayed.cancel(); mVelocityTracker.clear(); if (mSendHoverEnterAndMoveDelayed.isPending()) { Loading Loading @@ -1110,6 +1059,7 @@ class TouchExplorer implements EventStreamTransformation { private final GestureDetector mGestureDetector; private boolean mFirstTapDetected; private boolean mDoubleTapDetected; private int mPolicyFlags; DoubleTapDetector(Context context) { mGestureDetector = new GestureDetector(context, this); Loading @@ -1117,6 +1067,7 @@ class TouchExplorer implements EventStreamTransformation { } public void onMotionEvent(MotionEvent event, int policyFlags) { mPolicyFlags = policyFlags; switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: mDoubleTapDetected = false; Loading @@ -1134,6 +1085,11 @@ class TouchExplorer implements EventStreamTransformation { return true; } @Override public void onLongPress(MotionEvent e) { maybeSendLongPress(e, mPolicyFlags); } @Override public boolean onSingleTapUp(MotionEvent event) { mFirstTapDetected = true; Loading @@ -1154,6 +1110,38 @@ class TouchExplorer implements EventStreamTransformation { return true; } private void maybeSendLongPress(MotionEvent event, int policyFlags) { if (!mDoubleTapDetected) { return; } clear(); // Pointers should not be zero when running this command. if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) { return; } final int pointerIndex = event.getActionIndex(); final int pointerId = event.getPointerId(pointerIndex); Point clickLocation = mTempPoint; final int result = computeClickLocation(clickLocation); if (result == CLICK_LOCATION_NONE) { return; } mLongPressingPointerId = pointerId; mLongPressingPointerDeltaX = (int) event.getX(pointerIndex) - clickLocation.x; mLongPressingPointerDeltaY = (int) event.getY(pointerIndex) - clickLocation.y; sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); mCurrentState = STATE_DELEGATING; sendDownForAllNotInjectedPointers(event, policyFlags); } private void maybeFinishDoubleTap(MotionEvent event, int policyFlags) { if (!mDoubleTapDetected) { return; Loading @@ -1169,7 +1157,6 @@ class TouchExplorer implements EventStreamTransformation { // Remove pending event deliveries. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); if (mSendTouchExplorationEndDelayed.isPending()) { mSendTouchExplorationEndDelayed.forceSendAndRemove(); Loading @@ -1178,8 +1165,8 @@ class TouchExplorer implements EventStreamTransformation { mSendTouchInteractionEndDelayed.forceSendAndRemove(); } final int pointerId = event.getPointerId(event.getActionIndex()); final int pointerIndex = event.findPointerIndex(pointerId); final int pointerIndex = event.getActionIndex(); final int pointerId = event.getPointerId(pointerIndex); Point clickLocation = mTempPoint; final int result = computeClickLocation(clickLocation); Loading Loading @@ -1305,65 +1292,6 @@ class TouchExplorer implements EventStreamTransformation { } } /** * Class for delayed sending of long press. */ private final class PerformLongPressDelayed implements Runnable { private MotionEvent mEvent; private int mPolicyFlags; public void post(MotionEvent prototype, int policyFlags) { mEvent = MotionEvent.obtain(prototype); mPolicyFlags = policyFlags; mHandler.postDelayed(this, ViewConfiguration.getLongPressTimeout()); } public void cancel() { if (mEvent != null) { mHandler.removeCallbacks(this); clear(); } } private boolean isPending() { return mHandler.hasCallbacks(this); } @Override public void run() { // Pointers should not be zero when running this command. if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) { return; } final int pointerId = mEvent.getPointerId(mEvent.getActionIndex()); final int pointerIndex = mEvent.findPointerIndex(pointerId); Point clickLocation = mTempPoint; final int result = computeClickLocation(clickLocation); if (result == CLICK_LOCATION_NONE) { return; } mLongPressingPointerId = pointerId; mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocation.x; mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocation.y; sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags); mCurrentState = STATE_DELEGATING; sendDownForAllNotInjectedPointers(mEvent, mPolicyFlags); clear(); } private void clear() { mEvent.recycle(); mEvent = null; mPolicyFlags = 0; } } /** * Class for delayed sending of hover enter and move events. */ Loading Loading
services/accessibility/java/com/android/server/accessibility/TouchExplorer.java +42 −114 Original line number Diff line number Diff line Loading @@ -112,12 +112,6 @@ class TouchExplorer implements EventStreamTransformation { // Timeout before trying to decide what the user is trying to do. private final int mDetermineUserIntentTimeout; // Timeout within which we try to detect a tap. private final int mTapTimeout; // Slop between the down and up tap to be a tap. private final int mTouchSlop; // Slop between the first and second tap to be a double tap. private final int mDoubleTapSlop; Loading @@ -142,9 +136,6 @@ class TouchExplorer implements EventStreamTransformation { // Command for delayed sending of touch interaction end events. private final SendAccessibilityEventDelayed mSendTouchInteractionEndDelayed; // Command for delayed sending of a long press. private final PerformLongPressDelayed mPerformLongPressDelayed; // Command for exiting gesture detection mode after a timeout. private final ExitGestureDetectionModeDelayed mExitGestureDetectionModeDelayed; Loading Loading @@ -173,9 +164,6 @@ class TouchExplorer implements EventStreamTransformation { // Handle to the accessibility manager service. private final AccessibilityManagerService mAms; // Temporary rectangle to avoid instantiation. private final Rect mTempRect = new Rect(); // Temporary point to avoid instantiation. private final Point mTempPoint = new Point(); Loading Loading @@ -226,12 +214,9 @@ class TouchExplorer implements EventStreamTransformation { mAms = service; mReceivedPointerTracker = new ReceivedPointerTracker(); mInjectedPointerTracker = new InjectedPointerTracker(); mTapTimeout = ViewConfiguration.getTapTimeout(); mDetermineUserIntentTimeout = ViewConfiguration.getDoubleTapTimeout(); mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop(); mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop(); mHandler = new Handler(context.getMainLooper()); mPerformLongPressDelayed = new PerformLongPressDelayed(); mExitGestureDetectionModeDelayed = new ExitGestureDetectionModeDelayed(); mGestureLibrary = GestureLibraries.fromRawResource(context, R.raw.accessibility_gestures); mGestureLibrary.setOrientationStyle(8); Loading Loading @@ -299,7 +284,6 @@ class TouchExplorer implements EventStreamTransformation { // Remove all pending callbacks. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); mExitGestureDetectionModeDelayed.cancel(); mSendTouchExplorationEndDelayed.cancel(); mSendTouchInteractionEndDelayed.cancel(); Loading Loading @@ -437,7 +421,6 @@ class TouchExplorer implements EventStreamTransformation { // we resent the delayed callback and wait again. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); if (mSendTouchExplorationEndDelayed.isPending()) { mSendTouchExplorationEndDelayed.forceSendAndRemove(); Loading @@ -447,18 +430,7 @@ class TouchExplorer implements EventStreamTransformation { mSendTouchInteractionEndDelayed.forceSendAndRemove(); } // If we have the first tap, schedule a long press and break // since we do not want to schedule hover enter because // the delayed callback will kick in before the long click. // This would lead to a state transition resulting in long // pressing the item below the double taped area which is // not necessary where accessibility focus is. if (mDoubleTapDetector.firstTapDetected()) { // We got a tap now post a long press action. mPerformLongPressDelayed.post(event, policyFlags); break; } if (!mTouchExplorationInProgress) { if (!mDoubleTapDetector.firstTapDetected() && !mTouchExplorationInProgress) { if (!mSendHoverEnterAndMoveDelayed.isPending()) { // Deliver hover enter with a delay to have a chance // to detect what the user is trying to do. Loading @@ -478,7 +450,6 @@ class TouchExplorer implements EventStreamTransformation { // decide what we will actually do next. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); } break; case MotionEvent.ACTION_MOVE: { final int pointerId = receivedTracker.getPrimaryPointerId(); Loading Loading @@ -521,7 +492,6 @@ class TouchExplorer implements EventStreamTransformation { mVelocityTracker.clear(); mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); mExitGestureDetectionModeDelayed.post(); // Send accessibility event to announce the start // of gesture recognition. Loading @@ -532,28 +502,12 @@ class TouchExplorer implements EventStreamTransformation { // exploring so start sending events. mSendHoverEnterAndMoveDelayed.forceSendAndRemove(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, policyFlags); } break; } } else { // Cancel the long press if pending and the user // moved more than the slop. if (mPerformLongPressDelayed.isPending()) { final float deltaX = receivedTracker.getReceivedPointerDownX(pointerId) - rawEvent.getX(pointerIndex); final float deltaY = receivedTracker.getReceivedPointerDownY(pointerId) - rawEvent.getY(pointerIndex); final double moveDelta = Math.hypot(deltaX, deltaY); // The user has moved enough for us to decide. if (moveDelta > mTouchSlop) { mPerformLongPressDelayed.cancel(); } } if (mTouchExplorationInProgress) { sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags); sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits, Loading @@ -569,9 +523,7 @@ class TouchExplorer implements EventStreamTransformation { // scheduled sending events. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); } else { mPerformLongPressDelayed.cancel(); if (mTouchExplorationInProgress) { // If the user is touch exploring the second pointer may be // performing a double tap to activate an item without need Loading Loading @@ -620,9 +572,7 @@ class TouchExplorer implements EventStreamTransformation { // scheduled sending events. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); } else { mPerformLongPressDelayed.cancel(); // We are sending events so send exit and gesture // end since we transition to another state. sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); Loading @@ -643,7 +593,6 @@ class TouchExplorer implements EventStreamTransformation { final int pointerId = event.getPointerId(event.getActionIndex()); final int pointerIdBits = (1 << pointerId); mPerformLongPressDelayed.cancel(); mVelocityTracker.clear(); if (mSendHoverEnterAndMoveDelayed.isPending()) { Loading Loading @@ -1110,6 +1059,7 @@ class TouchExplorer implements EventStreamTransformation { private final GestureDetector mGestureDetector; private boolean mFirstTapDetected; private boolean mDoubleTapDetected; private int mPolicyFlags; DoubleTapDetector(Context context) { mGestureDetector = new GestureDetector(context, this); Loading @@ -1117,6 +1067,7 @@ class TouchExplorer implements EventStreamTransformation { } public void onMotionEvent(MotionEvent event, int policyFlags) { mPolicyFlags = policyFlags; switch (event.getActionMasked()) { case MotionEvent.ACTION_DOWN: mDoubleTapDetected = false; Loading @@ -1134,6 +1085,11 @@ class TouchExplorer implements EventStreamTransformation { return true; } @Override public void onLongPress(MotionEvent e) { maybeSendLongPress(e, mPolicyFlags); } @Override public boolean onSingleTapUp(MotionEvent event) { mFirstTapDetected = true; Loading @@ -1154,6 +1110,38 @@ class TouchExplorer implements EventStreamTransformation { return true; } private void maybeSendLongPress(MotionEvent event, int policyFlags) { if (!mDoubleTapDetected) { return; } clear(); // Pointers should not be zero when running this command. if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) { return; } final int pointerIndex = event.getActionIndex(); final int pointerId = event.getPointerId(pointerIndex); Point clickLocation = mTempPoint; final int result = computeClickLocation(clickLocation); if (result == CLICK_LOCATION_NONE) { return; } mLongPressingPointerId = pointerId; mLongPressingPointerDeltaX = (int) event.getX(pointerIndex) - clickLocation.x; mLongPressingPointerDeltaY = (int) event.getY(pointerIndex) - clickLocation.y; sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags); mCurrentState = STATE_DELEGATING; sendDownForAllNotInjectedPointers(event, policyFlags); } private void maybeFinishDoubleTap(MotionEvent event, int policyFlags) { if (!mDoubleTapDetected) { return; Loading @@ -1169,7 +1157,6 @@ class TouchExplorer implements EventStreamTransformation { // Remove pending event deliveries. mSendHoverEnterAndMoveDelayed.cancel(); mSendHoverExitDelayed.cancel(); mPerformLongPressDelayed.cancel(); if (mSendTouchExplorationEndDelayed.isPending()) { mSendTouchExplorationEndDelayed.forceSendAndRemove(); Loading @@ -1178,8 +1165,8 @@ class TouchExplorer implements EventStreamTransformation { mSendTouchInteractionEndDelayed.forceSendAndRemove(); } final int pointerId = event.getPointerId(event.getActionIndex()); final int pointerIndex = event.findPointerIndex(pointerId); final int pointerIndex = event.getActionIndex(); final int pointerId = event.getPointerId(pointerIndex); Point clickLocation = mTempPoint; final int result = computeClickLocation(clickLocation); Loading Loading @@ -1305,65 +1292,6 @@ class TouchExplorer implements EventStreamTransformation { } } /** * Class for delayed sending of long press. */ private final class PerformLongPressDelayed implements Runnable { private MotionEvent mEvent; private int mPolicyFlags; public void post(MotionEvent prototype, int policyFlags) { mEvent = MotionEvent.obtain(prototype); mPolicyFlags = policyFlags; mHandler.postDelayed(this, ViewConfiguration.getLongPressTimeout()); } public void cancel() { if (mEvent != null) { mHandler.removeCallbacks(this); clear(); } } private boolean isPending() { return mHandler.hasCallbacks(this); } @Override public void run() { // Pointers should not be zero when running this command. if (mReceivedPointerTracker.getLastReceivedEvent().getPointerCount() == 0) { return; } final int pointerId = mEvent.getPointerId(mEvent.getActionIndex()); final int pointerIndex = mEvent.findPointerIndex(pointerId); Point clickLocation = mTempPoint; final int result = computeClickLocation(clickLocation); if (result == CLICK_LOCATION_NONE) { return; } mLongPressingPointerId = pointerId; mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocation.x; mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocation.y; sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags); mCurrentState = STATE_DELEGATING; sendDownForAllNotInjectedPointers(mEvent, mPolicyFlags); clear(); } private void clear() { mEvent.recycle(); mEvent = null; mPolicyFlags = 0; } } /** * Class for delayed sending of hover enter and move events. */ Loading