Merge "Adding accessibility support to the PIN lock screen."
This commit is contained in:
committed by
Android (Google) Code Review
commit
0ba9546b7b
@@ -28,6 +28,7 @@ import android.graphics.Paint.Align;
|
|||||||
import android.graphics.Region.Op;
|
import android.graphics.Region.Op;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.inputmethodservice.Keyboard.Key;
|
import android.inputmethodservice.Keyboard.Key;
|
||||||
|
import android.media.AudioManager;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.util.AttributeSet;
|
import android.util.AttributeSet;
|
||||||
@@ -39,6 +40,8 @@ import android.view.MotionEvent;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewConfiguration;
|
import android.view.ViewConfiguration;
|
||||||
import android.view.ViewGroup.LayoutParams;
|
import android.view.ViewGroup.LayoutParams;
|
||||||
|
import android.view.accessibility.AccessibilityEvent;
|
||||||
|
import android.view.accessibility.AccessibilityManager;
|
||||||
import android.widget.PopupWindow;
|
import android.widget.PopupWindow;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
@@ -175,7 +178,6 @@ public class KeyboardView extends View implements View.OnClickListener {
|
|||||||
private boolean mShowTouchPoints = true;
|
private boolean mShowTouchPoints = true;
|
||||||
private int mPopupPreviewX;
|
private int mPopupPreviewX;
|
||||||
private int mPopupPreviewY;
|
private int mPopupPreviewY;
|
||||||
private int mWindowY;
|
|
||||||
|
|
||||||
private int mLastX;
|
private int mLastX;
|
||||||
private int mLastY;
|
private int mLastY;
|
||||||
@@ -242,7 +244,11 @@ public class KeyboardView extends View implements View.OnClickListener {
|
|||||||
private boolean mKeyboardChanged;
|
private boolean mKeyboardChanged;
|
||||||
/** The canvas for the above mutable keyboard bitmap */
|
/** The canvas for the above mutable keyboard bitmap */
|
||||||
private Canvas mCanvas;
|
private Canvas mCanvas;
|
||||||
|
/** The accessibility manager for accessibility support */
|
||||||
|
private AccessibilityManager mAccessibilityManager;
|
||||||
|
/** The audio manager for accessibility support */
|
||||||
|
private AudioManager mAudioManager;
|
||||||
|
|
||||||
Handler mHandler = new Handler() {
|
Handler mHandler = new Handler() {
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(Message msg) {
|
public void handleMessage(Message msg) {
|
||||||
@@ -362,6 +368,10 @@ public class KeyboardView extends View implements View.OnClickListener {
|
|||||||
mSwipeThreshold = (int) (500 * getResources().getDisplayMetrics().density);
|
mSwipeThreshold = (int) (500 * getResources().getDisplayMetrics().density);
|
||||||
mDisambiguateSwipe = getResources().getBoolean(
|
mDisambiguateSwipe = getResources().getBoolean(
|
||||||
com.android.internal.R.bool.config_swipeDisambiguation);
|
com.android.internal.R.bool.config_swipeDisambiguation);
|
||||||
|
|
||||||
|
mAccessibilityManager = AccessibilityManager.getInstance(context);
|
||||||
|
mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
|
||||||
|
|
||||||
resetMultiTap();
|
resetMultiTap();
|
||||||
initGestureDetector();
|
initGestureDetector();
|
||||||
}
|
}
|
||||||
@@ -835,12 +845,16 @@ public class KeyboardView extends View implements View.OnClickListener {
|
|||||||
final Key[] keys = mKeys;
|
final Key[] keys = mKeys;
|
||||||
if (oldKeyIndex != mCurrentKeyIndex) {
|
if (oldKeyIndex != mCurrentKeyIndex) {
|
||||||
if (oldKeyIndex != NOT_A_KEY && keys.length > oldKeyIndex) {
|
if (oldKeyIndex != NOT_A_KEY && keys.length > oldKeyIndex) {
|
||||||
keys[oldKeyIndex].onReleased(mCurrentKeyIndex == NOT_A_KEY);
|
Key oldKey = keys[oldKeyIndex];
|
||||||
|
oldKey.onReleased(mCurrentKeyIndex == NOT_A_KEY);
|
||||||
invalidateKey(oldKeyIndex);
|
invalidateKey(oldKeyIndex);
|
||||||
|
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT, oldKey.codes[0]);
|
||||||
}
|
}
|
||||||
if (mCurrentKeyIndex != NOT_A_KEY && keys.length > mCurrentKeyIndex) {
|
if (mCurrentKeyIndex != NOT_A_KEY && keys.length > mCurrentKeyIndex) {
|
||||||
keys[mCurrentKeyIndex].onPressed();
|
Key newKey = keys[mCurrentKeyIndex];
|
||||||
|
newKey.onPressed();
|
||||||
invalidateKey(mCurrentKeyIndex);
|
invalidateKey(mCurrentKeyIndex);
|
||||||
|
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_HOVER_ENTER, newKey.codes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// If key changed and preview is on ...
|
// If key changed and preview is on ...
|
||||||
@@ -940,6 +954,47 @@ public class KeyboardView extends View implements View.OnClickListener {
|
|||||||
mPreviewText.setVisibility(VISIBLE);
|
mPreviewText.setVisibility(VISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void sendAccessibilityEvent(int eventType, int code) {
|
||||||
|
if (mAccessibilityManager.isEnabled()) {
|
||||||
|
AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
|
||||||
|
onInitializeAccessibilityEvent(event);
|
||||||
|
// Add text only if headset is used to avoid leaking passwords.
|
||||||
|
if (mAudioManager.isBluetoothA2dpOn() || mAudioManager.isWiredHeadsetOn()) {
|
||||||
|
String text = null;
|
||||||
|
switch (code) {
|
||||||
|
case Keyboard.KEYCODE_ALT:
|
||||||
|
text = mContext.getString(R.string.keyboardview_keycode_alt);
|
||||||
|
break;
|
||||||
|
case Keyboard.KEYCODE_CANCEL:
|
||||||
|
text = mContext.getString(R.string.keyboardview_keycode_cancel);
|
||||||
|
break;
|
||||||
|
case Keyboard.KEYCODE_DELETE:
|
||||||
|
text = mContext.getString(R.string.keyboardview_keycode_delete);
|
||||||
|
break;
|
||||||
|
case Keyboard.KEYCODE_DONE:
|
||||||
|
text = mContext.getString(R.string.keyboardview_keycode_done);
|
||||||
|
break;
|
||||||
|
case Keyboard.KEYCODE_MODE_CHANGE:
|
||||||
|
text = mContext.getString(R.string.keyboardview_keycode_mode_change);
|
||||||
|
break;
|
||||||
|
case Keyboard.KEYCODE_SHIFT:
|
||||||
|
text = mContext.getString(R.string.keyboardview_keycode_shift);
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
text = mContext.getString(R.string.keyboardview_keycode_enter);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
text = String.valueOf((char) code);
|
||||||
|
}
|
||||||
|
event.getText().add(text);
|
||||||
|
} else {
|
||||||
|
event.getText().add(mContext.getString(
|
||||||
|
R.string.keyboard_headset_required_to_hear_password));
|
||||||
|
}
|
||||||
|
mAccessibilityManager.sendAccessibilityEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests a redraw of the entire keyboard. Calling {@link #invalidate} is not sufficient
|
* Requests a redraw of the entire keyboard. Calling {@link #invalidate} is not sufficient
|
||||||
* because the keyboard renders the keys to an off-screen buffer and an invalidate() only
|
* because the keyboard renders the keys to an off-screen buffer and an invalidate() only
|
||||||
@@ -1074,11 +1129,49 @@ public class KeyboardView extends View implements View.OnClickListener {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private long mOldEventTime;
|
@Override
|
||||||
private boolean mUsedVelocity;
|
protected boolean dispatchHoverEvent(MotionEvent event) {
|
||||||
|
// If touch exploring is enabled we ignore touch events and transform
|
||||||
|
// the stream of hover events as touch events. This allows one consistent
|
||||||
|
// event stream to drive the keyboard since during touch exploring the
|
||||||
|
// first touch generates only hover events and tapping on the same
|
||||||
|
// location generates hover and touch events.
|
||||||
|
if (mAccessibilityManager.isEnabled()
|
||||||
|
&& mAccessibilityManager.isTouchExplorationEnabled()
|
||||||
|
&& event.getPointerCount() == 1) {
|
||||||
|
final int action = event.getAction();
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_HOVER_ENTER:
|
||||||
|
event.setAction(MotionEvent.ACTION_DOWN);
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_HOVER_MOVE:
|
||||||
|
event.setAction(MotionEvent.ACTION_MOVE);
|
||||||
|
break;
|
||||||
|
case MotionEvent.ACTION_HOVER_EXIT:
|
||||||
|
event.setAction(MotionEvent.ACTION_UP);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
onTouchEventInternal(event);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return super.dispatchHoverEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onTouchEvent(MotionEvent me) {
|
public boolean onTouchEvent(MotionEvent event) {
|
||||||
|
// If touch exploring is enabled we ignore touch events and transform
|
||||||
|
// the stream of hover events as touch events. This allows one consistent
|
||||||
|
// event stream to drive the keyboard since during touch exploring the
|
||||||
|
// first touch generates only hover events and tapping on the same
|
||||||
|
// location generates hover and touch events.
|
||||||
|
if (mAccessibilityManager.isEnabled()
|
||||||
|
&& mAccessibilityManager.isTouchExplorationEnabled()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return onTouchEventInternal(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean onTouchEventInternal(MotionEvent me) {
|
||||||
// Convert multi-pointer up/down events to single up/down events to
|
// Convert multi-pointer up/down events to single up/down events to
|
||||||
// deal with the typical multi-pointer behavior of two-thumb typing
|
// deal with the typical multi-pointer behavior of two-thumb typing
|
||||||
final int pointerCount = me.getPointerCount();
|
final int pointerCount = me.getPointerCount();
|
||||||
@@ -1126,7 +1219,6 @@ public class KeyboardView extends View implements View.OnClickListener {
|
|||||||
touchY += mVerticalCorrection;
|
touchY += mVerticalCorrection;
|
||||||
final int action = me.getAction();
|
final int action = me.getAction();
|
||||||
final long eventTime = me.getEventTime();
|
final long eventTime = me.getEventTime();
|
||||||
mOldEventTime = eventTime;
|
|
||||||
int keyIndex = getKeyIndices(touchX, touchY, null);
|
int keyIndex = getKeyIndices(touchX, touchY, null);
|
||||||
mPossiblePoly = possiblePoly;
|
mPossiblePoly = possiblePoly;
|
||||||
|
|
||||||
|
|||||||
@@ -3068,6 +3068,26 @@
|
|||||||
<!-- Description of the not pressed state of a ToggleButton. [CHAR LIMIT=NONE] -->
|
<!-- Description of the not pressed state of a ToggleButton. [CHAR LIMIT=NONE] -->
|
||||||
<string name="togglebutton_not_pressed">not pressed</string>
|
<string name="togglebutton_not_pressed">not pressed</string>
|
||||||
|
|
||||||
|
<!-- KeyboardView - accessibility support -->
|
||||||
|
<!-- Description of the Alt button in a KeyboardView. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboardview_keycode_alt">Alt</string>
|
||||||
|
<!-- Description of the Cancel button in a KeyboardView. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboardview_keycode_cancel">Cancel</string>
|
||||||
|
<!-- Description of the Delete button in a KeyboardView. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboardview_keycode_delete">Delete</string>
|
||||||
|
<!-- Description of the Done button in a KeyboardView. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboardview_keycode_done">Done</string>
|
||||||
|
<!-- Description of the Mode change button in a KeyboardView. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboardview_keycode_mode_change">Mode change</string>
|
||||||
|
<!-- Description of the Shift button in a KeyboardView. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboardview_keycode_shift">Shift</string>
|
||||||
|
<!-- Description of the Enter button in a KeyboardView. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboardview_keycode_enter">Enter</string>
|
||||||
|
|
||||||
|
<!-- Announce that a headset is required to hear keyboard keys while typing a password. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="keyboard_headset_required_to_hear_password">Key. Headset required to hear
|
||||||
|
keys while typing a password.</string>
|
||||||
|
|
||||||
<!-- Content description for the action bar "home" affordance. [CHAR LIMIT=NONE] -->
|
<!-- Content description for the action bar "home" affordance. [CHAR LIMIT=NONE] -->
|
||||||
<string name="action_bar_home_description">Navigate home</string>
|
<string name="action_bar_home_description">Navigate home</string>
|
||||||
<!-- Content description for the action bar "up" affordance. [CHAR LIMIT=NONE] -->
|
<!-- Content description for the action bar "up" affordance. [CHAR LIMIT=NONE] -->
|
||||||
|
|||||||
Reference in New Issue
Block a user