Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 700fd875 authored by Ryan Lin's avatar Ryan Lin Committed by Android (Google) Code Review
Browse files

Merge "Make magnification mode switch accessible"

parents da2e6636 28e29387
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -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] -->
+35 −0
Original line number Diff line number Diff line
@@ -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);
+49 −7
Original line number Diff line number Diff line
@@ -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);
    }
}