Loading services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java +66 −72 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.gesture.GestureStore; import android.gesture.GestureStroke; import android.gesture.Prediction; import android.util.Slog; import android.util.TypedValue; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.VelocityTracker; Loading Loading @@ -70,7 +71,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen // Indicates that we've collected enough data to be sure it could be a // gesture. private boolean mGestureConfirmed; private boolean mGestureStarted; // Indicates that motion events from the second pointer are being checked // for a double tap. Loading @@ -83,47 +84,39 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen // Policy flags of the previous event. private int mPolicyFlags; // The X of the previous event. private float mPreviousX; // These values track the previous point that was saved to use for gesture // detection. They are only updated when the user moves more than the // recognition threshold. private float mPreviousGestureX; private float mPreviousGestureY; // The Y of the previous event. private float mPreviousY; // The X of the down event. // These values track the previous point that was used to determine if there // was a transition into or out of gesture detection. They are updated when // the user moves more than the detection threshold. private float mBaseX; // The Y of the down event. private float mBaseY; private long mBaseTime; // Slop between the first and second tap to be a double tap. private final int mDoubleTapSlop; // The scaled velocity above which we detect gestures. private final int mScaledGestureDetectionVelocity; // This is the calculated movement threshold used track if the user is still // moving their finger. private final float mGestureDetectionThreshold; // Buffer for storing points for gesture detection. private final ArrayList<GesturePoint> mStrokeBuffer = new ArrayList<GesturePoint>(100); // Helper to track gesture velocity. private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); // The minimal delta between moves to add a gesture point. private static final int TOUCH_TOLERANCE = 3; // The minimal score for accepting a predicted gesture. private static final float MIN_PREDICTION_SCORE = 2.0f; // The velocity above which we detect gestures. Expressed in DIPs/Second. private static final int GESTURE_DETECTION_VELOCITY_DIP = 1000; // Constant used to calculate velocity in seconds. private static final int VELOCITY_UNITS_SECONDS = 1000; private static final int GESTURE_CONFIRM_MM = 10; private static final long CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS = 1000; private static final long CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS = 500; AccessibilityGestureDetector(Context context, Listener listener) { mListener = listener; mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop(); mGestureDetector = new GestureDetector(context, this); mGestureDetector.setOnDoubleTapListener(this); Loading @@ -132,15 +125,14 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen mGestureLibrary.setSequenceType(GestureStore.SEQUENCE_SENSITIVE); mGestureLibrary.load(); final float density = context.getResources().getDisplayMetrics().density; mScaledGestureDetectionVelocity = (int) (GESTURE_DETECTION_VELOCITY_DIP * density); mGestureDetectionThreshold = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1, context.getResources().getDisplayMetrics()) * GESTURE_CONFIRM_MM; } public boolean onMotionEvent(MotionEvent event, int policyFlags) { mVelocityTracker.addMovement(event); final float x = event.getX(); final float y = event.getY(); final long time = event.getEventTime(); mPolicyFlags = policyFlags; switch (event.getActionMasked()) { Loading @@ -148,54 +140,56 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen mDoubleTapDetected = false; mSecondFingerDoubleTap = false; mRecognizingGesture = true; mGestureConfirmed = false; mGestureStarted = false; mPreviousGestureX = x; mPreviousGestureY = y; mStrokeBuffer.clear(); mStrokeBuffer.add(new GesturePoint(x, y, time)); mBaseX = x; mBaseY = y; mPreviousX = x; mPreviousY = y; mStrokeBuffer.clear(); mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); mVelocityTracker.clear(); mVelocityTracker.addMovement(event); mBaseTime = time; break; case MotionEvent.ACTION_MOVE: if (mRecognizingGesture) { if (!mGestureConfirmed) { mVelocityTracker.addMovement(event); // It is *important* to use the distance traveled by the pointers // on the screen which may or may not be magnified. final float deltaX = mBaseX - event.getX(0); final float deltaY = mBaseY - event.getY(0); final float deltaX = mBaseX - x; final float deltaY = mBaseY - y; final double moveDelta = Math.hypot(deltaX, deltaY); // The user has moved enough for us to decide. if (moveDelta > mDoubleTapSlop) { // Check whether the user is performing a gesture. We // detect gestures if the pointer is moving above a // given velocity. mVelocityTracker.computeCurrentVelocity(VELOCITY_UNITS_SECONDS); final float maxAbsVelocity = Math.max( Math.abs(mVelocityTracker.getXVelocity(0)), Math.abs(mVelocityTracker.getYVelocity(0))); if (maxAbsVelocity > mScaledGestureDetectionVelocity) { // We have to perform gesture detection, so // notify the listener. mGestureConfirmed = true; if (moveDelta > mGestureDetectionThreshold) { // If the pointer has moved more than the threshold, // update the stored values. mBaseX = x; mBaseY = y; mBaseTime = time; // If this hasn't been confirmed as a gesture yet, send // the event. if (!mGestureStarted) { mGestureStarted = true; mListener.onGestureStarted(); } } else { // This won't match any gesture, so notify the // listener. final long timeDelta = time - mBaseTime; final long threshold = mGestureStarted ? CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS : CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS; // If the pointer hasn't moved for longer than the // timeout, cancel gesture detection. if (timeDelta > threshold) { cancelGesture(); mListener.onGestureCancelled(event, policyFlags); return false; } } } final float dX = Math.abs(x - mPreviousX); final float dY = Math.abs(y - mPreviousY); final float dX = Math.abs(x - mPreviousGestureX); final float dY = Math.abs(y - mPreviousGestureY); if (dX >= TOUCH_TOLERANCE || dY >= TOUCH_TOLERANCE) { mPreviousX = x; mPreviousY = y; mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); mPreviousGestureX = x; mPreviousGestureY = y; mStrokeBuffer.add(new GesturePoint(x, y, time)); } } break; Loading @@ -204,8 +198,8 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen if (maybeFinishDoubleTap(event, policyFlags)) { return true; } if (mGestureConfirmed) { mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); if (mGestureStarted) { mStrokeBuffer.add(new GesturePoint(x, y, time)); if (!recognizeGesture()) { mListener.onGestureCancelled(event, policyFlags); Loading @@ -223,7 +217,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen // If this was the second finger, attempt to recognize double // taps on it. mSecondFingerDoubleTap = true; mSecondPointerDownTime = event.getEventTime(); mSecondPointerDownTime = time; } else { // If there are more than two fingers down, stop watching // for a double tap. Loading Loading @@ -268,8 +262,8 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen mFirstTapDetected = false; mDoubleTapDetected = false; mSecondFingerDoubleTap = false; mGestureStarted = false; cancelGesture(); mVelocityTracker.clear(); } public boolean firstTapDetected() { Loading Loading @@ -323,7 +317,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen private void cancelGesture() { mRecognizingGesture = false; mGestureConfirmed = false; mGestureStarted = false; mStrokeBuffer.clear(); } Loading Loading
services/accessibility/java/com/android/server/accessibility/AccessibilityGestureDetector.java +66 −72 Original line number Diff line number Diff line Loading @@ -25,6 +25,7 @@ import android.gesture.GestureStore; import android.gesture.GestureStroke; import android.gesture.Prediction; import android.util.Slog; import android.util.TypedValue; import android.view.GestureDetector; import android.view.MotionEvent; import android.view.VelocityTracker; Loading Loading @@ -70,7 +71,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen // Indicates that we've collected enough data to be sure it could be a // gesture. private boolean mGestureConfirmed; private boolean mGestureStarted; // Indicates that motion events from the second pointer are being checked // for a double tap. Loading @@ -83,47 +84,39 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen // Policy flags of the previous event. private int mPolicyFlags; // The X of the previous event. private float mPreviousX; // These values track the previous point that was saved to use for gesture // detection. They are only updated when the user moves more than the // recognition threshold. private float mPreviousGestureX; private float mPreviousGestureY; // The Y of the previous event. private float mPreviousY; // The X of the down event. // These values track the previous point that was used to determine if there // was a transition into or out of gesture detection. They are updated when // the user moves more than the detection threshold. private float mBaseX; // The Y of the down event. private float mBaseY; private long mBaseTime; // Slop between the first and second tap to be a double tap. private final int mDoubleTapSlop; // The scaled velocity above which we detect gestures. private final int mScaledGestureDetectionVelocity; // This is the calculated movement threshold used track if the user is still // moving their finger. private final float mGestureDetectionThreshold; // Buffer for storing points for gesture detection. private final ArrayList<GesturePoint> mStrokeBuffer = new ArrayList<GesturePoint>(100); // Helper to track gesture velocity. private final VelocityTracker mVelocityTracker = VelocityTracker.obtain(); // The minimal delta between moves to add a gesture point. private static final int TOUCH_TOLERANCE = 3; // The minimal score for accepting a predicted gesture. private static final float MIN_PREDICTION_SCORE = 2.0f; // The velocity above which we detect gestures. Expressed in DIPs/Second. private static final int GESTURE_DETECTION_VELOCITY_DIP = 1000; // Constant used to calculate velocity in seconds. private static final int VELOCITY_UNITS_SECONDS = 1000; private static final int GESTURE_CONFIRM_MM = 10; private static final long CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS = 1000; private static final long CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS = 500; AccessibilityGestureDetector(Context context, Listener listener) { mListener = listener; mDoubleTapSlop = ViewConfiguration.get(context).getScaledDoubleTapSlop(); mGestureDetector = new GestureDetector(context, this); mGestureDetector.setOnDoubleTapListener(this); Loading @@ -132,15 +125,14 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen mGestureLibrary.setSequenceType(GestureStore.SEQUENCE_SENSITIVE); mGestureLibrary.load(); final float density = context.getResources().getDisplayMetrics().density; mScaledGestureDetectionVelocity = (int) (GESTURE_DETECTION_VELOCITY_DIP * density); mGestureDetectionThreshold = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_MM, 1, context.getResources().getDisplayMetrics()) * GESTURE_CONFIRM_MM; } public boolean onMotionEvent(MotionEvent event, int policyFlags) { mVelocityTracker.addMovement(event); final float x = event.getX(); final float y = event.getY(); final long time = event.getEventTime(); mPolicyFlags = policyFlags; switch (event.getActionMasked()) { Loading @@ -148,54 +140,56 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen mDoubleTapDetected = false; mSecondFingerDoubleTap = false; mRecognizingGesture = true; mGestureConfirmed = false; mGestureStarted = false; mPreviousGestureX = x; mPreviousGestureY = y; mStrokeBuffer.clear(); mStrokeBuffer.add(new GesturePoint(x, y, time)); mBaseX = x; mBaseY = y; mPreviousX = x; mPreviousY = y; mStrokeBuffer.clear(); mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); mVelocityTracker.clear(); mVelocityTracker.addMovement(event); mBaseTime = time; break; case MotionEvent.ACTION_MOVE: if (mRecognizingGesture) { if (!mGestureConfirmed) { mVelocityTracker.addMovement(event); // It is *important* to use the distance traveled by the pointers // on the screen which may or may not be magnified. final float deltaX = mBaseX - event.getX(0); final float deltaY = mBaseY - event.getY(0); final float deltaX = mBaseX - x; final float deltaY = mBaseY - y; final double moveDelta = Math.hypot(deltaX, deltaY); // The user has moved enough for us to decide. if (moveDelta > mDoubleTapSlop) { // Check whether the user is performing a gesture. We // detect gestures if the pointer is moving above a // given velocity. mVelocityTracker.computeCurrentVelocity(VELOCITY_UNITS_SECONDS); final float maxAbsVelocity = Math.max( Math.abs(mVelocityTracker.getXVelocity(0)), Math.abs(mVelocityTracker.getYVelocity(0))); if (maxAbsVelocity > mScaledGestureDetectionVelocity) { // We have to perform gesture detection, so // notify the listener. mGestureConfirmed = true; if (moveDelta > mGestureDetectionThreshold) { // If the pointer has moved more than the threshold, // update the stored values. mBaseX = x; mBaseY = y; mBaseTime = time; // If this hasn't been confirmed as a gesture yet, send // the event. if (!mGestureStarted) { mGestureStarted = true; mListener.onGestureStarted(); } } else { // This won't match any gesture, so notify the // listener. final long timeDelta = time - mBaseTime; final long threshold = mGestureStarted ? CANCEL_ON_PAUSE_THRESHOLD_STARTED_MS : CANCEL_ON_PAUSE_THRESHOLD_NOT_STARTED_MS; // If the pointer hasn't moved for longer than the // timeout, cancel gesture detection. if (timeDelta > threshold) { cancelGesture(); mListener.onGestureCancelled(event, policyFlags); return false; } } } final float dX = Math.abs(x - mPreviousX); final float dY = Math.abs(y - mPreviousY); final float dX = Math.abs(x - mPreviousGestureX); final float dY = Math.abs(y - mPreviousGestureY); if (dX >= TOUCH_TOLERANCE || dY >= TOUCH_TOLERANCE) { mPreviousX = x; mPreviousY = y; mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); mPreviousGestureX = x; mPreviousGestureY = y; mStrokeBuffer.add(new GesturePoint(x, y, time)); } } break; Loading @@ -204,8 +198,8 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen if (maybeFinishDoubleTap(event, policyFlags)) { return true; } if (mGestureConfirmed) { mStrokeBuffer.add(new GesturePoint(x, y, event.getEventTime())); if (mGestureStarted) { mStrokeBuffer.add(new GesturePoint(x, y, time)); if (!recognizeGesture()) { mListener.onGestureCancelled(event, policyFlags); Loading @@ -223,7 +217,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen // If this was the second finger, attempt to recognize double // taps on it. mSecondFingerDoubleTap = true; mSecondPointerDownTime = event.getEventTime(); mSecondPointerDownTime = time; } else { // If there are more than two fingers down, stop watching // for a double tap. Loading Loading @@ -268,8 +262,8 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen mFirstTapDetected = false; mDoubleTapDetected = false; mSecondFingerDoubleTap = false; mGestureStarted = false; cancelGesture(); mVelocityTracker.clear(); } public boolean firstTapDetected() { Loading Loading @@ -323,7 +317,7 @@ class AccessibilityGestureDetector extends GestureDetector.SimpleOnGestureListen private void cancelGesture() { mRecognizingGesture = false; mGestureConfirmed = false; mGestureStarted = false; mStrokeBuffer.clear(); } Loading