diff --git a/src/com/android/settings/accessibility/PreferredShortcuts.java b/src/com/android/settings/accessibility/PreferredShortcuts.java index e166f38a52f..895430afb73 100644 --- a/src/com/android/settings/accessibility/PreferredShortcuts.java +++ b/src/com/android/settings/accessibility/PreferredShortcuts.java @@ -42,7 +42,8 @@ public final class PreferredShortcuts { /** * Retrieves the user preferred shortcut types for the given {@code componentName} from - * SharedPreferences. + * SharedPreferences. If the user doesn't have a preferred shortcut, + * {@link ShortcutConstants.UserShortcutType.SOFTWARE} is returned. * * @param context {@link Context} to access the {@link SharedPreferences} * @param componentName Name of the service or activity, should be the format of {@link @@ -52,7 +53,26 @@ public final class PreferredShortcuts { @ShortcutConstants.UserShortcutType public static int retrieveUserShortcutType( @NonNull Context context, @NonNull String componentName) { - final int defaultTypes = getDefaultPreferredShortcutTypesForTarget(componentName); + return retrieveUserShortcutType( + context, componentName, ShortcutConstants.UserShortcutType.SOFTWARE); + } + + /** + * Retrieves the user preferred shortcut types for the given {@code componentName} from + * SharedPreferences. + * + * @param context {@link Context} to access the {@link SharedPreferences} + * @param componentName Name of the service or activity, should be the format of {@link + * ComponentName#flattenToString()}. + * @param defaultTypes The default shortcut types to use if the user doesn't have a + * preferred shortcut. + * @return {@link ShortcutConstants.UserShortcutType} + */ + @ShortcutConstants.UserShortcutType + public static int retrieveUserShortcutType( + @NonNull Context context, + @NonNull String componentName, + @ShortcutConstants.UserShortcutType int defaultTypes) { // Create a mutable set to modify final Set info = new HashSet<>(getFromSharedPreferences(context)); @@ -150,14 +170,5 @@ public final class PreferredShortcuts { getSharedPreferences(context).edit().clear().apply(); } - /** - * Returns the default shortcut types for the given accessibility feature. - */ - @ShortcutConstants.UserShortcutType - private static int getDefaultPreferredShortcutTypesForTarget(@NonNull String componentName) { - // TODO (b/322712028): return different default shortcut types for the given component - return ShortcutConstants.UserShortcutType.SOFTWARE; - } - private PreferredShortcuts() {} } diff --git a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java index 0b5ad3ee9f0..e89ff9473c5 100644 --- a/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragment.java @@ -45,6 +45,7 @@ import android.widget.CompoundButton; import androidx.annotation.Nullable; +import com.android.internal.accessibility.common.ShortcutConstants; import com.android.settings.R; import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment; @@ -330,7 +331,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends @Override public void onToggleClicked(ShortcutPreference preference) { final int shortcutTypes = retrieveUserShortcutType(getPrefContext(), - mComponentName.flattenToString()); + mComponentName.flattenToString(), getDefaultShortcutTypes()); if (preference.isChecked()) { final boolean isWarningRequired; if (android.view.accessibility.Flags.cleanupAccessibilityWarningDialog()) { @@ -476,6 +477,16 @@ public class ToggleAccessibilityServicePreferenceFragment extends return TAG; } + @Override + protected int getDefaultShortcutTypes() { + if (android.view.accessibility.Flags.a11yQsShortcut()) { + return getTileComponentName() == null ? super.getDefaultShortcutTypes() + : ShortcutConstants.UserShortcutType.QUICK_SETTINGS; + } + + return super.getDefaultShortcutTypes(); + } + private void onAllowButtonFromEnableToggleClicked() { handleConfirmServiceEnabled(/* confirmed= */ true); if (serviceSupportsAccessibilityButton()) { @@ -507,7 +518,7 @@ public class ToggleAccessibilityServicePreferenceFragment extends mShortcutPreference.setChecked(true); final int shortcutTypes = retrieveUserShortcutType(getPrefContext(), - mComponentName.flattenToString()); + mComponentName.flattenToString(), getDefaultShortcutTypes()); AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes, mComponentName); mIsDialogShown.set(false); diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index ed47007fbcf..ef828dbf973 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -54,6 +54,7 @@ import androidx.preference.Preference; import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; +import com.android.internal.accessibility.common.ShortcutConstants; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.accessibility.AccessibilityDialogUtils.DialogType; @@ -661,7 +662,7 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment int value = restoreOnConfigChangedValue(); if (value == NOT_SET) { final int lastNonEmptyUserShortcutType = PreferredShortcuts.retrieveUserShortcutType( - getPrefContext(), mComponentName.flattenToString()); + getPrefContext(), mComponentName.flattenToString(), getDefaultShortcutTypes()); value = mShortcutPreference.isChecked() ? lastNonEmptyUserShortcutType : UserShortcutType.EMPTY; } @@ -710,8 +711,8 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment return context.getText(R.string.accessibility_shortcut_state_off); } - final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(context, - mComponentName.flattenToString()); + final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType( + context, mComponentName.flattenToString(), getDefaultShortcutTypes()); final List list = new ArrayList<>(); if (android.view.accessibility.Flags.a11yQsShortcut()) { @@ -811,7 +812,7 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment } final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(getPrefContext(), - mComponentName.flattenToString()); + mComponentName.flattenToString(), getDefaultShortcutTypes()); mShortcutPreference.setChecked( AccessibilityUtil.hasValuesInSettings(getPrefContext(), shortcutTypes, mComponentName)); @@ -829,7 +830,7 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment } final int shortcutTypes = PreferredShortcuts.retrieveUserShortcutType(getPrefContext(), - mComponentName.flattenToString()); + mComponentName.flattenToString(), getDefaultShortcutTypes()); if (preference.isChecked()) { AccessibilityUtil.optInAllValuesToSettings(getPrefContext(), shortcutTypes, mComponentName); @@ -977,4 +978,13 @@ public abstract class ToggleFeaturePreferenceFragment extends DashboardFragment boolean isAnySetupWizard() { return WizardManagerHelper.isAnySetupWizard(getIntent()); } + + /** + * Returns the default preferred shortcut types when the user doesn't have a preferred shortcut + * types + */ + @ShortcutConstants.UserShortcutType + protected int getDefaultShortcutTypes() { + return ShortcutConstants.UserShortcutType.SOFTWARE; + } } diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java index 31741012d47..ae4f9a0ec9c 100644 --- a/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/ToggleAccessibilityServicePreferenceFragmentTest.java @@ -34,10 +34,10 @@ import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; import android.content.pm.ServiceInfo; import android.os.Bundle; -import android.platform.test.annotations.RequiresFlagsDisabled; -import android.platform.test.annotations.RequiresFlagsEnabled; -import android.platform.test.flag.junit.CheckFlagsRule; -import android.platform.test.flag.junit.DeviceFlagsValueProvider; +import android.platform.test.annotations.DisableFlags; +import android.platform.test.annotations.EnableFlags; +import android.platform.test.flag.junit.SetFlagsRule; +import android.provider.Settings; import android.service.quicksettings.TileService; import android.view.accessibility.AccessibilityManager; import android.view.accessibility.Flags; @@ -47,6 +47,7 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.test.core.app.ApplicationProvider; +import com.android.internal.accessibility.common.ShortcutConstants; import com.android.settings.R; import com.android.settings.SettingsActivity; import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType; @@ -68,13 +69,13 @@ import org.robolectric.shadows.ShadowAccessibilityManager; import org.robolectric.shadows.ShadowPackageManager; import java.util.List; +import java.util.Set; /** Tests for {@link ToggleAccessibilityServicePreferenceFragment} */ @RunWith(RobolectricTestRunner.class) public class ToggleAccessibilityServicePreferenceFragmentTest { - @Rule - public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule(); + @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(); private static final String PLACEHOLDER_PACKAGE_NAME = "com.placeholder.example"; private static final String PLACEHOLDER_PACKAGE_NAME2 = "com.placeholder.example2"; @@ -236,7 +237,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void enableService_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mToggleServiceSwitchPreference = @@ -249,7 +250,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void enableService_warningNotRequired_dontShowWarning() throws Throwable { final AccessibilityServiceInfo info = setupServiceWarningRequired(false); mFragment.mToggleServiceSwitchPreference = @@ -263,7 +264,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void toggleShortcutPreference_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); @@ -277,7 +278,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void toggleShortcutPreference_warningNotRequired_dontShowWarning() throws Throwable { setupServiceWarningRequired(false); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); @@ -291,7 +292,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) public void clickShortcutSettingsPreference_warningRequired_showWarning() throws Throwable { setupServiceWarningRequired(true); mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */null); @@ -303,8 +304,8 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - @RequiresFlagsEnabled(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) - @RequiresFlagsDisabled( + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @DisableFlags( com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN) public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_showDialog() throws Throwable { @@ -318,7 +319,7 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { } @Test - @RequiresFlagsEnabled({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, + @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, com.android.settings.accessibility.Flags.FLAG_EDIT_SHORTCUTS_IN_FULL_SCREEN}) public void clickShortcutSettingsPreference_warningNotRequired_dontShowWarning_launchActivity() throws Throwable { @@ -334,6 +335,155 @@ public class ToggleAccessibilityServicePreferenceFragmentTest { .isEqualTo(EditShortcutsPreferenceFragment.class.getName()); } + @Test + public void getDefaultShortcutTypes_noAssociatedTile_softwareTypeIsDefault() { + PreferredShortcuts.clearPreferredShortcuts(mContext); + when(mFragment.getTileComponentName()).thenReturn(null); + + assertThat(mFragment.getDefaultShortcutTypes()) + .isEqualTo(ShortcutConstants.UserShortcutType.SOFTWARE); + } + + @Test + @EnableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) + public void getDefaultShortcutTypes_hasAssociatedTile_qsTypeIsDefault() { + PreferredShortcuts.clearPreferredShortcuts(mContext); + when(mFragment.getTileComponentName()).thenReturn(PLACEHOLDER_TILE_COMPONENT_NAME); + + assertThat(mFragment.getDefaultShortcutTypes()) + .isEqualTo(ShortcutConstants.UserShortcutType.QUICK_SETTINGS); + } + + @Test + @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) + public void getDefaultShortcutTypes_hasAssociatedTile_softwareTypeIsDefault() { + PreferredShortcuts.clearPreferredShortcuts(mContext); + when(mFragment.getTileComponentName()).thenReturn(PLACEHOLDER_TILE_COMPONENT_NAME); + + assertThat(mFragment.getDefaultShortcutTypes()) + .isEqualTo(ShortcutConstants.UserShortcutType.SOFTWARE); + } + + @Test + @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) + public void toggleShortcutPreference_noUserPreferredShortcut_hasQsTile_enableQsShortcut() + throws Throwable { + PreferredShortcuts.clearPreferredShortcuts(mContext); + setupServiceWarningRequired(false); + when(mFragment.getTileComponentName()).thenReturn(PLACEHOLDER_TILE_COMPONENT_NAME); + mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null); + + mFragment.mShortcutPreference.setChecked(true); + mFragment.onToggleClicked(mFragment.mShortcutPreference); + + verify(mMockAccessibilityManager) + .enableShortcutsForTargets(true, + ShortcutConstants.UserShortcutType.QUICK_SETTINGS, + Set.of(mFragment.mComponentName.flattenToString()), mContext.getUserId()); + } + + @Test + @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) + public void toggleShortcutPreference_noUserPreferredShortcut_noQsTile_enableSoftwareShortcut() + throws Throwable { + PreferredShortcuts.clearPreferredShortcuts(mContext); + setupServiceWarningRequired(false); + when(mFragment.getTileComponentName()).thenReturn(null); + mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null); + + mFragment.mShortcutPreference.setChecked(true); + mFragment.onToggleClicked(mFragment.mShortcutPreference); + + verify(mMockAccessibilityManager) + .enableShortcutsForTargets(true, + ShortcutConstants.UserShortcutType.SOFTWARE, + Set.of(mFragment.mComponentName.flattenToString()), mContext.getUserId()); + } + + @Test + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) + public void toggleShortcutPreference_noUserPreferredShortcut_hasQsTile_flagOff_enableSoftwareShortcut() + throws Throwable { + PreferredShortcuts.clearPreferredShortcuts(mContext); + setupServiceWarningRequired(false); + when(mFragment.getTileComponentName()).thenReturn(PLACEHOLDER_TILE_COMPONENT_NAME); + mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null); + + mFragment.mShortcutPreference.setChecked(true); + mFragment.onToggleClicked(mFragment.mShortcutPreference); + + assertThat( + Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS)) + .contains(mFragment.mComponentName.flattenToString()); + } + + @Test + @EnableFlags(Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG) + @DisableFlags(Flags.FLAG_A11Y_QS_SHORTCUT) + public void toggleShortcutPreference_noUserPreferredShortcut_noQsTile_flagOff_enableSoftwareShortcut() + throws Throwable { + PreferredShortcuts.clearPreferredShortcuts(mContext); + setupServiceWarningRequired(false); + when(mFragment.getTileComponentName()).thenReturn(null); + mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null); + + mFragment.mShortcutPreference.setChecked(true); + mFragment.onToggleClicked(mFragment.mShortcutPreference); + + assertThat( + Settings.Secure.getString(mContext.getContentResolver(), + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS)) + .contains(mFragment.mComponentName.flattenToString()); + } + + @Test + @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) + public void toggleShortcutPreference_userPreferVolumeKeysShortcut_noQsTile_enableVolumeKeysShortcut() + throws Throwable { + setupServiceWarningRequired(false); + String componentName = mFragment.mComponentName.flattenToString(); + PreferredShortcuts.saveUserShortcutType( + mContext, + new PreferredShortcut(componentName, ShortcutConstants.UserShortcutType.HARDWARE)); + when(mFragment.getTileComponentName()).thenReturn(null); + mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null); + + mFragment.mShortcutPreference.setChecked(true); + mFragment.onToggleClicked(mFragment.mShortcutPreference); + + verify(mMockAccessibilityManager) + .enableShortcutsForTargets( + true, + ShortcutConstants.UserShortcutType.HARDWARE, + Set.of(componentName), + mContext.getUserId()); + } + + @Test + @EnableFlags({Flags.FLAG_CLEANUP_ACCESSIBILITY_WARNING_DIALOG, Flags.FLAG_A11Y_QS_SHORTCUT}) + public void toggleShortcutPreference_userPreferVolumeKeysShortcut_hasQsTile_enableVolumeKeysShortcut() + throws Throwable { + setupServiceWarningRequired(false); + String componentName = mFragment.mComponentName.flattenToString(); + PreferredShortcuts.saveUserShortcutType( + mContext, + new PreferredShortcut(componentName, ShortcutConstants.UserShortcutType.HARDWARE)); + when(mFragment.getTileComponentName()).thenReturn(PLACEHOLDER_TILE_COMPONENT_NAME); + mFragment.mShortcutPreference = new ShortcutPreference(mContext, /* attrs= */ null); + + mFragment.mShortcutPreference.setChecked(true); + mFragment.onToggleClicked(mFragment.mShortcutPreference); + + verify(mMockAccessibilityManager) + .enableShortcutsForTargets( + true, + ShortcutConstants.UserShortcutType.HARDWARE, + Set.of(componentName), + mContext.getUserId()); + } + private void setupTileService(String packageName, String name, String tileName) { final Intent tileProbe = new Intent(TileService.ACTION_QS_TILE); final ResolveInfo info = new ResolveInfo(); diff --git a/tests/unit/src/com/android/settings/accessibility/PreferredShortcutsTest.java b/tests/unit/src/com/android/settings/accessibility/PreferredShortcutsTest.java index 4ef63d0df81..364b17cc646 100644 --- a/tests/unit/src/com/android/settings/accessibility/PreferredShortcutsTest.java +++ b/tests/unit/src/com/android/settings/accessibility/PreferredShortcutsTest.java @@ -208,6 +208,23 @@ public class PreferredShortcutsTest { assertThat(savedPreferredShortcut).isEqualTo(UserShortcutType.HARDWARE); } + @Test + public void retrieveUserShortcutTypeWithoutDefault_noUserPreferredShortcuts_returnSoftwareShortcut() { + String target = COMPONENT_NAME_1.flattenToString(); + + assertThat(PreferredShortcuts.retrieveUserShortcutType(mContext, target)) + .isEqualTo(UserShortcutType.SOFTWARE); + } + + @Test + public void retrieveUserShortcutTypeWithDefaultAsDefault_noUserPreferredShortcuts_returnSpecifiedDefault() { + String target = COMPONENT_NAME_1.flattenToString(); + + assertThat(PreferredShortcuts.retrieveUserShortcutType(mContext, target, + UserShortcutType.HARDWARE)) + .isEqualTo(UserShortcutType.HARDWARE); + } + private static void clearShortcuts() { Settings.Secure.putString(sContentResolver, Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, "");