From 28e2938771afafcea668be47239e6bebc0e4d6a4 Mon Sep 17 00:00:00 2001 From: ryanlwlin Date: Wed, 23 Sep 2020 22:47:55 +0800 Subject: [PATCH] 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 --- packages/SystemUI/res/values/strings.xml | 8 +++ .../MagnificationModeSwitch.java | 35 ++++++++++++ .../MagnificationModeSwitchTest.java | 56 ++++++++++++++++--- 3 files changed, 92 insertions(+), 7 deletions(-) diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml index 2427d36076c58..b08ec130b760a 100644 --- a/packages/SystemUI/res/values/strings.xml +++ b/packages/SystemUI/res/values/strings.xml @@ -2678,6 +2678,14 @@ Move left Move right + + Magnification switch + + Magnify entire screen + + Magnify part of screen + + Switch diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java index 68e404e36bbaf..1af38970ea4c0 100644 --- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java +++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java @@ -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); diff --git a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java index 64e067396059d..0a51b26f4a85f 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java +++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java @@ -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); + } }