From 94621548c176c2bbba4100134337a9db5fba3d97 Mon Sep 17 00:00:00 2001 From: Riley Jones Date: Wed, 23 Oct 2024 21:25:38 +0000 Subject: [PATCH] Disabling elements on the A11y Shortcut setting subpage Elements on the subpage get disabled if there are no enabled shortcut targets for the relevant type. In the case of A11y button, the items on its fragment become unsearchable when the setting is disabled. Test: Manually verify conditions described above & in bug Bug: 349180207 Flag: com.android.settings.accessibility.fix_a11y_settings_search Change-Id: Id39e2eda6c9d1de4cdbfcbc22b8a1f443e2822d9 --- res/values/strings.xml | 2 + res/xml/accessibility_shortcuts_settings.xml | 5 +- .../AccessibilityButtonFragment.java | 19 ++++++- ...cessibilityButtonPreferenceController.java | 34 ++++++++++- ...utFromLockscreenPreferenceController.java} | 42 ++++++++++++-- .../AccessibilityButtonFragmentTest.java | 37 +++++++++++- ...ibilityButtonPreferenceControllerTest.java | 32 +++++++++++ ...omLockscreenPreferenceControllerTest.java} | 57 +++++++++++++++---- .../display/ColorContrastFragmentTest.java | 3 +- 9 files changed, 205 insertions(+), 26 deletions(-) rename src/com/android/settings/accessibility/{AccessibilityShortcutPreferenceController.java => HardwareShortcutFromLockscreenPreferenceController.java} (58%) rename tests/{unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceControllerTest.java => robotests/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceControllerTest.java} (56%) diff --git a/res/values/strings.xml b/res/values/strings.xml index ce2e3985b4e..7a646e09e70 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -5722,6 +5722,8 @@ Edit accessibility shortcuts Choose your shortcut for %1$s + + To use this, turn on the %1$s shortcut on an accessibility feature\'s page Continue diff --git a/res/xml/accessibility_shortcuts_settings.xml b/res/xml/accessibility_shortcuts_settings.xml index c8070564eb4..18ec9e927ba 100644 --- a/res/xml/accessibility_shortcuts_settings.xml +++ b/res/xml/accessibility_shortcuts_settings.xml @@ -19,7 +19,8 @@ xmlns:settings="http://schemas.android.com/apk/res-auto" android:key="accessibility_shortcuts_settings" android:persistent="false" - android:title="@string/accessibility_shortcuts_settings_title"> + android:title="@string/accessibility_shortcuts_settings_title" + settings:searchable="false"> + settings:controller="com.android.settings.accessibility.HardwareShortcutFromLockscreenPreferenceController"/> diff --git a/src/com/android/settings/accessibility/AccessibilityButtonFragment.java b/src/com/android/settings/accessibility/AccessibilityButtonFragment.java index 60e4bb28fea..116554d735a 100644 --- a/src/com/android/settings/accessibility/AccessibilityButtonFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityButtonFragment.java @@ -16,9 +16,14 @@ package com.android.settings.accessibility; -import android.app.settings.SettingsEnums; -import android.os.Bundle; +import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.os.Bundle; +import android.provider.Settings; + +import com.android.internal.accessibility.util.ShortcutUtils; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; @@ -61,5 +66,13 @@ public class AccessibilityButtonFragment extends DashboardFragment { } public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = - new BaseSearchIndexProvider(R.xml.accessibility_button_settings); + new BaseSearchIndexProvider(R.xml.accessibility_button_settings) { + @Override + protected boolean isPageSearchEnabled(Context context) { + // Page should be unsearchable if there are no active button targets + String targets = Settings.Secure.getStringForUser(context.getContentResolver(), + ShortcutUtils.convertToKey(SOFTWARE), context.getUserId()); + return targets != null && !targets.isEmpty(); + } + }; } diff --git a/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java index 68a765c9230..d9ee3cd31f7 100644 --- a/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java +++ b/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java @@ -16,9 +16,13 @@ package com.android.settings.accessibility; +import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; + import android.content.Context; import android.content.res.Resources; +import android.view.accessibility.AccessibilityManager; +import androidx.annotation.NonNull; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; @@ -32,14 +36,39 @@ import java.util.List; * Preference controller for accessibility button preference. */ public class AccessibilityButtonPreferenceController extends BasePreferenceController { - public AccessibilityButtonPreferenceController(Context context, String key) { super(context, key); } @Override public int getAvailabilityStatus() { - return AVAILABLE; + if (!com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) { + return AVAILABLE; + } else { + if (mContext.getSystemService(AccessibilityManager.class) + .getAccessibilityShortcutTargets(SOFTWARE).isEmpty()) { + return DISABLED_DEPENDENT_SETTING; + } else { + return AVAILABLE; + } + } + } + + @Override + public void updateState(@NonNull Preference preference) { + super.updateState(preference); + refreshSummary(preference); + } + + @Override + public @NonNull CharSequence getSummary() { + if (getAvailabilityStatus() == AVAILABLE) { + return ""; + } else { + return mContext.getString( + R.string.accessibility_shortcut_unassigned_setting_unavailable_summary, + AccessibilityUtil.getShortcutSummaryList(mContext, SOFTWARE)); + } } @Override @@ -47,7 +76,6 @@ public class AccessibilityButtonPreferenceController extends BasePreferenceContr super.displayPreference(screen); final Preference preference = screen.findPreference(getPreferenceKey()); preference.setTitle(getPreferenceTitleResource()); - } @Override diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceController.java b/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceController.java similarity index 58% rename from src/com/android/settings/accessibility/AccessibilityShortcutPreferenceController.java rename to src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceController.java index d204bb761db..a6d5b7bc7fe 100644 --- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceController.java +++ b/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceController.java @@ -15,6 +15,7 @@ */ package com.android.settings.accessibility; +import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE; import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; import static com.android.settings.accessibility.AccessibilityUtil.State.ON; @@ -22,16 +23,21 @@ import android.content.ContentResolver; import android.content.Context; import android.os.UserHandle; import android.provider.Settings; +import android.view.accessibility.AccessibilityManager; + +import androidx.annotation.NonNull; +import androidx.preference.Preference; import com.android.settings.R; import com.android.settings.core.TogglePreferenceController; /** - * Settings page for accessibility shortcut + * Setting to allow the hardware shortcut to turn on from the lock screen */ -public class AccessibilityShortcutPreferenceController extends TogglePreferenceController { - - public AccessibilityShortcutPreferenceController(Context context, String preferenceKey) { +public class HardwareShortcutFromLockscreenPreferenceController + extends TogglePreferenceController { + public HardwareShortcutFromLockscreenPreferenceController( + Context context, String preferenceKey) { super(context, preferenceKey); } @@ -56,7 +62,33 @@ public class AccessibilityShortcutPreferenceController extends TogglePreferenceC @Override public int getAvailabilityStatus() { - return AVAILABLE; + if (!com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) { + return AVAILABLE; + } else { + if (mContext.getSystemService(AccessibilityManager.class) + .getAccessibilityShortcutTargets(HARDWARE).isEmpty()) { + return DISABLED_DEPENDENT_SETTING; + } else { + return AVAILABLE; + } + } + } + + @Override + public void updateState(@NonNull Preference preference) { + super.updateState(preference); + refreshSummary(preference); + } + + @Override + public @NonNull CharSequence getSummary() { + if (getAvailabilityStatus() == AVAILABLE) { + return mContext.getString(R.string.accessibility_shortcut_description); + } else { + return mContext.getString( + R.string.accessibility_shortcut_unassigned_setting_unavailable_summary, + AccessibilityUtil.getShortcutSummaryList(mContext, HARDWARE)); + } } @Override diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java index 94312a60eee..386463a5666 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java @@ -19,6 +19,8 @@ package com.android.settings.accessibility; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; +import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.spy; @@ -39,6 +41,7 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.internal.accessibility.util.ShortcutUtils; import com.android.settings.R; import com.android.settings.testutils.XmlTestUtils; import com.android.settings.testutils.shadow.ShadowFragment; @@ -132,6 +135,7 @@ public class AccessibilityButtonFragmentTest { } @Test + @DisableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH) public void getNonIndexableKeys_existInXmlLayout() { final List niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER .getNonIndexableKeys(mContext); @@ -139,7 +143,38 @@ public class AccessibilityButtonFragmentTest { XmlTestUtils.getKeysFromPreferenceXml(mContext, R.xml.accessibility_button_settings); - assertThat(keys).containsAtLeastElementsIn(niks); + assertThat(keys).isNotNull(); + assertThat(niks).containsAtLeastElementsIn(keys); + } + + @Test + @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH) + public void getNonIndexableKeys_noTargets_doesNotExistInXmlLayout() { + Settings.Secure.putStringForUser(mContext.getContentResolver(), + ShortcutUtils.convertToKey(SOFTWARE), "", mContext.getUserId()); + final List niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(mContext); + final List keys = + XmlTestUtils.getKeysFromPreferenceXml(mContext, + R.xml.accessibility_button_settings); + + assertThat(keys).isNotNull(); + assertThat(niks).containsAtLeastElementsIn(keys); + } + + @Test + @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH) + public void getNonIndexableKeys_hasTargets_expectedKeys() { + Settings.Secure.putStringForUser(mContext.getContentResolver(), + ShortcutUtils.convertToKey(SOFTWARE), "Foo", mContext.getUserId()); + final List niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER + .getNonIndexableKeys(mContext); + + // Some keys should show up anyway, as they're flagged as unsearchable in the xml. + assertThat(niks).containsAtLeast( + "accessibility_button_preview", + "accessibility_button_footer", + "accessibility_button_or_gesture"); } private static class TestAccessibilityButtonFragment extends AccessibilityButtonFragment { diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java index 85aa77c1ab8..e5169cd0082 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java @@ -20,6 +20,10 @@ import static android.provider.Settings.Secure.NAVIGATION_MODE; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; +import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE; +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; + import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.when; @@ -31,12 +35,15 @@ import android.platform.test.annotations.EnableFlags; import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Flags; import android.provider.Settings; +import android.view.accessibility.AccessibilityManager; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; +import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settings.testutils.shadow.ShadowAccessibilityManager; import com.android.settingslib.search.SearchIndexableRaw; import org.junit.Before; @@ -48,11 +55,17 @@ import org.mockito.Spy; import org.mockito.junit.MockitoJUnit; import org.mockito.junit.MockitoRule; import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; import java.util.ArrayList; import java.util.List; /** Tests for {@link AccessibilityButtonPreferenceController}. */ +@Config(shadows = { + SettingsShadowResources.class, + com.android.settings.testutils.shadow.ShadowAccessibilityManager.class +}) @RunWith(RobolectricTestRunner.class) public class AccessibilityButtonPreferenceControllerTest { @@ -68,9 +81,12 @@ public class AccessibilityButtonPreferenceControllerTest { private PreferenceScreen mScreen; private Preference mPreference; private AccessibilityButtonPreferenceController mController; + private ShadowAccessibilityManager mShadowAccessibilityManager; @Before public void setUp() { + mShadowAccessibilityManager = Shadow.extract( + mContext.getSystemService(AccessibilityManager.class)); mController = new AccessibilityButtonPreferenceController(mContext, "test_key"); mPreference = new Preference(mContext); mPreference.setKey("test_key"); @@ -163,4 +179,20 @@ public class AccessibilityButtonPreferenceControllerTest { assertThat(raw.screenTitle).isEqualTo( mResources.getString(R.string.accessibility_shortcuts_settings_title)); } + + @Test + @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH) + public void getAvailabilityStatus_settingEmpty_disabled() { + mShadowAccessibilityManager.setAccessibilityShortcutTargets(SOFTWARE, List.of()); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); + } + + @Test + @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH) + public void getAvailabilityStatus_settingNotEmpty_available() { + mShadowAccessibilityManager.setAccessibilityShortcutTargets(SOFTWARE, List.of("Foo")); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } } diff --git a/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceControllerTest.java similarity index 56% rename from tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceControllerTest.java rename to tests/robotests/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceControllerTest.java index 7d903ee01a4..30541a6a2b6 100644 --- a/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceControllerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2020 The Android Open Source Project + * Copyright (C) 2024 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,36 +16,57 @@ package com.android.settings.accessibility; +import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE; import static com.android.settings.accessibility.AccessibilityUtil.State.OFF; import static com.android.settings.accessibility.AccessibilityUtil.State.ON; - -import androidx.test.core.app.ApplicationProvider; -import androidx.test.ext.junit.runners.AndroidJUnit4; +import static com.android.settings.core.BasePreferenceController.AVAILABLE; +import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING; import static com.google.common.truth.Truth.assertThat; import android.content.Context; import android.os.UserHandle; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; import android.provider.Settings; +import android.view.accessibility.AccessibilityManager; import androidx.preference.SwitchPreference; +import androidx.test.core.app.ApplicationProvider; + +import com.android.settings.testutils.shadow.SettingsShadowResources; +import com.android.settings.testutils.shadow.ShadowAccessibilityManager; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; +import org.robolectric.shadow.api.Shadow; -@RunWith(AndroidJUnit4.class) -public class AccessibilityShortcutPreferenceControllerTest { +import java.util.List; - private Context mContext; +@Config(shadows = { + SettingsShadowResources.class, + com.android.settings.testutils.shadow.ShadowAccessibilityManager.class +}) +@RunWith(RobolectricTestRunner.class) +public class HardwareShortcutFromLockscreenPreferenceControllerTest { + @Rule + public SetFlagsRule mSetFlagsRule = new SetFlagsRule(); + + private Context mContext = ApplicationProvider.getApplicationContext(); private SwitchPreference mPreference; - private AccessibilityShortcutPreferenceController mController; + private HardwareShortcutFromLockscreenPreferenceController mController; + private ShadowAccessibilityManager mShadowAccessibilityManager; @Before public void setUp() { - mContext = ApplicationProvider.getApplicationContext(); + mShadowAccessibilityManager = Shadow.extract( + mContext.getSystemService(AccessibilityManager.class)); mPreference = new SwitchPreference(mContext); - mController = new AccessibilityShortcutPreferenceController(mContext, + mController = new HardwareShortcutFromLockscreenPreferenceController(mContext, "accessibility_shortcut_preference"); } @@ -89,4 +110,20 @@ public class AccessibilityShortcutPreferenceControllerTest { Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, ON, UserHandle.USER_CURRENT)).isEqualTo(OFF); } + + @Test + @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH) + public void getAvailabilityStatus_settingEmpty_disabled() { + mShadowAccessibilityManager.setAccessibilityShortcutTargets(HARDWARE, List.of()); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING); + } + + @Test + @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH) + public void getAvailabilityStatus_settingNotEmpty_available() { + mShadowAccessibilityManager.setAccessibilityShortcutTargets(HARDWARE, List.of("Foo")); + + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE); + } } diff --git a/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java index 47a7363b531..1e6827ba9f3 100644 --- a/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java +++ b/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java @@ -28,7 +28,6 @@ import android.content.Context; import androidx.test.core.app.ApplicationProvider; import com.android.settings.R; -import com.android.settings.accessibility.ShortcutsSettingsFragment; import com.android.settings.testutils.XmlTestUtils; import org.junit.Before; @@ -79,7 +78,7 @@ public class ColorContrastFragmentTest { @Test public void getNonIndexableKeys_existInXmlLayout() { final List niks = - ShortcutsSettingsFragment.SEARCH_INDEX_DATA_PROVIDER + ColorContrastFragment.SEARCH_INDEX_DATA_PROVIDER .getNonIndexableKeys(mContext); final List keys = XmlTestUtils.getKeysFromPreferenceXml(mContext,