Hides A11yMenu buttons that are restricted for the current user.
Bug: 347269196
Test: atest AccessibilityMenuServiceTest
Flag: com.android.systemui.accessibility.accessibilitymenu.hide_restricted_actions
Change-Id: I764c2a922bcd626b620fa9f45e5530d83ff3a069
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
index d674b6c..c881e07 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/Android.bp
@@ -37,6 +37,7 @@
"androidx.core_core",
"androidx.preference_preference",
"androidx.viewpager_viewpager",
+ "com_android_systemui_flags_lib",
"SettingsLibDisplayUtils",
"SettingsLibSettingsTheme",
"com_android_a11y_menu_flags_lib",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
index a98625f..a7b91c2 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/AndroidManifest.xml
@@ -18,6 +18,7 @@
package="com.android.systemui.accessibility.accessibilitymenu">
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
+ <uses-permission android:name="android.permission.MANAGE_USERS"/>
<application android:supportsRtl="true">
<service
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
index c1e43c9..6d79011 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
+++ b/packages/SystemUI/accessibility/accessibilitymenu/aconfig/accessibility.aconfig
@@ -29,3 +29,13 @@
purpose: PURPOSE_BUGFIX
}
}
+
+flag {
+ name: "hide_restricted_actions"
+ namespace: "accessibility"
+ description: "Hides shortcut buttons for possibly restricted actions like brightness/volume adjustment"
+ bug: "347269196"
+ metadata {
+ purpose: PURPOSE_BUGFIX
+ }
+}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
index 7b43b72..2e036e6 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/src/com/android/systemui/accessibility/accessibilitymenu/view/A11yMenuOverlayLayout.java
@@ -16,6 +16,8 @@
package com.android.systemui.accessibility.accessibilitymenu.view;
+import static android.os.UserManager.DISALLOW_ADJUST_VOLUME;
+import static android.os.UserManager.DISALLOW_CONFIG_BRIGHTNESS;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.View.ACCESSIBILITY_LIVE_REGION_POLITE;
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY;
@@ -24,6 +26,7 @@
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
+import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.Insets;
@@ -32,6 +35,8 @@
import android.hardware.display.DisplayManager;
import android.os.Handler;
import android.os.Looper;
+import android.os.UserHandle;
+import android.os.UserManager;
import android.view.Display;
import android.view.Gravity;
import android.view.LayoutInflater;
@@ -48,6 +53,7 @@
import androidx.annotation.NonNull;
import com.android.systemui.accessibility.accessibilitymenu.AccessibilityMenuService;
+import com.android.systemui.accessibility.accessibilitymenu.Flags;
import com.android.systemui.accessibility.accessibilitymenu.R;
import com.android.systemui.accessibility.accessibilitymenu.activity.A11yMenuSettingsActivity.A11yMenuPreferenceFragment;
import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut;
@@ -94,8 +100,6 @@
A11yMenuShortcut.ShortcutId.ID_SCREENSHOT_VALUE.ordinal()
};
-
-
private final AccessibilityMenuService mService;
private final WindowManager mWindowManager;
private final DisplayManager mDisplayManager;
@@ -195,11 +199,43 @@
for (int shortcutId :
(A11yMenuPreferenceFragment.isLargeButtonsEnabled(mService)
? LARGE_SHORTCUT_LIST_DEFAULT : SHORTCUT_LIST_DEFAULT)) {
- shortcutList.add(new A11yMenuShortcut(shortcutId));
+ if (!isShortcutRestricted(shortcutId)) {
+ shortcutList.add(new A11yMenuShortcut(shortcutId));
+ }
}
return shortcutList;
}
+ @SuppressLint("MissingPermission")
+ private boolean isShortcutRestricted(int shortcutId) {
+ if (!Flags.hideRestrictedActions()) {
+ return false;
+ }
+ final UserManager userManager = mService.getSystemService(UserManager.class);
+ if (userManager == null) {
+ return false;
+ }
+ final int userId = mService.getUserId();
+ final UserHandle userHandle = UserHandle.of(userId);
+ if (shortcutId == A11yMenuShortcut.ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal()
+ || shortcutId == A11yMenuShortcut.ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal()) {
+ if (userManager.hasUserRestriction(DISALLOW_CONFIG_BRIGHTNESS)
+ || (com.android.systemui.Flags.enforceBrightnessBaseUserRestriction()
+ && userManager.hasBaseUserRestriction(
+ DISALLOW_CONFIG_BRIGHTNESS, userHandle))) {
+ return true;
+ }
+ }
+ if (shortcutId == A11yMenuShortcut.ShortcutId.ID_VOLUME_DOWN_VALUE.ordinal()
+ || shortcutId == A11yMenuShortcut.ShortcutId.ID_VOLUME_UP_VALUE.ordinal()) {
+ if (userManager.hasUserRestriction(DISALLOW_ADJUST_VOLUME)
+ || userManager.hasBaseUserRestriction(DISALLOW_ADJUST_VOLUME, userHandle)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
/** Updates a11y menu layout position by configuring layout params. */
private void updateLayoutPosition() {
final Display display = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY);
@@ -326,8 +362,7 @@
return;
}
snackbar.setText(text);
- if (com.android.systemui.accessibility.accessibilitymenu
- .Flags.a11yMenuSnackbarLiveRegion()) {
+ if (Flags.a11yMenuSnackbarLiveRegion()) {
snackbar.setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
}
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
index 395354e..9d5a2e0 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/Android.bp
@@ -31,6 +31,7 @@
"androidx.test.core",
"androidx.test.runner",
"androidx.test.ext.junit",
+ "com_android_a11y_menu_flags_lib",
"compatibility-device-util-axt",
"platform-test-annotations",
"truth",
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
index 2be9245..40f71c5 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/AndroidManifest.xml
@@ -20,6 +20,7 @@
<!-- Needed to write to Settings.Secure to enable and disable the service under test. -->
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.CONTROL_DISPLAY_BRIGHTNESS"/>
+ <uses-permission android:name="android.permission.MANAGE_USERS"/>
<application android:debuggable="true">
<uses-library android:name="android.test.runner" />
diff --git a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
index 991ce12..d16617f 100644
--- a/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
+++ b/packages/SystemUI/accessibility/accessibilitymenu/tests/src/com/android/systemui/accessibility/accessibilitymenu/tests/AccessibilityMenuServiceTest.java
@@ -45,6 +45,10 @@
import android.hardware.display.DisplayManager;
import android.media.AudioManager;
import android.os.PowerManager;
+import android.os.UserManager;
+import android.platform.test.annotations.RequiresFlagsEnabled;
+import android.platform.test.flag.junit.CheckFlagsRule;
+import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import android.platform.uiautomator_helpers.WaitUtils;
import android.provider.Settings;
import android.util.Log;
@@ -59,6 +63,7 @@
import androidx.test.uiautomator.UiDevice;
import com.android.compatibility.common.util.TestUtils;
+import com.android.systemui.accessibility.accessibilitymenu.Flags;
import com.android.systemui.accessibility.accessibilitymenu.model.A11yMenuShortcut.ShortcutId;
import org.junit.After;
@@ -66,6 +71,7 @@
import org.junit.Assume;
import org.junit.Before;
import org.junit.BeforeClass;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -76,6 +82,9 @@
@RunWith(AndroidJUnit4.class)
public class AccessibilityMenuServiceTest {
+ @Rule
+ public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
+
private static final String TAG = "A11yMenuServiceTest";
private static final int CLICK_ID = AccessibilityNodeInfo.ACTION_CLICK;
@@ -121,26 +130,8 @@
sDisplayManager = context.getSystemService(DisplayManager.class);
unlockSignal();
- // Disable all a11yServices if any are active.
- if (!sAccessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
- TestUtils.waitUntil("Failed to disable all services",
- TIMEOUT_SERVICE_STATUS_CHANGE_S,
- () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty());
- }
+ enableA11yMenuService(context);
- // Enable a11yMenu service.
- Settings.Secure.putString(context.getContentResolver(),
- Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, SERVICE_NAME);
-
- TestUtils.waitUntil("Failed to enable service",
- TIMEOUT_SERVICE_STATUS_CHANGE_S,
- () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
- AccessibilityServiceInfo.FEEDBACK_ALL_MASK).stream().filter(
- info -> info.getId().contains(SERVICE_NAME)).count() == 1);
context.registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@@ -184,6 +175,29 @@
sUiDevice.pressHome();
}
+ private static void enableA11yMenuService(Context context) throws Throwable {
+ // Disable all a11yServices if any are active.
+ if (!sAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty()) {
+ Settings.Secure.putString(context.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
+ TestUtils.waitUntil("Failed to disable all services",
+ TIMEOUT_SERVICE_STATUS_CHANGE_S,
+ () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK).isEmpty());
+ }
+
+ // Enable a11yMenu service.
+ Settings.Secure.putString(context.getContentResolver(),
+ Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, SERVICE_NAME);
+
+ TestUtils.waitUntil("Failed to enable service",
+ TIMEOUT_SERVICE_STATUS_CHANGE_S,
+ () -> sAccessibilityManager.getEnabledAccessibilityServiceList(
+ AccessibilityServiceInfo.FEEDBACK_ALL_MASK).stream().filter(
+ info -> info.getId().contains(SERVICE_NAME)).count() == 1);
+ }
+
private static boolean isMenuVisible() {
sUiDevice.waitForIdle();
AccessibilityNodeInfo root = sUiAutomation.getRootInActiveWindow();
@@ -484,6 +498,54 @@
sOpenBlocked::get);
}
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_HIDE_RESTRICTED_ACTIONS)
+ public void testRestrictedActions_BrightnessNotAvailable() throws Throwable {
+ try {
+ setUserRestriction(UserManager.DISALLOW_CONFIG_BRIGHTNESS, true);
+ openMenu();
+
+ List<AccessibilityNodeInfo> buttons = getGridButtonList();
+ AccessibilityNodeInfo brightnessUpButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_BRIGHTNESS_UP_VALUE.ordinal()));
+ AccessibilityNodeInfo brightnessDownButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_BRIGHTNESS_DOWN_VALUE.ordinal()));
+
+ assertThat(brightnessUpButton).isNull();
+ assertThat(brightnessDownButton).isNull();
+ } finally {
+ setUserRestriction(UserManager.DISALLOW_CONFIG_BRIGHTNESS, false);
+ }
+ }
+
+ @Test
+ @RequiresFlagsEnabled(Flags.FLAG_HIDE_RESTRICTED_ACTIONS)
+ public void testRestrictedActions_VolumeNotAvailable() throws Throwable {
+ try {
+ setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, true);
+ openMenu();
+
+ List<AccessibilityNodeInfo> buttons = getGridButtonList();
+ AccessibilityNodeInfo volumeUpButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_VOLUME_UP_VALUE.ordinal()));
+ AccessibilityNodeInfo volumeDownButton = findGridButtonInfo(buttons,
+ String.valueOf(ShortcutId.ID_VOLUME_DOWN_VALUE.ordinal()));
+
+ assertThat(volumeUpButton).isNull();
+ assertThat(volumeDownButton).isNull();
+ } finally {
+ setUserRestriction(UserManager.DISALLOW_ADJUST_VOLUME, false);
+ }
+ }
+
+ private void setUserRestriction(String restriction, boolean isRestricted) throws Throwable {
+ final Context context = sInstrumentation.getTargetContext();
+ final UserManager userManager = context.getSystemService(UserManager.class);
+ userManager.setUserRestriction(restriction, isRestricted);
+ // Re-enable the service for the restriction to take effect.
+ enableA11yMenuService(context);
+ }
+
private static void unlockSignal() throws IOException {
// go/adb-cheats#unlock-screen
wakeUpScreen();