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

Commit c5c4babc authored by Isaac Chai's avatar Isaac Chai Committed by Android (Google) Code Review
Browse files

Merge "settings no hiding when voiceaccess or switchaccess is on" into main

parents 345a1793 a9474bb6
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -977,4 +977,13 @@
    Width in pixels of the Side FPS sensor.
    -->
    <integer name="config_sfpsSensorWidth">200</integer>

    <!--
    They are service names that, if enabled, will cause the magnification settings button
    to never hide after timeout.
    -->
    <string-array name="services_always_show_magnification_settings" translatable="false">
        <item>com.android.switchaccess.SwitchAccessService</item>
        <item>com.google.android.apps.accessibility.voiceaccess.JustSpeakService</item>
    </string-array>
</resources>
+41 −1
Original line number Diff line number Diff line
@@ -20,12 +20,14 @@ import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_
import static android.provider.Settings.Secure.ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW;
import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.annotation.NonNull;
import android.annotation.UiContext;
import android.content.ComponentCallbacks;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Insets;
import android.graphics.PixelFormat;
import android.graphics.Rect;
@@ -49,6 +51,8 @@ import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.res.R;

import java.util.Collections;
import java.util.Optional;
import java.util.Set;

/**
 * Shows/hides a {@link android.widget.ImageView} on the screen and changes the values of
@@ -315,11 +319,47 @@ class MagnificationModeSwitch implements MagnificationGestureDetector.OnGestureL
                    DEFAULT_FADE_OUT_ANIMATION_DELAY_MS,
                    AccessibilityManager.FLAG_CONTENT_ICONS
                            | AccessibilityManager.FLAG_CONTENT_CONTROLS);
            if (shouldAlwaysShowSettings()) {
                mUiTimeout = -1;
            }
        }
        // Refresh the time slot of the fade-out task whenever this method is called.
        stopFadeOutAnimation();
        if (mUiTimeout >= 0) {
            mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mUiTimeout);
        }
    }

    private boolean shouldAlwaysShowSettings() {
        try {
            var serviceNamesArray = mContext.getResources().getStringArray(
                    R.array.services_always_show_magnification_settings);
            if (serviceNamesArray.length == 0) {
                return false;
            }
            Set serviceNamesSet = Set.of(serviceNamesArray);

            var serviceInfoList = mAccessibilityManager
                    .getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
            for (var serviceInfo : serviceInfoList) {
                var serviceName = Optional.ofNullable(serviceInfo)
                        .map(AccessibilityServiceInfo::getResolveInfo)
                        .map(resolveInfo -> resolveInfo.serviceInfo)
                        .map(resolvedServiceInfo -> resolvedServiceInfo.name)
                        .orElse(null);
                if (serviceName == null) {
                    continue;
                }

                if (serviceNamesSet.contains(serviceName)) {
                    return true;
                }
            }
        } catch (Resources.NotFoundException nfe) {
            // No-op. Do not crash for not finding resources.
        }
        return false;
    }

    private void stopFadeOutAnimation() {
        mImageView.removeCallbacks(mFadeOutAnimationTask);
+85 −1
Original line number Diff line number Diff line
@@ -49,8 +49,11 @@ import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.accessibilityservice.AccessibilityServiceInfo;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ResolveInfo;
import android.content.pm.ServiceInfo;
import android.graphics.Insets;
import android.graphics.Rect;
import android.os.Handler;
@@ -71,8 +74,8 @@ import android.widget.ImageView;
import androidx.test.filters.SmallTest;

import com.android.internal.graphics.SfVsyncFrameCallbackProvider;
import com.android.systemui.res.R;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.res.R;

import org.junit.After;
import org.junit.Before;
@@ -185,6 +188,87 @@ public class MagnificationModeSwitchTest extends SysuiTestCase {
        verify(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), eq((long) a11yTimeout));
    }

    @Test
    public void showMagnificationButton_noA11yServicesRunning_postDelayedAnimationsWithTimeout() {
        final int a11yTimeout = 12345;
        when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn(
                a11yTimeout);
        when(mAccessibilityManager.getEnabledAccessibilityServiceList(anyInt()))
                .thenReturn(List.of());

        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);

        verify(mAccessibilityManager).getRecommendedTimeoutMillis(
                DEFAULT_FADE_OUT_ANIMATION_DELAY_MS, AccessibilityManager.FLAG_CONTENT_ICONS
                        | AccessibilityManager.FLAG_CONTENT_CONTROLS);
        verify(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), eq((long) a11yTimeout));
    }

    @Test
    public void showMagnificationButton_voiceAccessRunning_noTimeout() {
        var serviceInfo = createServiceInfoWithName(
                "com.google.android.apps.accessibility.voiceaccess.JustSpeakService");
        when(mAccessibilityManager.getEnabledAccessibilityServiceList(anyInt()))
                .thenReturn(List.of(serviceInfo));

        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);

        verify(mSpyImageView, never()).postOnAnimationDelayed(any(Runnable.class), anyLong());
    }

    @Test
    public void showMagnificationButton_switchAccessRunning_noTimeout() {
        var serviceInfo = createServiceInfoWithName(
                "com.android.switchaccess.SwitchAccessService");
        when(mAccessibilityManager.getEnabledAccessibilityServiceList(anyInt()))
                .thenReturn(List.of(serviceInfo));

        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);

        verify(mSpyImageView, never()).postOnAnimationDelayed(any(Runnable.class), anyLong());
    }

    @Test
    public void showMagnificationButton_switchAccessAndVoiceAccessBothRunning_noTimeout() {
        var switchAccessServiceInfo = createServiceInfoWithName(
                "com.android.switchaccess.SwitchAccessService");
        var voiceAccessServiceInfo = createServiceInfoWithName(
                "com.google.android.apps.accessibility.voiceaccess.JustSpeakService");
        when(mAccessibilityManager.getEnabledAccessibilityServiceList(anyInt()))
                .thenReturn(List.of(switchAccessServiceInfo, voiceAccessServiceInfo));

        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);

        verify(mSpyImageView, never()).postOnAnimationDelayed(any(Runnable.class), anyLong());
    }

    @Test
    public void showMagnificationButton_someOtherServiceRunning_postDelayedAnimationsWithTimeout() {
        final int a11yTimeout = 12345;
        when(mAccessibilityManager.getRecommendedTimeoutMillis(anyInt(), anyInt())).thenReturn(
                a11yTimeout);
        var serviceInfo1 = createServiceInfoWithName("com.test.someService1");
        var serviceInfo2 = createServiceInfoWithName("com.test.someService2");
        when(mAccessibilityManager.getEnabledAccessibilityServiceList(anyInt()))
                .thenReturn(List.of(serviceInfo1, serviceInfo2));

        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);

        verify(mAccessibilityManager).getRecommendedTimeoutMillis(
                DEFAULT_FADE_OUT_ANIMATION_DELAY_MS, AccessibilityManager.FLAG_CONTENT_ICONS
                        | AccessibilityManager.FLAG_CONTENT_CONTROLS);
        verify(mSpyImageView).postOnAnimationDelayed(any(Runnable.class), eq((long) a11yTimeout));
    }

    private AccessibilityServiceInfo createServiceInfoWithName(String name) {
        var resolveInfo = new ResolveInfo();
        resolveInfo.serviceInfo = new ServiceInfo();
        resolveInfo.serviceInfo.name = name;
        var serviceInfo = new AccessibilityServiceInfo();
        serviceInfo.setResolveInfo(resolveInfo);
        return serviceInfo;
    }

    @Test
    public void showMagnificationButton_windowModeAndFadingOut_verifyAnimationEndAction() {
        mMagnificationModeSwitch.showButton(ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN);