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,