diff --git a/res/xml/one_handed_settings.xml b/res/xml/one_handed_settings.xml index f46b7eae186..3865fd60451 100644 --- a/res/xml/one_handed_settings.xml +++ b/res/xml/one_handed_settings.xml @@ -56,4 +56,5 @@ settings:controller="com.android.settings.gestures.OneHandedActionShowNotificationPrefController"/> + diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java index 709e1657b7c..127c7c68a39 100644 --- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java +++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java @@ -17,6 +17,7 @@ package com.android.settings.accessibility; import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums; +import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_GENERAL_CATEGORY; import android.app.Dialog; import android.app.settings.SettingsEnums; @@ -34,11 +35,13 @@ import android.view.ViewGroup; import android.view.accessibility.AccessibilityManager; import android.widget.CheckBox; +import androidx.annotation.Nullable; import androidx.annotation.VisibleForTesting; +import androidx.preference.PreferenceCategory; import androidx.preference.PreferenceScreen; import com.android.settings.R; -import com.android.settings.SettingsPreferenceFragment; +import com.android.settings.dashboard.DashboardFragment; import com.android.settings.utils.LocaleUtils; import com.google.android.setupcompat.util.WizardManagerHelper; @@ -50,7 +53,7 @@ import java.util.Locale; /** * Base class for accessibility fragments shortcut functions and dialog management. */ -public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPreferenceFragment +public abstract class AccessibilityShortcutPreferenceFragment extends DashboardFragment implements ShortcutPreference.OnClickCallback { private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference"; protected static final String KEY_SAVED_USER_SHORTCUT_TYPE = "shortcut_type"; @@ -88,6 +91,10 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr setPreferenceScreen(preferenceScreen); } + if (showGeneralCategory()) { + initGeneralCategory(); + } + final List shortcutFeatureKeys = new ArrayList<>(); shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); shortcutFeatureKeys.add(Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); @@ -151,6 +158,7 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr @Override public Dialog onCreateDialog(int dialogId) { + final Dialog dialog; switch (dialogId) { case DialogEnums.EDIT_SHORTCUT: final CharSequence dialogTitle = getPrefContext().getString( @@ -158,11 +166,17 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr final int dialogType = WizardManagerHelper.isAnySetupWizard(getIntent()) ? AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC_SUW : AccessibilityDialogUtils.DialogType.EDIT_SHORTCUT_GENERIC; - final Dialog dialog = AccessibilityDialogUtils.showEditShortcutDialog( + dialog = AccessibilityDialogUtils.showEditShortcutDialog( getPrefContext(), dialogType, dialogTitle, this::callOnAlertDialogCheckboxClicked); setupEditShortcutDialog(dialog); return dialog; + case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL: + dialog = AccessibilityGestureNavigationTutorial + .createAccessibilityTutorialDialog(getPrefContext(), + getUserShortcutTypes()); + dialog.setCanceledOnTouchOutside(false); + return dialog; default: throw new IllegalArgumentException("Unsupported dialogId " + dialogId); } @@ -173,6 +187,8 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr switch (dialogId) { case DialogEnums.EDIT_SHORTCUT: return SettingsEnums.DIALOG_ACCESSIBILITY_SERVICE_EDIT_SHORTCUT; + case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL: + return SettingsEnums.DIALOG_ACCESSIBILITY_TUTORIAL; default: return SettingsEnums.ACTION_UNKNOWN; } @@ -202,6 +218,11 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); } + /** + * Overrides to return specific shortcut preference key + * + * @return String The specific shortcut preference key + */ protected String getShortcutPreferenceKey() { return KEY_SHORTCUT_PREFERENCE; } @@ -238,6 +259,13 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr return value; } + /** + * Returns the shortcut type list which has been checked by user. + */ + protected int getUserShortcutTypes() { + return AccessibilityUtil.getUserShortcutTypesFromSettings(getPrefContext(), + getComponentName()); + }; /** * This method will be invoked when a button in the edit shortcut dialog is clicked. @@ -259,6 +287,15 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr mShortcutPreference.setSummary(getShortcutTypeSummary(getPrefContext())); } + @VisibleForTesting + void initGeneralCategory() { + final PreferenceCategory generalCategory = new PreferenceCategory(getPrefContext()); + generalCategory.setKey(KEY_GENERAL_CATEGORY); + generalCategory.setTitle(getGeneralCategoryDescription(null)); + + getPreferenceScreen().addPreference(generalCategory); + } + @VisibleForTesting void saveNonEmptyUserShortcutType(int type) { if (type == AccessibilityUtil.UserShortcutType.EMPTY) { @@ -270,6 +307,28 @@ public abstract class AccessibilityShortcutPreferenceFragment extends SettingsPr PreferredShortcuts.saveUserShortcutType(getPrefContext(), shortcut); } + /** + * Overrides to return customized description for general category above shortcut + * + * @return CharSequence The customized description for general category + */ + protected CharSequence getGeneralCategoryDescription(@Nullable CharSequence title) { + if (title == null || title.toString().isEmpty()) { + // Return default 'Options' string for category + return getContext().getString(R.string.accessibility_screen_option); + } + return title; + } + + /** + * Overrides to determinate if showing additional category description above shortcut + * + * @return boolean true to show category, false otherwise. + */ + protected boolean showGeneralCategory() { + return false; + } + private void setDialogTextAreaClickListener(View dialogView, CheckBox checkBox) { final View dialogTextArea = dialogView.findViewById(R.id.container); dialogTextArea.setOnClickListener(v -> checkBox.toggle()); diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java index 1002a8491ca..640ae532161 100644 --- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java +++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java @@ -90,7 +90,7 @@ public abstract class ToggleFeaturePreferenceFragment extends SettingsPreference private static final String DRAWABLE_FOLDER = "drawable"; protected static final String KEY_USE_SERVICE_PREFERENCE = "use_service"; - protected static final String KEY_GENERAL_CATEGORY = "general_categories"; + public static final String KEY_GENERAL_CATEGORY = "general_categories"; protected static final String KEY_HTML_DESCRIPTION_PREFERENCE = "html_description"; private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference"; protected static final String KEY_SAVED_USER_SHORTCUT_TYPE = "shortcut_type"; diff --git a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java index e388585e5f4..bd8de9fdada 100644 --- a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java +++ b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java @@ -17,19 +17,23 @@ package com.android.settings.gestures; import android.content.Context; +import android.provider.Settings; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; /** - * The controller to handle one-handed mode enable or disable state. - **/ + * Preference controller for One-handed mode shortcut settings + */ public class OneHandedEnablePreferenceController extends BasePreferenceController { + private static final String ONE_HANDED_ENABLED = Settings.Secure.ONE_HANDED_MODE_ENABLED; + public OneHandedEnablePreferenceController(Context context, String preferenceKey) { super(context, preferenceKey); } + @Override public int getAvailabilityStatus() { return OneHandedSettingsUtils.isSupportOneHandedMode() ? AVAILABLE : UNSUPPORTED_ON_DEVICE; } @@ -40,4 +44,5 @@ public class OneHandedEnablePreferenceController extends BasePreferenceControlle OneHandedSettingsUtils.isOneHandedModeEnabled(mContext) ? R.string.gesture_setting_on : R.string.gesture_setting_off); } + } diff --git a/src/com/android/settings/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java index 11fc774cd30..6d1cbfd35d9 100644 --- a/src/com/android/settings/gestures/OneHandedSettings.java +++ b/src/com/android/settings/gestures/OneHandedSettings.java @@ -17,31 +17,28 @@ package com.android.settings.gestures; import android.app.settings.SettingsEnums; +import android.content.ComponentName; import android.content.Context; +import android.os.Bundle; import android.os.UserHandle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import com.android.internal.accessibility.AccessibilityShortcutController; import com.android.settings.R; -import com.android.settings.dashboard.DashboardFragment; +import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment; import com.android.settings.search.BaseSearchIndexProvider; -import com.android.settingslib.search.SearchIndexable; /** - * The Fragment for one-handed mode settings. + * Fragment for One-handed mode settings + * + *

The child {@link AccessibilityShortcutPreferenceFragment} shows the actual UI for + * providing basic accessibility shortcut service setup. */ -@SearchIndexable -public class OneHandedSettings extends DashboardFragment { - - private static final String TAG = "OneHandedSettings"; - - @Override - public int getMetricsCategory() { - return SettingsEnums.SETTINGS_ONE_HANDED; - } - - @Override - protected String getLogTag() { - return TAG; - } +public class OneHandedSettings extends AccessibilityShortcutPreferenceFragment { + private static final String ONE_HANDED_SHORTCUT_KEY = "one_handed_shortcuts_preference"; + private String mFeatureName; @Override protected void updatePreferenceStates() { @@ -49,11 +46,60 @@ public class OneHandedSettings extends DashboardFragment { super.updatePreferenceStates(); } + @Override + public int getDialogMetricsCategory(int dialogId) { + final int dialogMetrics = super.getDialogMetricsCategory(dialogId); + return dialogMetrics == SettingsEnums.ACTION_UNKNOWN ? SettingsEnums.SETTINGS_ONE_HANDED + : dialogMetrics; + } + + @Override + public int getMetricsCategory() { + return SettingsEnums.SETTINGS_ONE_HANDED; + } + + @Override + protected String getShortcutPreferenceKey() { + return ONE_HANDED_SHORTCUT_KEY; + } + + @Override + protected boolean showGeneralCategory() { + return true; + } + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, + Bundle savedInstanceState) { + return super.onCreateView(inflater, container, savedInstanceState); + } + + @Override + protected ComponentName getComponentName() { + return AccessibilityShortcutController.ONE_HANDED_COMPONENT_NAME; + } + + @Override + protected CharSequence getLabelName() { + return mFeatureName; + } + @Override protected int getPreferenceScreenResId() { return R.xml.one_handed_settings; } + @Override + protected String getLogTag() { + return null; + } + + @Override + public void onCreate(Bundle savedInstanceState) { + mFeatureName = getContext().getString(R.string.one_handed_title); + super.onCreate(savedInstanceState); + } + public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER = new BaseSearchIndexProvider(R.xml.one_handed_settings) { @Override diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java index 104f33553c8..6d70bf74cca 100644 --- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java +++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java @@ -22,6 +22,7 @@ import static com.google.common.truth.Truth.assertThat; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import android.content.ComponentName; @@ -30,6 +31,7 @@ import android.content.DialogInterface; import android.os.Bundle; import android.provider.Settings; +import androidx.annotation.Nullable; import androidx.appcompat.app.AlertDialog; import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; @@ -179,6 +181,7 @@ public class AccessibilityShortcutPreferenceFragmentTest { AccessibilityUtil.UserShortcutType.SOFTWARE | AccessibilityUtil.UserShortcutType.HARDWARE); mFragment.onCreate(savedInstanceState); + mFragment.onAttach(mContext); mFragment.setupEditShortcutDialog(dialog); final int value = mFragment.getShortcutTypeCheckBoxValue(); mFragment.saveNonEmptyUserShortcutType(value); @@ -191,6 +194,20 @@ public class AccessibilityShortcutPreferenceFragmentTest { | AccessibilityUtil.UserShortcutType.HARDWARE); } + @Test + public void showGeneralCategory_shouldInitCategory() { + final Bundle savedInstanceState = new Bundle(); + when(mFragment.showGeneralCategory()).thenReturn(true); + mFragment.onCreate(savedInstanceState); + + verify(mFragment).initGeneralCategory(); + } + + @Test + public void showGeneralCategory_shouldSetDefaultDescription() { + assertThat(mFragment.getGeneralCategoryDescription(null)).isNotNull(); + } + private void callEmptyOnClicked(DialogInterface dialog, int which) {} private void putStringIntoSettings(String key, String componentName) { @@ -214,9 +231,35 @@ public class AccessibilityShortcutPreferenceFragmentTest { return PLACEHOLDER_PACKAGE_NAME; } + @Override + public int getUserShortcutTypes() { + return 0; + } + + @Override + protected CharSequence getGeneralCategoryDescription(@Nullable CharSequence title) { + return super.getGeneralCategoryDescription(null); + } + + @Override + protected boolean showGeneralCategory() { + // For showGeneralCategory_shouldInitCategory() + return true; + } + @Override public int getMetricsCategory() { return 0; } + + @Override + protected int getPreferenceScreenResId() { + return 0; + } + + @Override + protected String getLogTag() { + return null; + } }; }