From d9a4197d9d3aad1881ba856782a6554a6a115281 Mon Sep 17 00:00:00 2001 From: Jason Chang Date: Sun, 27 Jun 2021 20:49:02 +0800 Subject: [PATCH] Change One-handed mode controls states in the Settings pages for improving better UX experience MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit According to UX feedback to adjust One-handed mode UI controls’ status in the Settings page for better UX experience. Bug: 192171369 Test: manual verified on Settings > System > Gesture page > System controls page Test: make RunSettingsRoboTests ROBOTEST_FILTER= "com.android.settings.gestures .OneHandedEnablePreferenceControllerTest" Test: make RunSettingsRoboTests ROBOTEST_FILTER= "com.android.settings.gestures .OneHandedMainSwitchPreferenceControllerTest" Test: make RunSettingsRoboTests ROBOTEST_FILTER= "com.android.settings.gestures .OneHandedActionPullDownPrefControllerTest" Test: make RunSettingsRoboTests ROBOTEST_FILTER= "com.android.settings.gestures .OneHandedActionShowNotificationPrefControllerTest" Test: make RunSettingsRoboTests ROBOTEST_FILTER= "com.android.settings.gestures .OneHandedPreferenceCategoryControllerTest" Change-Id: I76242fe70c3ec06cd5e2f9bb059c87293cc686dd --- res/values/arrays.xml | 8 -- res/values/strings.xml | 17 +--- res/xml/one_handed_settings.xml | 4 +- ...OneHandedActionPullDownPrefController.java | 3 +- ...dActionShowNotificationPrefController.java | 3 +- .../OneHandedEnablePreferenceController.java | 4 - ...OneHandedPreferenceCategoryController.java | 52 ++++++++++++ .../gestures/OneHandedSettingsUtils.java | 34 +++++++- ...andedActionPullDownPrefControllerTest.java | 22 +++++ ...ionShowNotificationPrefControllerTest.java | 22 +++++ ...andedPreferenceCategoryControllerTest.java | 81 +++++++++++++++++++ 11 files changed, 217 insertions(+), 33 deletions(-) create mode 100644 src/com/android/settings/gestures/OneHandedPreferenceCategoryController.java create mode 100644 tests/robotests/src/com/android/settings/gestures/OneHandedPreferenceCategoryControllerTest.java diff --git a/res/values/arrays.xml b/res/values/arrays.xml index 00577cd5739..34506658c45 100644 --- a/res/values/arrays.xml +++ b/res/values/arrays.xml @@ -1575,14 +1575,6 @@ @string/rtt_settings_always_visible - - - @string/screensaver_settings_summary_never - @string/one_handed_timeout_short - @string/one_handed_timeout_medium - @string/one_handed_timeout_long - - 0 diff --git a/res/values/strings.xml b/res/values/strings.xml index ef0a0517584..45f01bf8da1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -11721,29 +11721,16 @@ Double-tap to check device - - Swipe for notifications - - Swipe down on the bottom edge of the screen to show your notifications.\nYou can\'t use one-handed mode when this feature is turned on. - One-handed mode Use one-handed mode - - Exit when switching apps - - Timeout - - 4 seconds - - 8 seconds - - 12 seconds reachability Swipe down to + + Use the shortcut to To use one handed mode, swipe down from the bottom edge of the screen. To use this feature, make sure gesture navigation is turned on in system navigation settings. diff --git a/res/xml/one_handed_settings.xml b/res/xml/one_handed_settings.xml index 8893e1eda21..2f5c091bdf0 100644 --- a/res/xml/one_handed_settings.xml +++ b/res/xml/one_handed_settings.xml @@ -39,7 +39,8 @@ + android:title="@string/one_handed_mode_swipe_down_category" + settings:controller="com.android.settings.gestures.OneHandedPreferenceCategoryController"> - diff --git a/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java index 84ea8b6c457..e17165b1856 100644 --- a/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java +++ b/src/com/android/settings/gestures/OneHandedActionPullDownPrefController.java @@ -92,7 +92,8 @@ public class OneHandedActionPullDownPrefController extends BasePreferenceControl if (mPreference == null) { return; } - if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI)) { + if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI) + || uri.equals(OneHandedSettingsUtils.SHORTCUT_ENABLED_URI)) { mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext)); } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) { updateState(mPreference); diff --git a/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java index 564429986e1..9f56a14afd6 100644 --- a/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java +++ b/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefController.java @@ -92,7 +92,8 @@ public class OneHandedActionShowNotificationPrefController extends BasePreferenc if (mPreference == null) { return; } - if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI)) { + if (uri.equals(OneHandedSettingsUtils.ONE_HANDED_MODE_ENABLED_URI) + || uri.equals(OneHandedSettingsUtils.SHORTCUT_ENABLED_URI)) { mPreference.setEnabled(OneHandedSettingsUtils.canEnableController(mContext)); } else if (uri.equals(OneHandedSettingsUtils.SHOW_NOTIFICATION_ENABLED_URI)) { updateState(mPreference); diff --git a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java index bd8de9fdada..29004c8f1fd 100644 --- a/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java +++ b/src/com/android/settings/gestures/OneHandedEnablePreferenceController.java @@ -17,7 +17,6 @@ package com.android.settings.gestures; import android.content.Context; -import android.provider.Settings; import com.android.settings.R; import com.android.settings.core.BasePreferenceController; @@ -27,8 +26,6 @@ import com.android.settings.core.BasePreferenceController; */ 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); } @@ -44,5 +41,4 @@ 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/OneHandedPreferenceCategoryController.java b/src/com/android/settings/gestures/OneHandedPreferenceCategoryController.java new file mode 100644 index 00000000000..9623299343c --- /dev/null +++ b/src/com/android/settings/gestures/OneHandedPreferenceCategoryController.java @@ -0,0 +1,52 @@ +/* + * Copyright (C) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.gestures; + +import android.content.Context; + +import androidx.preference.Preference; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; +import com.android.settings.core.BasePreferenceController; + +/** + * Category Preference controller for One-handed mode category + */ +public class OneHandedPreferenceCategoryController extends BasePreferenceController { + + private Preference mPreference; + + public OneHandedPreferenceCategoryController(Context context, String preferenceKey) { + super(context, preferenceKey); + } + + @Override + public int getAvailabilityStatus() { + return AVAILABLE; + } + + @Override + public void displayPreference(PreferenceScreen screen) { + super.displayPreference(screen); + mPreference = screen.findPreference(getPreferenceKey()); + mPreference.setTitle( + OneHandedSettingsUtils.getNavigationBarMode(mContext) == 0 /* 3 button */ + ? R.string.one_handed_mode_use_shortcut_category + : R.string.one_handed_mode_swipe_down_category); + } +} diff --git a/src/com/android/settings/gestures/OneHandedSettingsUtils.java b/src/com/android/settings/gestures/OneHandedSettingsUtils.java index a9311296b43..f058689912b 100644 --- a/src/com/android/settings/gestures/OneHandedSettingsUtils.java +++ b/src/com/android/settings/gestures/OneHandedSettingsUtils.java @@ -16,6 +16,8 @@ package com.android.settings.gestures; +import static com.android.internal.accessibility.AccessibilityShortcutController.ONE_HANDED_COMPONENT_NAME; + import android.content.ContentResolver; import android.content.Context; import android.database.ContentObserver; @@ -33,6 +35,9 @@ import androidx.annotation.VisibleForTesting; */ public class OneHandedSettingsUtils { + static final String ONE_HANDED_MODE_TARGET_NAME = + ONE_HANDED_COMPONENT_NAME.getShortClassName(); + static final String SUPPORT_ONE_HANDED_MODE = "ro.support_one_handed_mode"; static final int OFF = 0; static final int ON = 1; @@ -40,6 +45,8 @@ public class OneHandedSettingsUtils { Settings.Secure.getUriFor(Settings.Secure.ONE_HANDED_MODE_ENABLED); static final Uri SHOW_NOTIFICATION_ENABLED_URI = Settings.Secure.getUriFor(Settings.Secure.SWIPE_BOTTOM_TO_NOTIFICATION_ENABLED); + static final Uri SHORTCUT_ENABLED_URI = + Settings.Secure.getUriFor(Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS); public enum OneHandedTimeout { NEVER(0), SHORT(4), MEDIUM(8), LONG(12); @@ -220,8 +227,30 @@ public class OneHandedSettingsUtils { * navigation settings. */ public static boolean canEnableController(Context context) { - return (OneHandedSettingsUtils.isOneHandedModeEnabled(context) - && OneHandedSettingsUtils.getNavigationBarMode(context) != 0 /* 3-button mode */); + return ((OneHandedSettingsUtils.isOneHandedModeEnabled(context) + && getNavigationBarMode(context) != 0 /* 3-button */) + || getShortcutEnabled(context)); + } + + /** + * Queries one-handed mode shortcut enabled in settings or not. + * + * @return true if user enabled one-handed shortcut in settings, false otherwise. + */ + public static boolean getShortcutEnabled(Context context) { + final String targets = Settings.Secure.getStringForUser(context.getContentResolver(), + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, sCurrentUserId); + return targets != null ? targets.contains(ONE_HANDED_MODE_TARGET_NAME) : false; + } + + /** + * This is a test only API for set Shortcut enabled or not. + */ + @VisibleForTesting + public void setShortcutEnabled(Context context, boolean enabled) { + final String targetName = enabled ? ONE_HANDED_MODE_TARGET_NAME : ""; + Settings.Secure.putStringForUser(context.getContentResolver(), + Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS, targetName, sCurrentUserId); } /** @@ -256,6 +285,7 @@ public class OneHandedSettingsUtils { final ContentResolver resolver = mContext.getContentResolver(); resolver.registerContentObserver(ONE_HANDED_MODE_ENABLED_URI, true, this); resolver.registerContentObserver(SHOW_NOTIFICATION_ENABLED_URI, true, this); + resolver.registerContentObserver(SHORTCUT_ENABLED_URI, true, this); } @Override diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java index 60398de9937..36938c2ee9d 100644 --- a/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/OneHandedActionPullDownPrefControllerTest.java @@ -105,4 +105,26 @@ public class OneHandedActionPullDownPrefControllerTest { assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING); } + + @Test + public void getAvailabilityStatus_setShortcutEnabled_shouldEnabled() { + SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true"); + OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false); + mUtils.setNavigationBarMode(mContext, "0" /* 3-button mode */); + mUtils.setShortcutEnabled(mContext, true); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void getAvailabilityStatus_setShortcutDisabled_shouldDisabled() { + SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true"); + OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false); + mUtils.setNavigationBarMode(mContext, "0" /* 3-button mode */); + mUtils.setShortcutEnabled(mContext, false); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING); + } } diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java index b56a4f78f16..a7afccd2fe5 100644 --- a/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java +++ b/tests/robotests/src/com/android/settings/gestures/OneHandedActionShowNotificationPrefControllerTest.java @@ -104,4 +104,26 @@ public class OneHandedActionShowNotificationPrefControllerTest { assertThat(mController.getAvailabilityStatus()) .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING); } + + @Test + public void getAvailabilityStatus_setShortcutEnabled_shouldEnabled() { + SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true"); + OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false); + mUtils.setNavigationBarMode(mContext, "0" /* 3-button mode */); + mUtils.setShortcutEnabled(mContext, true); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.AVAILABLE); + } + + @Test + public void getAvailabilityStatus_setShortcutDisabled_shouldDisabled() { + SystemProperties.set(OneHandedSettingsUtils.SUPPORT_ONE_HANDED_MODE, "true"); + OneHandedSettingsUtils.setOneHandedModeEnabled(mContext, false); + mUtils.setNavigationBarMode(mContext, "0" /* 3-button mode */); + mUtils.setShortcutEnabled(mContext, false); + + assertThat(mController.getAvailabilityStatus()) + .isEqualTo(BasePreferenceController.DISABLED_DEPENDENT_SETTING); + } } diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedPreferenceCategoryControllerTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedPreferenceCategoryControllerTest.java new file mode 100644 index 00000000000..112e04aa806 --- /dev/null +++ b/tests/robotests/src/com/android/settings/gestures/OneHandedPreferenceCategoryControllerTest.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2021 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.settings.gestures; + +import static junit.framework.TestCase.assertTrue; + +import static org.mockito.Mockito.when; + +import android.content.Context; +import android.os.UserHandle; +import android.text.TextUtils; + +import androidx.preference.PreferenceCategory; +import androidx.preference.PreferenceScreen; + +import com.android.settings.R; + +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.RuntimeEnvironment; + +@RunWith(RobolectricTestRunner.class) +public class OneHandedPreferenceCategoryControllerTest { + + private static final String KEY = "gesture_one_handed_mode_swipe_down"; + + private Context mContext; + private OneHandedSettingsUtils mUtils; + private OneHandedPreferenceCategoryController mController; + @Mock + private PreferenceCategory mPreference; + @Mock + private PreferenceScreen mScreen; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mContext = RuntimeEnvironment.application; + mUtils = new OneHandedSettingsUtils(mContext); + mController = new OneHandedPreferenceCategoryController(mContext, KEY); + OneHandedSettingsUtils.setUserId(UserHandle.myUserId()); + mPreference = new PreferenceCategory(mContext); + when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference); + } + + @Test + public void getTitle_set3ButtonMode_shouldReturnSetShortcutTo() { + mUtils.setNavigationBarMode(mContext, "0" /* 3 button */); + mController.displayPreference(mScreen); + + assertTrue(TextUtils.equals(mPreference.getTitle(), mContext.getText( + R.string.one_handed_mode_use_shortcut_category))); + } + + @Test + public void getTitle_setGestureMode_shouldReturnSwipeDownTo() { + mUtils.setNavigationBarMode(mContext, "2" /* fully gestural */); + mController.displayPreference(mScreen); + + assertTrue(TextUtils.equals(mPreference.getTitle(), mContext.getText( + R.string.one_handed_mode_swipe_down_category))); + } +}