2626import android .graphics .Canvas ;
2727import android .graphics .drawable .BitmapDrawable ;
2828import android .os .Vibrator ;
29+ import android .text .TextUtils ;
2930import android .util .AttributeSet ;
3031import android .util .Log ;
3132import android .view .MotionEvent ;
3233import android .view .View ;
34+ import android .view .accessibility .AccessibilityEvent ;
35+ import android .view .accessibility .AccessibilityManager ;
3336
3437import com .android .internal .R ;
3538
@@ -64,6 +67,18 @@ public class WaveView extends View implements ValueAnimator.AnimatorUpdateListen
6467 private static final long DELAY_INCREMENT2 = 12 ; // increment per wave while not tracking
6568 private static final long WAVE_DELAY = WAVE_DURATION / WAVE_COUNT ; // initial propagation delay
6669
70+ /**
71+ * The scale by which to multiply the unlock handle width to compute the radius
72+ * in which it can be grabbed when accessibility is disabled.
73+ */
74+ private static final float GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_DISABLED = 0.5f ;
75+
76+ /**
77+ * The scale by which to multiply the unlock handle width to compute the radius
78+ * in which it can be grabbed when accessibility is enabled (more generous).
79+ */
80+ private static final float GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_ENABLED = 1.0f ;
81+
6782 private Vibrator mVibrator ;
6883 private OnTriggerListener mOnTriggerListener ;
6984 private ArrayList <DrawableHolder > mDrawables = new ArrayList <DrawableHolder >(3 );
@@ -450,6 +465,27 @@ public void run() {
450465 }
451466 };
452467
468+ @ Override
469+ public boolean onHoverEvent (MotionEvent event ) {
470+ if (AccessibilityManager .getInstance (mContext ).isTouchExplorationEnabled ()) {
471+ final int action = event .getAction ();
472+ switch (action ) {
473+ case MotionEvent .ACTION_HOVER_ENTER :
474+ event .setAction (MotionEvent .ACTION_DOWN );
475+ break ;
476+ case MotionEvent .ACTION_HOVER_MOVE :
477+ event .setAction (MotionEvent .ACTION_MOVE );
478+ break ;
479+ case MotionEvent .ACTION_HOVER_EXIT :
480+ event .setAction (MotionEvent .ACTION_UP );
481+ break ;
482+ }
483+ onTouchEvent (event );
484+ event .setAction (action );
485+ }
486+ return super .onHoverEvent (event );
487+ }
488+
453489 @ Override
454490 public boolean onTouchEvent (MotionEvent event ) {
455491 final int action = event .getAction ();
@@ -460,21 +496,12 @@ public boolean onTouchEvent(MotionEvent event) {
460496 case MotionEvent .ACTION_DOWN :
461497 removeCallbacks (mLockTimerActions );
462498 mFingerDown = true ;
463- setGrabbedState (OnTriggerListener .CENTER_HANDLE );
464- {
465- float x = mMouseX - mUnlockHalo .getX ();
466- float y = mMouseY - mUnlockHalo .getY ();
467- float dist = (float ) Math .hypot (x , y );
468- if (dist < mUnlockHalo .getWidth ()*0.5f ) {
469- if (mLockState == STATE_READY ) {
470- mLockState = STATE_START_ATTEMPT ;
471- }
472- }
473- }
499+ tryTransitionToStartAttemptState (event );
474500 handled = true ;
475501 break ;
476502
477503 case MotionEvent .ACTION_MOVE :
504+ tryTransitionToStartAttemptState (event );
478505 handled = true ;
479506 break ;
480507
@@ -501,6 +528,47 @@ public boolean onTouchEvent(MotionEvent event) {
501528 return handled ? true : super .onTouchEvent (event );
502529 }
503530
531+ /**
532+ * Tries to transition to start attempt state.
533+ *
534+ * @param event A motion event.
535+ */
536+ private void tryTransitionToStartAttemptState (MotionEvent event ) {
537+ final float dx = event .getX () - mUnlockHalo .getX ();
538+ final float dy = event .getY () - mUnlockHalo .getY ();
539+ float dist = (float ) Math .hypot (dx , dy );
540+ if (dist <= getScaledGrabHandleRadius ()) {
541+ setGrabbedState (OnTriggerListener .CENTER_HANDLE );
542+ if (mLockState == STATE_READY ) {
543+ mLockState = STATE_START_ATTEMPT ;
544+ if (AccessibilityManager .getInstance (mContext ).isEnabled ()) {
545+ announceUnlockHandle ();
546+ }
547+ }
548+ }
549+ }
550+
551+ /**
552+ * @return The radius in which the handle is grabbed scaled based on
553+ * whether accessibility is enabled.
554+ */
555+ private float getScaledGrabHandleRadius () {
556+ if (AccessibilityManager .getInstance (mContext ).isEnabled ()) {
557+ return GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_ENABLED * mUnlockHalo .getWidth ();
558+ } else {
559+ return GRAB_HANDLE_RADIUS_SCALE_ACCESSIBILITY_DISABLED * mUnlockHalo .getWidth ();
560+ }
561+ }
562+
563+ /**
564+ * Announces the unlock handle if accessibility is enabled.
565+ */
566+ private void announceUnlockHandle () {
567+ setContentDescription (mContext .getString (R .string .description_target_unlock_tablet ));
568+ sendAccessibilityEvent (AccessibilityEvent .TYPE_VIEW_FOCUSED );
569+ setContentDescription (null );
570+ }
571+
504572 /**
505573 * Triggers haptic feedback.
506574 */
0 commit comments