Keyboard shortcuts: A11Y fixes
* Letters are no more announced as capitals
* Focus now moves into the function key buttons (images)
* The keyboard shortcuts are not being verbalized individually
but instead the whole group is now verbalized in one go.
Bug: 29267887
Bug: 29259734
Bug: 29260915
Change-Id: Ie2cf519338cbb7d07c2d52b419dcf6b5a9e14147
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
index 461a03b..a6b120b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyboardShortcuts.java
@@ -16,6 +16,8 @@
package com.android.systemui.statusbar;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.Dialog;
@@ -45,9 +47,11 @@
import android.view.KeyboardShortcutInfo;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.AccessibilityDelegate;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager.KeyboardShortcutsReceiver;
+import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
@@ -65,6 +69,7 @@
import java.util.List;
import static android.content.Context.LAYOUT_INFLATER_SERVICE;
+import static android.view.View.IMPORTANT_FOR_ACCESSIBILITY_YES;
import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
/**
@@ -599,7 +604,7 @@
final int itemsSize = group.getItems().size();
for (int j = 0; j < itemsSize; j++) {
KeyboardShortcutInfo info = group.getItems().get(j);
- List<StringOrDrawable> shortcutKeys = getHumanReadableShortcutKeys(info);
+ List<StringDrawableContainer> shortcutKeys = getHumanReadableShortcutKeys(info);
if (shortcutKeys == null) {
// Ignore shortcuts we can't display keys for.
Log.w(TAG, "Keyboard Shortcut contains unsupported keys, skipping.");
@@ -629,25 +634,33 @@
.findViewById(R.id.keyboard_shortcuts_item_container);
final int shortcutKeysSize = shortcutKeys.size();
for (int k = 0; k < shortcutKeysSize; k++) {
- StringOrDrawable shortcutRepresentation = shortcutKeys.get(k);
- if (shortcutRepresentation.drawable != null) {
+ StringDrawableContainer shortcutRepresentation = shortcutKeys.get(k);
+ if (shortcutRepresentation.mDrawable != null) {
ImageView shortcutKeyIconView = (ImageView) inflater.inflate(
R.layout.keyboard_shortcuts_key_icon_view, shortcutItemsContainer,
false);
Bitmap bitmap = Bitmap.createBitmap(shortcutKeyIconItemHeightWidth,
shortcutKeyIconItemHeightWidth, Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
- shortcutRepresentation.drawable.setBounds(0, 0, canvas.getWidth(),
+ shortcutRepresentation.mDrawable.setBounds(0, 0, canvas.getWidth(),
canvas.getHeight());
- shortcutRepresentation.drawable.draw(canvas);
+ shortcutRepresentation.mDrawable.draw(canvas);
shortcutKeyIconView.setImageBitmap(bitmap);
+ shortcutKeyIconView.setImportantForAccessibility(
+ IMPORTANT_FOR_ACCESSIBILITY_YES);
+ shortcutKeyIconView.setAccessibilityDelegate(
+ new ShortcutKeyAccessibilityDelegate(
+ shortcutRepresentation.mString));
shortcutItemsContainer.addView(shortcutKeyIconView);
- } else if (shortcutRepresentation.string != null) {
+ } else if (shortcutRepresentation.mString != null) {
TextView shortcutKeyTextView = (TextView) inflater.inflate(
R.layout.keyboard_shortcuts_key_view, shortcutItemsContainer,
false);
shortcutKeyTextView.setMinimumWidth(shortcutKeyTextItemMinWidth);
- shortcutKeyTextView.setText(shortcutRepresentation.string);
+ shortcutKeyTextView.setText(shortcutRepresentation.mString);
+ shortcutKeyTextView.setAccessibilityDelegate(
+ new ShortcutKeyAccessibilityDelegate(
+ shortcutRepresentation.mString));
shortcutItemsContainer.addView(shortcutKeyTextView);
}
}
@@ -663,19 +676,20 @@
}
}
- private List<StringOrDrawable> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
- List<StringOrDrawable> shortcutKeys = getHumanReadableModifiers(info);
+ private List<StringDrawableContainer> getHumanReadableShortcutKeys(KeyboardShortcutInfo info) {
+ List<StringDrawableContainer> shortcutKeys = getHumanReadableModifiers(info);
if (shortcutKeys == null) {
return null;
}
- String displayLabelString = null;
- Drawable displayLabelDrawable = null;
+ String shortcutKeyString = null;
+ Drawable shortcutKeyDrawable = null;
if (info.getBaseCharacter() > Character.MIN_VALUE) {
- displayLabelString = String.valueOf(info.getBaseCharacter());
+ shortcutKeyString = String.valueOf(info.getBaseCharacter());
} else if (mSpecialCharacterDrawables.get(info.getKeycode()) != null) {
- displayLabelDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+ shortcutKeyDrawable = mSpecialCharacterDrawables.get(info.getKeycode());
+ shortcutKeyString = mSpecialCharacterNames.get(info.getKeycode());
} else if (mSpecialCharacterNames.get(info.getKeycode()) != null) {
- displayLabelString = mSpecialCharacterNames.get(info.getKeycode());
+ shortcutKeyString = mSpecialCharacterNames.get(info.getKeycode());
} else {
// Special case for shortcuts with no base key or keycode.
if (info.getKeycode() == KeyEvent.KEYCODE_UNKNOWN) {
@@ -683,27 +697,28 @@
}
char displayLabel = mKeyCharacterMap.getDisplayLabel(info.getKeycode());
if (displayLabel != 0) {
- displayLabelString = String.valueOf(displayLabel);
+ shortcutKeyString = String.valueOf(displayLabel);
} else {
displayLabel = mBackupKeyCharacterMap.getDisplayLabel(info.getKeycode());
if (displayLabel != 0) {
- displayLabelString = String.valueOf(displayLabel);
+ shortcutKeyString = String.valueOf(displayLabel);
} else {
return null;
}
}
}
- if (displayLabelDrawable != null) {
- shortcutKeys.add(new StringOrDrawable(displayLabelDrawable));
- } else if (displayLabelString != null) {
- shortcutKeys.add(new StringOrDrawable(displayLabelString));
+ if (shortcutKeyString != null) {
+ shortcutKeys.add(new StringDrawableContainer(shortcutKeyString, shortcutKeyDrawable));
+ } else {
+ Log.w(TAG, "Keyboard Shortcut does not have a text representation, skipping.");
}
+
return shortcutKeys;
}
- private List<StringOrDrawable> getHumanReadableModifiers(KeyboardShortcutInfo info) {
- final List<StringOrDrawable> shortcutKeys = new ArrayList<>();
+ private List<StringDrawableContainer> getHumanReadableModifiers(KeyboardShortcutInfo info) {
+ final List<StringDrawableContainer> shortcutKeys = new ArrayList<>();
int modifiers = info.getModifiers();
if (modifiers == 0) {
return shortcutKeys;
@@ -711,13 +726,9 @@
for(int i = 0; i < mModifierNames.size(); ++i) {
final int supportedModifier = mModifierNames.keyAt(i);
if ((modifiers & supportedModifier) != 0) {
- if (mModifierDrawables.get(supportedModifier) != null) {
- shortcutKeys.add(new StringOrDrawable(
- mModifierDrawables.get(supportedModifier)));
- } else {
- shortcutKeys.add(new StringOrDrawable(
- mModifierNames.get(supportedModifier)));
- }
+ shortcutKeys.add(new StringDrawableContainer(
+ mModifierNames.get(supportedModifier),
+ mModifierDrawables.get(supportedModifier)));
modifiers &= ~supportedModifier;
}
}
@@ -728,16 +739,31 @@
return shortcutKeys;
}
- private static final class StringOrDrawable {
- public String string;
- public Drawable drawable;
+ private final class ShortcutKeyAccessibilityDelegate extends AccessibilityDelegate {
+ private String mContentDescription;
- public StringOrDrawable(String string) {
- this.string = string;
+ ShortcutKeyAccessibilityDelegate(String contentDescription) {
+ mContentDescription = contentDescription;
}
- public StringOrDrawable(Drawable drawable) {
- this.drawable = drawable;
+ @Override
+ public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
+ super.onInitializeAccessibilityNodeInfo(host, info);
+ if (mContentDescription != null) {
+ info.setContentDescription(mContentDescription.toLowerCase());
+ }
+ }
+ }
+
+ private static final class StringDrawableContainer {
+ @NonNull
+ public String mString;
+ @Nullable
+ public Drawable mDrawable;
+
+ StringDrawableContainer(String string, Drawable drawable) {
+ mString = string;
+ mDrawable = drawable;
}
}
}