Make magnification mode switch accessible
To support accessibility of magnification mode switch,
We provide content description, state description and
click action.
Bug: 168278448
Test: Enable Talkback to do manually test
atest MagnificationModeSwitchTest
Change-Id: I1b94f3849f85db4f6dc2b801d0dd6ff40d0c87ed
This commit is contained in:
@@ -2678,6 +2678,14 @@
|
||||
<string name="accessibility_control_move_left">Move left</string>
|
||||
<!-- Action in accessibility menu to move the magnification window right. [CHAR LIMIT=30] -->
|
||||
<string name="accessibility_control_move_right">Move right</string>
|
||||
<!-- Content description for magnification mode switch. [CHAR LIMIT=NONE] -->
|
||||
<string name="magnification_mode_switch_description">Magnification switch</string>
|
||||
<!-- A11y state description for magnification mode switch that device is in full-screen mode. [CHAR LIMIT=NONE] -->
|
||||
<string name="magnification_mode_switch_state_full_screen">Magnify entire screen</string>
|
||||
<!-- A11y state description for magnification mode switch that device is in window mode. [CHAR LIMIT=NONE] -->
|
||||
<string name="magnification_mode_switch_state_window">Magnify part of screen</string>
|
||||
<!-- Click action label for magnification switch. [CHAR LIMIT=NONE] -->
|
||||
<string name="magnification_mode_switch_click_label">Switch</string>
|
||||
|
||||
<!-- Device Controls strings -->
|
||||
<!-- Device Controls empty state, title [CHAR LIMIT=30] -->
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
|
||||
package com.android.systemui.accessibility;
|
||||
|
||||
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.Context;
|
||||
import android.content.pm.ActivityInfo;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.util.MathUtils;
|
||||
import android.view.Gravity;
|
||||
@@ -28,6 +31,8 @@ import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -71,6 +76,29 @@ class MagnificationModeSwitch {
|
||||
applyResourcesValues();
|
||||
mImageView.setImageResource(getIconResId(mMagnificationMode));
|
||||
mImageView.setOnTouchListener(this::onTouch);
|
||||
mImageView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
|
||||
@Override
|
||||
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
|
||||
super.onInitializeAccessibilityNodeInfo(host, info);
|
||||
info.setStateDescription(formatStateDescription());
|
||||
info.setContentDescription(mContext.getResources().getString(
|
||||
R.string.magnification_mode_switch_description));
|
||||
final AccessibilityAction clickAction = new AccessibilityAction(
|
||||
AccessibilityAction.ACTION_CLICK.getId(), mContext.getResources().getString(
|
||||
R.string.magnification_mode_switch_click_label));
|
||||
info.addAction(clickAction);
|
||||
info.setClickable(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean performAccessibilityAction(View host, int action, Bundle args) {
|
||||
if (action == AccessibilityAction.ACTION_CLICK.getId()) {
|
||||
handleSingleTap();
|
||||
return true;
|
||||
}
|
||||
return super.performAccessibilityAction(host, action, args);
|
||||
}
|
||||
});
|
||||
|
||||
mAnimationTask = () -> {
|
||||
mImageView.animate()
|
||||
@@ -81,6 +109,13 @@ class MagnificationModeSwitch {
|
||||
};
|
||||
}
|
||||
|
||||
private CharSequence formatStateDescription() {
|
||||
final int stringId = mMagnificationMode == ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW
|
||||
? R.string.magnification_mode_switch_state_window
|
||||
: R.string.magnification_mode_switch_state_full_screen;
|
||||
return mContext.getResources().getString(stringId);
|
||||
}
|
||||
|
||||
private void applyResourcesValues() {
|
||||
final int padding = mContext.getResources().getDimensionPixelSize(
|
||||
R.dimen.magnification_switch_button_padding);
|
||||
|
||||
@@ -22,11 +22,14 @@ import static android.view.MotionEvent.ACTION_CANCEL;
|
||||
import static android.view.MotionEvent.ACTION_DOWN;
|
||||
import static android.view.MotionEvent.ACTION_MOVE;
|
||||
import static android.view.MotionEvent.ACTION_UP;
|
||||
import static android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction.ACTION_CLICK;
|
||||
|
||||
import static com.android.systemui.accessibility.MagnificationModeSwitch.getIconResId;
|
||||
|
||||
import static junit.framework.Assert.assertEquals;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.hasItems;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||
import static org.mockito.ArgumentMatchers.anyLong;
|
||||
@@ -45,10 +48,12 @@ import android.view.View;
|
||||
import android.view.ViewConfiguration;
|
||||
import android.view.ViewPropertyAnimator;
|
||||
import android.view.WindowManager;
|
||||
import android.view.accessibility.AccessibilityNodeInfo;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.systemui.R;
|
||||
import com.android.systemui.SysuiTestCase;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -142,13 +147,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
resetMockImageViewAndAnimator();
|
||||
listener.onTouch(mSpyImageView, MotionEvent.obtain(
|
||||
0, ViewConfiguration.getTapTimeout(), ACTION_UP, 100, 100, 0));
|
||||
verify(mViewPropertyAnimator).cancel();
|
||||
verify(mSpyImageView).setImageResource(
|
||||
getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
|
||||
verify(mWindowManager).removeView(mSpyImageView);
|
||||
final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
|
||||
assertEquals(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW, actualMode);
|
||||
verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -222,6 +221,34 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
assertShowButtonAnimation();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initializeA11yNode_showWindowModeButton_expectedValues() {
|
||||
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
|
||||
final AccessibilityNodeInfo nodeInfo = new AccessibilityNodeInfo();
|
||||
|
||||
mSpyImageView.onInitializeAccessibilityNodeInfo(nodeInfo);
|
||||
|
||||
assertEquals(mContext.getString(R.string.magnification_mode_switch_description),
|
||||
nodeInfo.getContentDescription());
|
||||
assertEquals(mContext.getString(R.string.magnification_mode_switch_state_window),
|
||||
nodeInfo.getStateDescription());
|
||||
assertThat(nodeInfo.getActionList(),
|
||||
hasItems(new AccessibilityNodeInfo.AccessibilityAction(
|
||||
ACTION_CLICK.getId(), mContext.getResources().getString(
|
||||
R.string.magnification_mode_switch_click_label))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void performA11yActions_showWindowModeButton_verifyTapAction() {
|
||||
mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);
|
||||
resetMockImageViewAndAnimator();
|
||||
|
||||
mSpyImageView.performAccessibilityAction(
|
||||
ACTION_CLICK.getId(), null);
|
||||
|
||||
verifyTapAction(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);
|
||||
}
|
||||
|
||||
private void assertModeUnchanged(int expectedMode) {
|
||||
final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
|
||||
@@ -254,4 +281,19 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
|
||||
Mockito.reset(mSpyImageView);
|
||||
initMockImageViewAndAnimator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the tap behaviour including the image of the button and the magnification mode.
|
||||
*
|
||||
* @param expectedMode the expected mode after tapping
|
||||
*/
|
||||
private void verifyTapAction(int expectedMode) {
|
||||
verify(mViewPropertyAnimator).cancel();
|
||||
verify(mSpyImageView).setImageResource(
|
||||
getIconResId(expectedMode));
|
||||
verify(mWindowManager).removeView(mSpyImageView);
|
||||
final int actualMode = Settings.Secure.getInt(mContext.getContentResolver(),
|
||||
Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE, 0);
|
||||
assertEquals(expectedMode, actualMode);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user