Merge "settings no hiding when voiceaccess or switchaccess is on" into main
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 572f6ff..1a37e2d 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -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>
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
index 84f1395..d9d9e37 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/MagnificationModeSwitch.java
@@ -20,12 +20,14 @@
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.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,10 +319,46 @@
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();
- mImageView.postOnAnimationDelayed(mFadeOutAnimationTask, mUiTimeout);
+ 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() {
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 8fd2bd6a..1a88545 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/accessibility/MagnificationModeSwitchTest.java
@@ -49,8 +49,11 @@
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 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;
@@ -186,6 +189,87 @@
}
@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);
executeFadeOutAnimation();