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

Commit 35b675f8 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Makes Settings > Accessibility > Magnification prefs searchable." into main

parents 1cc49800 3079b2d1
Loading
Loading
Loading
Loading
+182 −66
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ import androidx.annotation.StringRes;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.SwitchPreferenceCompat;
import androidx.preference.TwoStatePreference;

import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType;
@@ -64,7 +63,11 @@ import com.android.settings.DialogCreatable;
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.search.SearchIndexableRaw;
import com.android.settingslib.widget.IllustrationPreference;

import com.google.android.setupcompat.util.WizardManagerHelper;
@@ -73,16 +76,20 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.StringJoiner;
import java.util.stream.Stream;

/**
 * Fragment that shows the actual UI for providing basic magnification accessibility service setup
 * and does not have toggle bar to turn on service to use.
 */
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class ToggleScreenMagnificationPreferenceFragment extends
        ToggleFeaturePreferenceFragment implements
        MagnificationModePreferenceController.DialogHelper {

    private static final String TAG = "ToggleScreenMagnificationPreferenceFragment";
    @VisibleForTesting
    static final String KEY_MAGNIFICATION_SHORTCUT_PREFERENCE = "magnification_shortcut_preference";
    private static final char COMPONENT_NAME_SEPARATOR = ':';
    private static final TextUtils.SimpleStringSplitter sStringColonSplitter =
            new TextUtils.SimpleStringSplitter(COMPONENT_NAME_SEPARATOR);
@@ -181,38 +188,29 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        }
    }

    private static boolean isWindowMagnificationSupported(Context context) {
        return context.getResources().getBoolean(
                com.android.internal.R.bool.config_magnification_area)
                && context.getPackageManager().hasSystemFeature(
                PackageManager.FEATURE_WINDOW_MAGNIFICATION);
    }

    @Override
    protected void initSettingsPreference() {
        // If the device doesn't support window magnification feature, it should hide the
        // settings preference.
        final boolean supportWindowMagnification =
                getContext().getResources().getBoolean(
                        com.android.internal.R.bool.config_magnification_area)
                        && getContext().getPackageManager().hasSystemFeature(
                        PackageManager.FEATURE_WINDOW_MAGNIFICATION);
        if (!supportWindowMagnification) {
        if (!isWindowMagnificationSupported(getContext())) {
            return;
        }
        mSettingsPreference = new Preference(getPrefContext());
        mSettingsPreference.setTitle(R.string.accessibility_magnification_mode_title);
        mSettingsPreference.setKey(MagnificationModePreferenceController.PREF_KEY);
        mSettingsPreference.setPersistent(false);

        final PreferenceCategory generalCategory = findPreference(KEY_GENERAL_CATEGORY);
        generalCategory.addPreference(mSettingsPreference);

        final MagnificationModePreferenceController magnificationModePreferenceController =
                new MagnificationModePreferenceController(getContext(),
                        MagnificationModePreferenceController.PREF_KEY);
        magnificationModePreferenceController.setDialogHelper(this);
        getSettingsLifecycle().addObserver(magnificationModePreferenceController);
        magnificationModePreferenceController.displayPreference(getPreferenceScreen());
        addPreferenceController(magnificationModePreferenceController);

        // LINT.IfChange(:preference_list)
        addMagnificationModeSetting(generalCategory);
        addFollowTypingSetting(generalCategory);
        addOneFingerPanningSetting(generalCategory);
        addAlwaysOnSetting(generalCategory);
        addJoystickSetting(generalCategory);
        // LINT.ThenChange(:search_data)
    }

    @Override
@@ -240,15 +238,37 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        super.onProcessArguments(arguments);
    }

    private static Preference createMagnificationModePreference(Context context) {
        final Preference pref = new Preference(context);
        pref.setTitle(R.string.accessibility_magnification_mode_title);
        pref.setKey(MagnificationModePreferenceController.PREF_KEY);
        pref.setPersistent(false);
        return pref;
    }

    private void addMagnificationModeSetting(PreferenceCategory generalCategory) {
        mSettingsPreference = createMagnificationModePreference(getPrefContext());
        generalCategory.addPreference(mSettingsPreference);

        final MagnificationModePreferenceController magnificationModePreferenceController =
                new MagnificationModePreferenceController(getContext(),
                        MagnificationModePreferenceController.PREF_KEY);
        magnificationModePreferenceController.setDialogHelper(this);
        getSettingsLifecycle().addObserver(magnificationModePreferenceController);
        magnificationModePreferenceController.displayPreference(getPreferenceScreen());
        addPreferenceController(magnificationModePreferenceController);
    }

    private static Preference createFollowTypingPreference(Context context) {
        final Preference pref = new SwitchPreferenceCompat(context);
        pref.setTitle(R.string.accessibility_screen_magnification_follow_typing_title);
        pref.setSummary(R.string.accessibility_screen_magnification_follow_typing_summary);
        pref.setKey(MagnificationFollowTypingPreferenceController.PREF_KEY);
        return pref;
    }

    private void addFollowTypingSetting(PreferenceCategory generalCategory) {
        var followingTypingSwitchPreference = new SwitchPreferenceCompat(getPrefContext());
        followingTypingSwitchPreference.setTitle(
                R.string.accessibility_screen_magnification_follow_typing_title);
        followingTypingSwitchPreference.setSummary(
                R.string.accessibility_screen_magnification_follow_typing_summary);
        followingTypingSwitchPreference.setKey(
                MagnificationFollowTypingPreferenceController.PREF_KEY);
        generalCategory.addPreference(followingTypingSwitchPreference);
        generalCategory.addPreference(createFollowTypingPreference(getPrefContext()));

        var followTypingPreferenceController = new MagnificationFollowTypingPreferenceController(
                getContext(), MagnificationFollowTypingPreferenceController.PREF_KEY);
@@ -257,8 +277,8 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        addPreferenceController(followTypingPreferenceController);
    }

    private boolean isAlwaysOnSettingEnabled() {
        final boolean defaultValue = getContext().getResources().getBoolean(
    private static boolean isAlwaysOnSupported(Context context) {
        final boolean defaultValue = context.getResources().getBoolean(
                com.android.internal.R.bool.config_magnification_always_on_enabled);

        return DeviceConfig.getBoolean(
@@ -268,19 +288,21 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        );
    }

    private static Preference createAlwaysOnPreference(Context context) {
        final Preference pref = new SwitchPreferenceCompat(context);
        pref.setTitle(R.string.accessibility_screen_magnification_always_on_title);
        pref.setSummary(R.string.accessibility_screen_magnification_always_on_summary);
        pref.setKey(MagnificationAlwaysOnPreferenceController.PREF_KEY);
        return pref;
    }

    private void addAlwaysOnSetting(PreferenceCategory generalCategory) {
        if (!isAlwaysOnSettingEnabled()) {
        if (!isAlwaysOnSupported(getContext())) {
            return;
        }

        var alwaysOnPreference = new SwitchPreferenceCompat(getPrefContext());
        alwaysOnPreference.setTitle(
                R.string.accessibility_screen_magnification_always_on_title);
        alwaysOnPreference.setSummary(
                R.string.accessibility_screen_magnification_always_on_summary);
        alwaysOnPreference.setKey(
                MagnificationAlwaysOnPreferenceController.PREF_KEY);
        generalCategory.addPreference(alwaysOnPreference);
        final Preference pref = createAlwaysOnPreference(getPrefContext());
        generalCategory.addPreference(pref);

        var alwaysOnPreferenceController = new MagnificationAlwaysOnPreferenceController(
                getContext(), MagnificationAlwaysOnPreferenceController.PREF_KEY);
@@ -290,17 +312,24 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        addPreferenceController(alwaysOnPreferenceController);
    }

    private static Preference createOneFingerPanningPreference(Context context) {
        final Preference pref = new SwitchPreferenceCompat(context);
        pref.setTitle(R.string.accessibility_magnification_one_finger_panning_title);
        pref.setKey(MagnificationOneFingerPanningPreferenceController.PREF_KEY);
        return pref;
    }

    private static boolean isOneFingerPanningSupported() {
        return Flags.enableMagnificationOneFingerPanningGesture();
    }

    private void addOneFingerPanningSetting(PreferenceCategory generalCategory) {
        if (!Flags.enableMagnificationOneFingerPanningGesture()) {
        if (!isOneFingerPanningSupported()) {
            return;
        }

        var oneFingerPanningPreference = new SwitchPreferenceCompat(getPrefContext());
        oneFingerPanningPreference.setTitle(
                R.string.accessibility_magnification_one_finger_panning_title);
        oneFingerPanningPreference.setKey(
                MagnificationOneFingerPanningPreferenceController.PREF_KEY);
        generalCategory.addPreference(oneFingerPanningPreference);
        final Preference pref = createOneFingerPanningPreference(getPrefContext());
        generalCategory.addPreference(pref);

        mOneFingerPanningPreferenceController =
                new MagnificationOneFingerPanningPreferenceController(getContext());
@@ -310,23 +339,28 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        addPreferenceController(mOneFingerPanningPreferenceController);
    }

    private void addJoystickSetting(PreferenceCategory generalCategory) {
        if (!DeviceConfig.getBoolean(
    private static Preference createJoystickPreference(Context context) {
        final Preference pref = new SwitchPreferenceCompat(context);
        pref.setTitle(R.string.accessibility_screen_magnification_joystick_title);
        pref.setSummary(R.string.accessibility_screen_magnification_joystick_summary);
        pref.setKey(MagnificationJoystickPreferenceController.PREF_KEY);
        return pref;
    }

    private static boolean isJoystickSupported() {
        return DeviceConfig.getBoolean(
                DeviceConfig.NAMESPACE_WINDOW_MANAGER,
                "MagnificationJoystick__enable_magnification_joystick",
                false
        )) {
                false);
    }

    private void addJoystickSetting(PreferenceCategory generalCategory) {
        if (!isJoystickSupported()) {
            return;
        }

        TwoStatePreference joystickPreference = new SwitchPreferenceCompat(getPrefContext());
        joystickPreference.setTitle(
                R.string.accessibility_screen_magnification_joystick_title);
        joystickPreference.setSummary(
                R.string.accessibility_screen_magnification_joystick_summary);
        joystickPreference.setKey(
                MagnificationJoystickPreferenceController.PREF_KEY);
        generalCategory.addPreference(joystickPreference);
        final Preference pref = createJoystickPreference(getPrefContext());
        generalCategory.addPreference(pref);

        MagnificationJoystickPreferenceController joystickPreferenceController =
                new MagnificationJoystickPreferenceController(
@@ -517,6 +551,11 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        generalCategory.addPreference(mShortcutPreference);
    }

    @Override
    protected String getShortcutPreferenceKey() {
        return KEY_MAGNIFICATION_SHORTCUT_PREFERENCE;
    }

    @Override
    protected CharSequence getShortcutTitle() {
        return getText(R.string.accessibility_screen_magnification_shortcut_title);
@@ -790,4 +829,81 @@ public class ToggleScreenMagnificationPreferenceFragment extends
        return PreferredShortcuts.retrieveUserShortcutType(
                getPrefContext(), MAGNIFICATION_CONTROLLER_NAME);
    }

    public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
            new BaseSearchIndexProvider() {
                // LINT.IfChange(:search_data)
                @Override
                public List<SearchIndexableRaw> getRawDataToIndex(Context context,
                        boolean enabled) {
                    final List<SearchIndexableRaw> rawData =
                            super.getRawDataToIndex(context, enabled);

                    if (!com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
                        return rawData;
                    }

                    rawData.add(createShortcutPreferenceSearchData(context));
                    Stream.of(
                                    createMagnificationModePreference(context),
                                    createFollowTypingPreference(context),
                                    createOneFingerPanningPreference(context),
                                    createAlwaysOnPreference(context),
                                    createJoystickPreference(context)
                            )
                            .forEach(pref ->
                                    rawData.add(createPreferenceSearchData(context, pref)));
                    return rawData;
                }

                @Override
                public List<String> getNonIndexableKeys(Context context) {
                    final List<String> niks = super.getNonIndexableKeys(context);

                    if (!com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
                        return niks;
                    }

                    if (!isWindowMagnificationSupported(context)) {
                        niks.add(MagnificationModePreferenceController.PREF_KEY);
                        niks.add(MagnificationFollowTypingPreferenceController.PREF_KEY);
                        niks.add(MagnificationOneFingerPanningPreferenceController.PREF_KEY);
                        niks.add(MagnificationAlwaysOnPreferenceController.PREF_KEY);
                        niks.add(MagnificationJoystickPreferenceController.PREF_KEY);
                    } else {
                        if (!isAlwaysOnSupported(context)
                                // This preference's title "Keep on while switching apps" does not
                                // mention magnification so it may confuse users who search a term
                                // like "Keep on".
                                // So we hide it if the user has no magnification shortcut enabled.
                                || getUserShortcutTypeFromSettings(context) == DEFAULT) {
                            niks.add(MagnificationAlwaysOnPreferenceController.PREF_KEY);
                        }
                        if (!isOneFingerPanningSupported()) {
                            niks.add(MagnificationOneFingerPanningPreferenceController.PREF_KEY);
                        }
                        if (!isJoystickSupported()) {
                            niks.add(MagnificationJoystickPreferenceController.PREF_KEY);
                        }
                    }
                    return niks;
                }
                // LINT.ThenChange(:preference_list)

                private SearchIndexableRaw createPreferenceSearchData(
                        Context context, Preference pref) {
                    final SearchIndexableRaw raw = new SearchIndexableRaw(context);
                    raw.key = pref.getKey();
                    raw.title = pref.getTitle().toString();
                    return raw;
                }

                private SearchIndexableRaw createShortcutPreferenceSearchData(Context context) {
                    final SearchIndexableRaw raw = new SearchIndexableRaw(context);
                    raw.key = KEY_MAGNIFICATION_SHORTCUT_PREFERENCE;
                    raw.title = context.getString(
                            R.string.accessibility_screen_magnification_shortcut_title);
                    return raw;
                }
            };
}
+106 −3
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static com.android.internal.accessibility.common.ShortcutConstants.UserSh
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.android.settings.accessibility.MagnificationCapabilities.MagnificationMode;
import static com.android.settings.accessibility.ToggleScreenMagnificationPreferenceFragment.KEY_MAGNIFICATION_SHORTCUT_PREFERENCE;

import static com.google.common.truth.Truth.assertThat;

@@ -70,6 +71,7 @@ import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settings.testutils.shadow.ShadowStorageManager;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.search.SearchIndexableRaw;

import com.google.common.truth.Correspondence;

@@ -1025,6 +1027,107 @@ public class ToggleScreenMagnificationPreferenceFragmentTest {
                .isEqualTo(collectionInfo.getImportantForAccessibilityItemCount() + 1);
    }

    @Test
    @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
    public void getRawDataToIndex_returnsAllPreferenceKeys() {
        List<String> expectedSearchKeys = List.of(
                KEY_MAGNIFICATION_SHORTCUT_PREFERENCE,
                MagnificationModePreferenceController.PREF_KEY,
                MagnificationFollowTypingPreferenceController.PREF_KEY,
                MagnificationOneFingerPanningPreferenceController.PREF_KEY,
                MagnificationAlwaysOnPreferenceController.PREF_KEY,
                MagnificationJoystickPreferenceController.PREF_KEY);

        final List<SearchIndexableRaw> rawData = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true);
        final List<String> actualSearchKeys = rawData.stream().map(raw -> raw.key).toList();

        assertThat(actualSearchKeys).containsExactlyElementsIn(expectedSearchKeys);
    }

    @Test
    @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
    public void
            getNonIndexableKeys_windowMagnificationNotSupported_onlyShortcutPreferenceSearchable() {
        setWindowMagnificationSupported(false, false);

        final List<String> niks = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
        final List<SearchIndexableRaw> rawData = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getRawDataToIndex(mContext, true);
        // Expect all search data, except the shortcut preference, to be in NIKs.
        final List<String> expectedNiks = rawData.stream().map(raw -> raw.key)
                .filter(key -> !key.equals(KEY_MAGNIFICATION_SHORTCUT_PREFERENCE)).toList();

        // In NonIndexableKeys == not searchable
        assertThat(niks).containsExactlyElementsIn(expectedNiks);
    }

    @Test
    @EnableFlags({
            com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH,
            Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE})
    public void getNonIndexableKeys_hasShortcutAndAllFeaturesEnabled_allItemsSearchable() {
        setMagnificationTripleTapEnabled(true);
        setAlwaysOnSupported(true);
        setJoystickSupported(true);

        final List<String> niks = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);

        // Empty NonIndexableKeys == all indexed items are searchable
        assertThat(niks).isEmpty();
    }

    @Test
    @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
    public void getNonIndexableKeys_noShortcut_alwaysOnSupported_notSearchable() {
        setMagnificationTripleTapEnabled(false);
        setAlwaysOnSupported(true);

        final List<String> niks = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);

        // In NonIndexableKeys == not searchable
        assertThat(niks).contains(MagnificationAlwaysOnPreferenceController.PREF_KEY);
    }

    @Test
    @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
    public void getNonIndexableKeys_hasShortcut_alwaysOnNotSupported_notSearchable() {
        setMagnificationTripleTapEnabled(true);
        setAlwaysOnSupported(false);

        final List<String> niks = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);

        // In NonIndexableKeys == not searchable
        assertThat(niks).contains(MagnificationAlwaysOnPreferenceController.PREF_KEY);
    }

    @Test
    @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
    @DisableFlags(Flags.FLAG_ENABLE_MAGNIFICATION_ONE_FINGER_PANNING_GESTURE)
    public void getNonIndexableKeys_oneFingerPanningNotSupported_notSearchable() {
        final List<String> niks = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);

        // In NonIndexableKeys == not searchable
        assertThat(niks).contains(MagnificationOneFingerPanningPreferenceController.PREF_KEY);
    }

    @Test
    @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
    public void getNonIndexableKeys_joystickNotSupported_notSearchable() {
        setJoystickSupported(false);

        final List<String> niks = ToggleScreenMagnificationPreferenceFragment
                .SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);

        // In NonIndexableKeys == not searchable
        assertThat(niks).contains(MagnificationJoystickPreferenceController.PREF_KEY);
    }

    private void putStringIntoSettings(String key, String componentName) {
        Settings.Secure.putString(mContext.getContentResolver(), key, componentName);
    }