Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59a329ca authored by Chun-Ku Lin's avatar Chun-Ku Lin Committed by Android (Google) Code Review
Browse files

Merge "Make QS shortcut type as default preferred shortcut for A11yService...

Merge "Make QS shortcut type as default preferred shortcut for A11yService that associate with a TileService" into main
parents 23cb6eeb 5cdf972b
Loading
Loading
Loading
Loading
+22 −11
Original line number Diff line number Diff line
@@ -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<String> 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() {}
}
+13 −2
Original line number Diff line number Diff line
@@ -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);
+15 −5
Original line number Diff line number Diff line
@@ -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<CharSequence> 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;
    }
}
+164 −14
Original line number Diff line number Diff line
@@ -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();
+17 −0
Original line number Diff line number Diff line
@@ -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, "");