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

Commit 636aa9b3 authored by mincheli's avatar mincheli
Browse files

Applies Accessibility UI timeout for showing duration of magnification button

Users can change Time to take action (Accessibility timeout) settings
to make the magnification button showing duration aligned with
recommended a11y UI timeout.
Settings Page: Settings > Accessibility settings > Time to take action.
Demo video: b/167977099#comment2

Bug: 167977099
Test: atest MagnificationModeSwitchTest
Change-Id: I428b9d8221854edc476fcd455f3b9114b6b97ae9
parent 168d7918
Loading
Loading
Loading
Loading
+11 −4
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction;
import android.widget.ImageView;
@@ -48,15 +49,16 @@ class MagnificationModeSwitch {

    @VisibleForTesting
    static final long FADING_ANIMATION_DURATION_MS = 300;
    private static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000;
    // The button visible duration starting from the last showButton() called.
    private int mVisibleDuration = DEFAULT_FADE_OUT_ANIMATION_DELAY_MS;
    @VisibleForTesting
    static final int DEFAULT_FADE_OUT_ANIMATION_DELAY_MS = 3000;
    private int mUiTimeout;
    private final Runnable mFadeInAnimationTask;
    private final Runnable mFadeOutAnimationTask;
    @VisibleForTesting
    boolean mIsFadeOutAnimating = false;

    private final Context mContext;
    private final AccessibilityManager mAccessibilityManager;
    private final WindowManager mWindowManager;
    private final ImageView mImageView;
    private final PointF mLastDown = new PointF();
@@ -74,6 +76,7 @@ class MagnificationModeSwitch {
    @VisibleForTesting
    MagnificationModeSwitch(Context context, @NonNull ImageView imageView) {
        mContext = context;
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
        mWindowManager = (WindowManager) mContext.getSystemService(
                Context.WINDOW_SERVICE);
        mParams = createLayoutParams();
@@ -202,6 +205,10 @@ class MagnificationModeSwitch {
            mWindowManager.addView(mImageView, mParams);
            mIsVisible = true;
            mImageView.postOnAnimation(mFadeInAnimationTask);
            mUiTimeout = mAccessibilityManager.getRecommendedTimeoutMillis(
                    DEFAULT_FADE_OUT_ANIMATION_DELAY_MS,
                    AccessibilityManager.FLAG_CONTENT_ICONS
                            | AccessibilityManager.FLAG_CONTENT_CONTROLS);
        }
        if (mIsFadeOutAnimating) {
            mImageView.animate().cancel();
@@ -209,7 +216,7 @@ class MagnificationModeSwitch {
        }
        // Refresh the time slot of the fade-out task whenever this method is called.
        mImageView.removeCallbacks(mFadeOutAnimationTask);
        mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mVisibleDuration);
        mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mUiTimeout);
    }

    void onConfigurationChanged(int configDiff) {
+1 −2
Original line number Diff line number Diff line
@@ -72,8 +72,7 @@ public class WindowMagnification extends SystemUI implements WindowMagnifierCall
        super(context);
        mHandler = mainHandler;
        mLastConfiguration = new Configuration(context.getResources().getConfiguration());
        mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
                Context.ACCESSIBILITY_SERVICE);
        mAccessibilityManager = mContext.getSystemService(AccessibilityManager.class);
        mCommandQueue = commandQueue;
        mModeSwitchesController = modeSwitchesController;
        final WindowMagnificationController controller = new WindowMagnificationController(mContext,
+31 −4
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ 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.DEFAULT_FADE_OUT_ANIMATION_DELAY_MS;
import static com.android.systemui.accessibility.MagnificationModeSwitch.FADING_ANIMATION_DURATION_MS;
import static com.android.systemui.accessibility.MagnificationModeSwitch.getIconResId;

@@ -33,6 +34,7 @@ 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.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
@@ -48,6 +50,7 @@ import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewPropertyAnimator;
import android.view.WindowManager;
import android.view.accessibility.AccessibilityManager;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.ImageView;

@@ -74,6 +77,8 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {

    private ImageView mSpyImageView;
    @Mock
    private AccessibilityManager mAccessibilityManager;
    @Mock
    private WindowManager mWindowManager;
    @Mock
    private ViewPropertyAnimator mViewPropertyAnimator;
@@ -89,6 +94,7 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
                wm.getMaximumWindowMetrics()
        ).when(mWindowManager).getMaximumWindowMetrics();
        mContext.addMockSystemService(Context.WINDOW_SERVICE, mWindowManager);
        mContext.addMockSystemService(Context.ACCESSIBILITY_SERVICE, mAccessibilityManager);
        mSpyImageView = Mockito.spy(new ImageView(mContext));
        resetMockImageViewAndAnimator();

@@ -108,16 +114,37 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
    @Test
    public void showWindowModeButton_fullscreenMode_addViewAndSetImageResource() {
        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);

        verify(mSpyImageView).setImageResource(
                getIconResId(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW));
        verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class));
        assertShowFadingAnimation(FADE_IN_ALPHA);
        assertShowFadingAnimation(FADE_OUT_ALPHA);
    }

        ArgumentCaptor<Runnable> captor = ArgumentCaptor.forClass(Runnable.class);
        verify(mViewPropertyAnimator).withEndAction(captor.capture());
        verify(mWindowManager).addView(eq(mSpyImageView), any(WindowManager.LayoutParams.class));
    @Test
    public void showMagnificationButton_a11yTimeout_autoFadeOut() {
        final int a11yTimeout = 12345;
        when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn(
                a11yTimeout);

        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW);

        captor.getValue().run();
        verify(mAccessibilityManager).getRecommendedTimeoutMillis(
                DEFAULT_FADE_OUT_ANIMATION_DELAY_MS, AccessibilityManager.FLAG_CONTENT_ICONS
                        | AccessibilityManager.FLAG_CONTENT_CONTROLS);
        final ArgumentCaptor<Runnable> fadeOutCaptor = ArgumentCaptor.forClass(Runnable.class);
        final ArgumentCaptor<Long> fadeOutDelay = ArgumentCaptor.forClass(Long.class);
        verify(mSpyImageView).postOnAnimationDelayed(fadeOutCaptor.capture(),
                fadeOutDelay.capture());
        assertEquals(a11yTimeout, (long) fadeOutDelay.getValue());

        // Verify the end action after fade-out.
        fadeOutCaptor.getValue().run();
        final ArgumentCaptor<Runnable> endActionCaptor = ArgumentCaptor.forClass(Runnable.class);
        verify(mViewPropertyAnimator).withEndAction(endActionCaptor.capture());

        endActionCaptor.getValue().run();

        verify(mViewPropertyAnimator).cancel();
        verify(mWindowManager).removeView(mSpyImageView);