1717package com .android .internal .widget ;
1818
1919
20- import com .android .internal .R ;
21-
2220import android .content .Context ;
2321import android .content .res .Resources ;
2422import android .content .res .TypedArray ;
3937import android .util .Log ;
4038import android .view .MotionEvent ;
4139import android .view .View ;
40+ import android .view .accessibility .AccessibilityEvent ;
41+ import android .view .accessibility .AccessibilityManager ;
42+
43+ import com .android .internal .R ;
4244
4345import java .util .ArrayList ;
4446import java .util .List ;
@@ -401,6 +403,34 @@ public void setDisplayMode(DisplayMode displayMode) {
401403 invalidate ();
402404 }
403405
406+ private void notifyCellAdded () {
407+ if (mOnPatternListener != null ) {
408+ mOnPatternListener .onPatternCellAdded (mPattern );
409+ }
410+ sendAccessEvent (R .string .lockscreen_access_pattern_cell_added );
411+ }
412+
413+ private void notifyPatternStarted () {
414+ if (mOnPatternListener != null ) {
415+ mOnPatternListener .onPatternStart ();
416+ }
417+ sendAccessEvent (R .string .lockscreen_access_pattern_start );
418+ }
419+
420+ private void notifyPatternDetected () {
421+ if (mOnPatternListener != null ) {
422+ mOnPatternListener .onPatternDetected (mPattern );
423+ }
424+ sendAccessEvent (R .string .lockscreen_access_pattern_detected );
425+ }
426+
427+ private void notifyPatternCleared () {
428+ if (mOnPatternListener != null ) {
429+ mOnPatternListener .onPatternCleared ();
430+ }
431+ sendAccessEvent (R .string .lockscreen_access_pattern_cleared );
432+ }
433+
404434 /**
405435 * Clear the pattern.
406436 */
@@ -554,9 +584,7 @@ private Cell detectAndAddHit(float x, float y) {
554584 private void addCellToPattern (Cell newCell ) {
555585 mPatternDrawLookup [newCell .getRow ()][newCell .getColumn ()] = true ;
556586 mPattern .add (newCell );
557- if (mOnPatternListener != null ) {
558- mOnPatternListener .onPatternCellAdded (mPattern );
559- }
587+ notifyCellAdded ();
560588 }
561589
562590 // helper method to find which cell a point maps to
@@ -618,6 +646,27 @@ private int getColumnHit(float x) {
618646 return -1 ;
619647 }
620648
649+ @ Override
650+ public boolean onHoverEvent (MotionEvent event ) {
651+ if (AccessibilityManager .getInstance (mContext ).isTouchExplorationEnabled ()) {
652+ final int action = event .getAction ();
653+ switch (action ) {
654+ case MotionEvent .ACTION_HOVER_ENTER :
655+ event .setAction (MotionEvent .ACTION_DOWN );
656+ break ;
657+ case MotionEvent .ACTION_HOVER_MOVE :
658+ event .setAction (MotionEvent .ACTION_MOVE );
659+ break ;
660+ case MotionEvent .ACTION_HOVER_EXIT :
661+ event .setAction (MotionEvent .ACTION_UP );
662+ break ;
663+ }
664+ onTouchEvent (event );
665+ event .setAction (action );
666+ }
667+ return super .onHoverEvent (event );
668+ }
669+
621670 @ Override
622671 public boolean onTouchEvent (MotionEvent event ) {
623672 if (!mInputEnabled || !isEnabled ()) {
@@ -636,10 +685,8 @@ public boolean onTouchEvent(MotionEvent event) {
636685 return true ;
637686 case MotionEvent .ACTION_CANCEL :
638687 resetPattern ();
639- if (mOnPatternListener != null ) {
640- mPatternInProgress = false ;
641- mOnPatternListener .onPatternCleared ();
642- }
688+ mPatternInProgress = false ;
689+ notifyPatternCleared ();
643690 if (PROFILE_DRAWING ) {
644691 if (mDrawingProfilingStarted ) {
645692 Debug .stopMethodTracing ();
@@ -661,9 +708,9 @@ private void handleActionMove(MotionEvent event) {
661708 final int patternSizePreHitDetect = mPattern .size ();
662709 Cell hitCell = detectAndAddHit (x , y );
663710 final int patternSize = mPattern .size ();
664- if (hitCell != null && ( mOnPatternListener != null ) && ( patternSize == 1 ) ) {
711+ if (hitCell != null && patternSize == 1 ) {
665712 mPatternInProgress = true ;
666- mOnPatternListener . onPatternStart ();
713+ notifyPatternStarted ();
667714 }
668715 // note current x and y for rubber banding of in progress patterns
669716 final float dx = Math .abs (x - mInProgressX );
@@ -778,11 +825,17 @@ private void handleActionMove(MotionEvent event) {
778825 }
779826 }
780827
828+ private void sendAccessEvent (int resId ) {
829+ setContentDescription (mContext .getString (resId ));
830+ sendAccessibilityEvent (AccessibilityEvent .TYPE_VIEW_SELECTED );
831+ setContentDescription (null );
832+ }
833+
781834 private void handleActionUp (MotionEvent event ) {
782835 // report pattern detected
783- if (!mPattern .isEmpty () && mOnPatternListener != null ) {
836+ if (!mPattern .isEmpty ()) {
784837 mPatternInProgress = false ;
785- mOnPatternListener . onPatternDetected ( mPattern );
838+ notifyPatternDetected ( );
786839 invalidate ();
787840 }
788841 if (PROFILE_DRAWING ) {
@@ -798,13 +851,13 @@ private void handleActionDown(MotionEvent event) {
798851 final float x = event .getX ();
799852 final float y = event .getY ();
800853 final Cell hitCell = detectAndAddHit (x , y );
801- if (hitCell != null && mOnPatternListener != null ) {
854+ if (hitCell != null ) {
802855 mPatternInProgress = true ;
803856 mPatternDisplayMode = DisplayMode .Correct ;
804- mOnPatternListener . onPatternStart ();
805- } else if ( mOnPatternListener != null ) {
857+ notifyPatternStarted ();
858+ } else {
806859 mPatternInProgress = false ;
807- mOnPatternListener . onPatternCleared ();
860+ notifyPatternCleared ();
808861 }
809862 if (hitCell != null ) {
810863 final float startX = getCenterXForColumn (hitCell .column );
0 commit comments