From 240760c570251f75387309aafe758afd57ab89b2 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 10 Jun 2019 00:57:03 -0700 Subject: [PATCH 1/8] Game Driver: Add UI support for prerelease Game Driver Bug: 134881329 Test: make RunSettingsRoboTests ROBOTEST_FILTER=GameDriver Change-Id: I9c710a5e6adff9b01c656d576f53f9b4b3360207 --- res/values/strings.xml | 3 ++ .../GameDriverAppPreferenceController.java | 25 ++++++++++++++-- ...GameDriverAppPreferenceControllerTest.java | 29 +++++++++++++++---- 3 files changed, 49 insertions(+), 8 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index e359fed4828..d3f68fcb837 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10648,12 +10648,15 @@ Default Game Driver + + Prerelease Driver System Graphics Driver @string/game_driver_app_preference_default @string/game_driver_app_preference_game_driver + @string/game_driver_app_preference_prerelease_driver @string/game_driver_app_preference_system diff --git a/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceController.java b/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceController.java index 09659be5eda..489408d4818 100644 --- a/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceController.java +++ b/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceController.java @@ -64,12 +64,14 @@ public class GameDriverAppPreferenceController extends BasePreferenceController private final String mPreferenceTitle; private final String mPreferenceDefault; private final String mPreferenceGameDriver; + private final String mPreferencePrereleaseDriver; private final String mPreferenceSystem; @VisibleForTesting GameDriverContentObserver mGameDriverContentObserver; private final List mAppInfos; private final Set mDevOptInApps; + private final Set mDevPrereleaseOptInApps; private final Set mDevOptOutApps; private PreferenceGroup mPreferenceGroup; @@ -88,6 +90,8 @@ public class GameDriverAppPreferenceController extends BasePreferenceController mPreferenceDefault = resources.getString(R.string.game_driver_app_preference_default); mPreferenceGameDriver = resources.getString(R.string.game_driver_app_preference_game_driver); + mPreferencePrereleaseDriver = + resources.getString(R.string.game_driver_app_preference_prerelease_driver); mPreferenceSystem = resources.getString(R.string.game_driver_app_preference_system); // TODO: Move this task to background if there's potential ANR/Jank. @@ -96,6 +100,8 @@ public class GameDriverAppPreferenceController extends BasePreferenceController mDevOptInApps = getGlobalSettingsString(mContentResolver, Settings.Global.GAME_DRIVER_OPT_IN_APPS); + mDevPrereleaseOptInApps = getGlobalSettingsString( + mContentResolver, Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS); mDevOptOutApps = getGlobalSettingsString(mContentResolver, Settings.Global.GAME_DRIVER_OPT_OUT_APPS); } @@ -147,21 +153,31 @@ public class GameDriverAppPreferenceController extends BasePreferenceController // opt-in and opt-out apps. Then set the new summary text. if (value.equals(mPreferenceSystem)) { mDevOptInApps.remove(packageName); + mDevPrereleaseOptInApps.remove(packageName); mDevOptOutApps.add(packageName); } else if (value.equals(mPreferenceGameDriver)) { mDevOptInApps.add(packageName); + mDevPrereleaseOptInApps.remove(packageName); + mDevOptOutApps.remove(packageName); + } else if (value.equals(mPreferencePrereleaseDriver)) { + mDevOptInApps.remove(packageName); + mDevPrereleaseOptInApps.add(packageName); mDevOptOutApps.remove(packageName); } else { mDevOptInApps.remove(packageName); + mDevPrereleaseOptInApps.remove(packageName); mDevOptOutApps.remove(packageName); } listPref.setValue(value); listPref.setSummary(value); - // Push the updated Sets for opt-in and opt-out apps to - // corresponding Settings.Global.GAME_DRIVER_OPT_(IN|OUT)_APPS + // Push the updated Sets for stable/prerelease opt-in and opt-out apps to + // corresponding Settings.Global.GAME_DRIVER(_PRERELEASE)?_OPT_(IN|OUT)_APPS Settings.Global.putString(mContentResolver, Settings.Global.GAME_DRIVER_OPT_IN_APPS, String.join(",", mDevOptInApps)); + Settings.Global.putString(mContentResolver, + Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, + String.join(",", mDevPrereleaseOptInApps)); Settings.Global.putString(mContentResolver, Settings.Global.GAME_DRIVER_OPT_OUT_APPS, String.join(",", mDevOptOutApps)); @@ -233,10 +249,13 @@ public class GameDriverAppPreferenceController extends BasePreferenceController listPreference.setEntryValues(mEntryList); // Initialize preference default and summary with the opt in/out choices - // from Settings.Global.GAME_DRIVER_OPT_(IN|OUT)_APPS + // from Settings.Global.GAME_DRIVER(_PRERELEASE)?_OPT_(IN|OUT)_APPS if (mDevOptOutApps.contains(packageName)) { listPreference.setValue(mPreferenceSystem); listPreference.setSummary(mPreferenceSystem); + } else if (mDevPrereleaseOptInApps.contains(packageName)) { + listPreference.setValue(mPreferencePrereleaseDriver); + listPreference.setSummary(mPreferencePrereleaseDriver); } else if (mDevOptInApps.contains(packageName)) { listPreference.setValue(mPreferenceGameDriver); listPreference.setSummary(mPreferenceGameDriver); diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceControllerTest.java index f6fa8e047a7..f007ce257a2 100644 --- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverAppPreferenceControllerTest.java @@ -56,7 +56,8 @@ public class GameDriverAppPreferenceControllerTest { private static final int DEFAULT = 0; private static final int GAME_DRIVER = 1; - private static final int SYSTEM = 2; + private static final int PRERELEASE_DRIVER = 2; + private static final int SYSTEM = 3; private static final String TEST_APP_NAME = "testApp"; private static final String TEST_PKG_NAME = "testPkg"; @@ -181,7 +182,7 @@ public class GameDriverAppPreferenceControllerTest { @Test public void createPreference_configGAME_DRIVER_shouldSetGameDriverAttributes() { - loadConfig(TEST_PKG_NAME, ""); + loadConfig(TEST_PKG_NAME, "", ""); final ListPreference preference = mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME); @@ -195,9 +196,25 @@ public class GameDriverAppPreferenceControllerTest { assertThat(preference.getSummary()).isEqualTo(mValueList[GAME_DRIVER]); } + @Test + public void createPreference_configPRERELEASE_DRIVER_shouldSetPrereleaseDriverAttributes() { + loadConfig("", TEST_PKG_NAME, ""); + final ListPreference preference = + mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME); + + assertThat(preference.getKey()).isEqualTo(TEST_PKG_NAME); + assertThat(preference.getTitle()).isEqualTo(TEST_APP_NAME); + assertThat(preference.getDialogTitle()).isEqualTo(mDialogTitle); + assertThat(preference.getEntries()).isEqualTo(mValueList); + assertThat(preference.getEntryValues()).isEqualTo(mValueList); + assertThat(preference.getEntry()).isEqualTo(mValueList[PRERELEASE_DRIVER]); + assertThat(preference.getValue()).isEqualTo(mValueList[PRERELEASE_DRIVER]); + assertThat(preference.getSummary()).isEqualTo(mValueList[PRERELEASE_DRIVER]); + } + @Test public void createPreference_configSystem_shouldSetSystemAttributes() { - loadConfig("", TEST_PKG_NAME); + loadConfig("", "", TEST_PKG_NAME); final ListPreference preference = mController.createListPreference(mContext, TEST_PKG_NAME, TEST_APP_NAME); @@ -274,10 +291,12 @@ public class GameDriverAppPreferenceControllerTest { when(mContext.getPackageManager()).thenReturn(mPackageManager); } - private void loadDefaultConfig() { loadConfig("", ""); } + private void loadDefaultConfig() { loadConfig("", "", ""); } - private void loadConfig(String optIn, String optOut) { + private void loadConfig(String optIn, String prereleaseOptIn, String optOut) { Settings.Global.putString(mResolver, Settings.Global.GAME_DRIVER_OPT_IN_APPS, optIn); + Settings.Global.putString( + mResolver, Settings.Global.GAME_DRIVER_PRERELEASE_OPT_IN_APPS, prereleaseOptIn); Settings.Global.putString(mResolver, Settings.Global.GAME_DRIVER_OPT_OUT_APPS, optOut); mController = new GameDriverAppPreferenceController(mContext, "testKey"); From 78ef02eb8faff2770d3c020f35b9d0c9bc5e189b Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Thu, 13 Jun 2019 12:29:15 -0400 Subject: [PATCH 2/8] Refresh the whole rule in zen listing screen Because the whole rule is pushed to NMS when it's enabled/disabled. Test: manual Fixes: 135170330 Change-Id: I4bbc30f82dab07cff9184f9ab8a6f729499c6126 --- .../ZenModeAutomaticRulesPreferenceController.java | 2 +- .../android/settings/notification/ZenRulePreference.java | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java index 499bfbc2fea..2f62f4539bd 100644 --- a/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java +++ b/src/com/android/settings/notification/ZenModeAutomaticRulesPreferenceController.java @@ -69,7 +69,7 @@ public class ZenModeAutomaticRulesPreferenceController extends for (int i = 0; i < sortedRules.length; i++) { ZenRulePreference pref = (ZenRulePreference) mPreferenceCategory.getPreference(i); // we are either: - // 1. updating the enabled state or name of the rule + // 1. updating everything about the rule // 2. rule was added or deleted, so reload the entire list if (Objects.equals(pref.mId, sortedRules[i].getKey())) { AutomaticZenRule rule = sortedRules[i].getValue(); diff --git a/src/com/android/settings/notification/ZenRulePreference.java b/src/com/android/settings/notification/ZenRulePreference.java index 8bc602a9c9a..fb6e92a6344 100644 --- a/src/com/android/settings/notification/ZenRulePreference.java +++ b/src/com/android/settings/notification/ZenRulePreference.java @@ -49,7 +49,7 @@ public class ZenRulePreference extends TwoTargetPreference { final ZenServiceListing mServiceListing; final PackageManager mPm; final MetricsFeatureProvider mMetricsFeatureProvider; - final AutomaticZenRule mRule; + AutomaticZenRule mRule; CharSequence mName; private Intent mIntent; @@ -122,14 +122,14 @@ public class ZenRulePreference extends TwoTargetPreference { if (!mRule.getName().equals(rule.getName())) { mName = rule.getName(); setTitle(mName); - mRule.setName(mName.toString()); } if (mRule.isEnabled() != rule.isEnabled()) { - mRule.setEnabled(rule.isEnabled()); setChecked(mRule.isEnabled()); setSummary(computeRuleSummary(mRule)); } + + mRule = rule; } @Override From 687906f2f9445ccd8b54941da418bd0e915199ab Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 10 Jun 2019 19:06:51 -0700 Subject: [PATCH 3/8] Game Driver: Allow user to apply prerelease driver for all apps Currently the global opt-in is only available to Game Driver. This change has added an option to let developers to opt-in all apps to use prerelease driver. GameDriverEnableForAllAppsPreferenceController is then refactored from SwitchPreference to ListPreference to support this change. Bug: 134881329 Test: make RunSettingsRoboTests ROBOTEST_FILTER=GameDriver Change-Id: I6dcb3a22a4033a576605d42aa80b09db088d4aa2 --- res/values/strings.xml | 6 ++ res/xml/game_driver_settings.xml | 7 +- ...rEnableForAllAppsPreferenceController.java | 64 ++++++++++++----- .../GameDriverGlobalSwitchBarController.java | 4 +- ...bleForAllAppsPreferenceControllerTest.java | 72 ++++++++++++++----- 5 files changed, 115 insertions(+), 38 deletions(-) diff --git a/res/values/strings.xml b/res/values/strings.xml index d3f68fcb837..c7bb7b53d47 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10652,6 +10652,12 @@ Prerelease Driver System Graphics Driver + + + @string/game_driver_app_preference_default + @string/game_driver_app_preference_game_driver + @string/game_driver_app_preference_prerelease_driver + @string/game_driver_app_preference_default diff --git a/res/xml/game_driver_settings.xml b/res/xml/game_driver_settings.xml index a04724a786f..6daeefb032c 100644 --- a/res/xml/game_driver_settings.xml +++ b/res/xml/game_driver_settings.xml @@ -21,11 +21,14 @@ android:key="game_driver_settings" android:title="@string/game_driver_dashboard_title"> - - + Date: Thu, 13 Jun 2019 14:07:57 -0700 Subject: [PATCH 4/8] Handle null intent in WifiCallingPreferenceController When intent is null, we will hide wifi calling preference however its listener might still triggered with null intent. This CL update controller so it can handle this event inside listener callback. Fixes: 135095929 Test: RunSettingsRoboTests Change-Id: I4c5aba03871f11a2d9f9b4da329c2c2655ff9adb --- .../telephony/WifiCallingPreferenceController.java | 4 ++++ .../telephony/WifiCallingPreferenceControllerTest.java | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java index c71ee3536b2..4d4d3ef7f01 100644 --- a/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java +++ b/src/com/android/settings/network/telephony/WifiCallingPreferenceController.java @@ -114,6 +114,10 @@ public class WifiCallingPreferenceController extends TelephonyBasePreferenceCont if (mSimCallManager != null) { Intent intent = MobileNetworkUtils.buildPhoneAccountConfigureIntent(mContext, mSimCallManager); + if (intent == null) { + // Do nothing in this case since preference is invisible + return; + } final PackageManager pm = mContext.getPackageManager(); List resolutions = pm.queryIntentActivities(intent, 0); preference.setTitle(resolutions.get(0).loadLabel(pm)); diff --git a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java index 1a0126e4fd6..42422f9e8e5 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/WifiCallingPreferenceControllerTest.java @@ -27,6 +27,7 @@ import android.content.Context; import android.content.Intent; import android.os.PersistableBundle; import android.provider.Settings; +import android.telecom.PhoneAccountHandle; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyManager; @@ -117,6 +118,14 @@ public class WifiCallingPreferenceControllerTest { assertThat(mPreference.isEnabled()).isFalse(); } + @Test + public void updateState_invalidPhoneAccountHandle_shouldNotCrash() { + mController.mSimCallManager = new PhoneAccountHandle(null /* invalid */, ""); + + //Should not crash + mController.updateState(mPreference); + } + @Test public void updateState_wfcNonRoaming() { assertNull(mController.mSimCallManager); From 22b827db555f954dd0db96a502b02f5fe9b3ee1a Mon Sep 17 00:00:00 2001 From: Antony Sargent Date: Wed, 12 Jun 2019 15:33:33 -0700 Subject: [PATCH 5/8] Fix Calls/SMS default SIM selector In cases where a SIM is initially disabled, even after you turn it on the ListPreference's for selecting the default SIM for Calls and SMS weren't working because the preference change listener wasn't getting registered. This CL fixes that for these controllers by always registering a change listener whenever we make the preference visible. Fixes: 134472294 Bug: 135142209 Test: make RunSettingsRoboTests Change-Id: Ia9362b7f26309bdbd6c5e8140fb606b28e2b34d8 --- .../DefaultSubscriptionController.java | 5 +++++ .../DefaultSubscriptionControllerTest.java | 22 +++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java index 02a2d58c009..9eb5f8c4952 100644 --- a/src/com/android/settings/network/telephony/DefaultSubscriptionController.java +++ b/src/com/android/settings/network/telephony/DefaultSubscriptionController.java @@ -121,6 +121,11 @@ public abstract class DefaultSubscriptionController extends BasePreferenceContro } mPreference.setVisible(true); + // TODO(b/135142209) - for now we need to manually ensure we're registered as a change + // listener, because this might not have happened during displayPreference if + // getAvailabilityStatus returned CONDITIONALLY_UNAVAILABLE at the time. + mPreference.setOnPreferenceChangeListener(this); + final List subs = SubscriptionUtil.getActiveSubscriptions(mManager); // We'll have one entry for each available subscription, plus one for a "ask me every diff --git a/tests/robotests/src/com/android/settings/network/telephony/DefaultSubscriptionControllerTest.java b/tests/robotests/src/com/android/settings/network/telephony/DefaultSubscriptionControllerTest.java index 7dd636a4ab8..dbdad505d34 100644 --- a/tests/robotests/src/com/android/settings/network/telephony/DefaultSubscriptionControllerTest.java +++ b/tests/robotests/src/com/android/settings/network/telephony/DefaultSubscriptionControllerTest.java @@ -203,6 +203,28 @@ public class DefaultSubscriptionControllerTest { eq(SubscriptionManager.INVALID_SUBSCRIPTION_ID)); } + @Test + public void onPreferenceChange_prefBecomesAvailable_onPreferenceChangeCallbackNotNull() { + final SubscriptionInfo sub1 = createMockSub(111, "sub1"); + final SubscriptionInfo sub2 = createMockSub(222, "sub2"); + + // Start with only one sub active, so the pref is not available + SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1)); + doReturn(sub1.getSubscriptionId()).when(mController).getDefaultSubscriptionId(); + + mController.displayPreference(mScreen); + assertThat(mController.isAvailable()).isFalse(); + + // Now make two subs be active - the pref should become available, and the + // onPreferenceChange callback should be properly wired up. + SubscriptionUtil.setActiveSubscriptionsForTesting(Arrays.asList(sub1, sub2)); + mController.onSubscriptionsChanged(); + assertThat(mController.isAvailable()).isTrue(); + assertThat(mListPreference.getOnPreferenceChangeListener()).isEqualTo(mController); + mListPreference.callChangeListener("222"); + verify(mController).setDefaultSubscription(eq(222)); + } + @Test public void onSubscriptionsChanged_twoSubscriptionsDefaultChanges_selectedEntryGetsUpdated() { final SubscriptionInfo sub1 = createMockSub(111, "sub1"); From 336b0c23c5c0c49f3f948d0f55a378a49dd32175 Mon Sep 17 00:00:00 2001 From: Yi Jiang Date: Tue, 11 Jun 2019 19:30:34 -0700 Subject: [PATCH 6/8] Move the permission warning message to corresponding layout file. Bug: 129284701 Test: Manually verified Test: atest AdaptiveSleepPermissionPreferenceController Change-Id: Ic31bdb37f751288ae6dcd1253d56806c767e2e47 --- res/xml/adaptive_sleep_detail.xml | 8 +++ ...aptiveSleepDetailPreferenceController.java | 5 +- ...veSleepPermissionPreferenceController.java | 63 +++++++++++++++++++ .../display/AdaptiveSleepSettings.java | 57 ++--------------- ...epPermissionPreferenceControllerTest.java} | 47 +++++++------- 5 files changed, 103 insertions(+), 77 deletions(-) create mode 100644 src/com/android/settings/display/AdaptiveSleepPermissionPreferenceController.java rename tests/robotests/src/com/android/settings/display/{AdaptiveSleepSettingsTest.java => AdaptiveSleepPermissionPreferenceControllerTest.java} (58%) diff --git a/res/xml/adaptive_sleep_detail.xml b/res/xml/adaptive_sleep_detail.xml index 606bb55d465..568e6944581 100644 --- a/res/xml/adaptive_sleep_detail.xml +++ b/res/xml/adaptive_sleep_detail.xml @@ -28,6 +28,14 @@ settings:preview="@drawable/adaptive_sleep" settings:controller="com.android.settings.widget.VideoPreferenceController"/> + + { - final Intent intent = new Intent( - android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); - intent.setData(Uri.parse("package:" + mPackageName)); - mContext.startActivity(intent); - return true; - }); - return preference; - } - - @VisibleForTesting - void setupForTesting(PackageManager packageManager, Context context) { - mContext = context; - mPackageManager = packageManager; - mPermissionRequiredPreference = createPermissionMissionPreference(); - } } diff --git a/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceControllerTest.java similarity index 58% rename from tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java rename to tests/robotests/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceControllerTest.java index 971ebc52d67..f2edf980443 100644 --- a/tests/robotests/src/com/android/settings/display/AdaptiveSleepSettingsTest.java +++ b/tests/robotests/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceControllerTest.java @@ -16,65 +16,68 @@ package com.android.settings.display; +import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE; + 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 android.Manifest; import android.content.Context; import android.content.pm.PackageManager; -import androidx.preference.PreferenceScreen; +import androidx.preference.Preference; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.Mock; +import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.robolectric.RobolectricTestRunner; import org.robolectric.RuntimeEnvironment; @RunWith(RobolectricTestRunner.class) -public class AdaptiveSleepSettingsTest { - private AdaptiveSleepSettings mSettings; - private static final String PACKAGE_NAME = "package_name"; +public class AdaptiveSleepPermissionPreferenceControllerTest { + private final static String PACKAGE_NAME = "package_name"; + private AdaptiveSleepPermissionPreferenceController mController; @Mock private PackageManager mPackageManager; @Mock - private PreferenceScreen mScreen; + private Preference mPreference; @Before public void setUp() { MockitoAnnotations.initMocks(this); - - Context context = RuntimeEnvironment.application; - mSettings = spy(new AdaptiveSleepSettings()); - + Context context = Mockito.spy(RuntimeEnvironment.application); + doReturn(mPackageManager).when(context).getPackageManager(); doReturn(PACKAGE_NAME).when(mPackageManager).getAttentionServicePackageName(); doReturn(PackageManager.PERMISSION_GRANTED).when(mPackageManager).checkPermission( Manifest.permission.CAMERA, PACKAGE_NAME); - doReturn(mScreen).when(mSettings).getPreferenceScreen(); - - mSettings.setupForTesting(mPackageManager, context); - mSettings.onAttach(context); - + mController = new AdaptiveSleepPermissionPreferenceController(context, "test_key"); + doReturn(mController.getPreferenceKey()).when(mPreference).getKey(); } @Test - public void onResume_hasPermission_preferenceInvisible() { - mSettings.onResume(); - - assertThat(mSettings.mPermissionRequiredPreference.isVisible()).isFalse(); + public void getAvailabilityStatus_returnAvailableUnsearchable() { + assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE_UNSEARCHABLE); } @Test - public void onResume_noPermission_preferenceVisible() { + public void updateStates_permissionGranted_preferenceInvisible() { + mController.updateState(mPreference); + + verify(mPreference).setVisible(false); + } + + @Test + public void updateStates_permissionRevoked_preferenceVisible() { doReturn(PackageManager.PERMISSION_DENIED).when(mPackageManager).checkPermission( Manifest.permission.CAMERA, PACKAGE_NAME); - mSettings.onResume(); + mController.updateState(mPreference); - assertThat(mSettings.mPermissionRequiredPreference.isVisible()).isTrue(); + verify(mPreference).setVisible(true); } } From 2d586f18f89051a69e9341c923d1096cb6735aa3 Mon Sep 17 00:00:00 2001 From: Kevin Chyn Date: Fri, 14 Jun 2019 12:56:59 -0700 Subject: [PATCH 7/8] Update string for work profile face unlock Fixes: 134053456 Test: With work profile and fully managed device, strings are correct Change-Id: I358b94acfa0626083fdc422b6333765dcc2bc158 --- res/values/strings.xml | 2 ++ .../face/FaceProfileStatusPreferenceController.java | 11 +++++++++++ .../settings/biometrics/face/FaceSettings.java | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/res/values/strings.xml b/res/values/strings.xml index 5f47c8ce66a..76562534f68 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -888,6 +888,8 @@ Set up face unlock Face unlock + + Face unlock for work How to set up face unlock diff --git a/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java b/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java index 196992dbd9d..18138d571dd 100644 --- a/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java +++ b/src/com/android/settings/biometrics/face/FaceProfileStatusPreferenceController.java @@ -19,6 +19,10 @@ package com.android.settings.biometrics.face; import android.content.Context; import android.os.UserHandle; +import com.android.settings.R; + +import androidx.preference.Preference; + public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceController { public static final String KEY_FACE_SETTINGS = "face_settings_profile"; @@ -37,4 +41,11 @@ public class FaceProfileStatusPreferenceController extends FaceStatusPreferenceC protected int getUserId() { return mProfileChallengeUserId; } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + preference.setTitle(mContext.getResources().getString( + R.string.security_settings_face_profile_preference_title)); + } } diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java index 9766f34cdad..2ec5f7a993d 100644 --- a/src/com/android/settings/biometrics/face/FaceSettings.java +++ b/src/com/android/settings/biometrics/face/FaceSettings.java @@ -119,6 +119,11 @@ public class FaceSettings extends DashboardFragment { mUserId = getActivity().getIntent().getIntExtra( Intent.EXTRA_USER_ID, UserHandle.myUserId()); + if (mUserManager.getUserInfo(mUserId).isManagedProfile()) { + getActivity().setTitle(getActivity().getResources().getString( + R.string.security_settings_face_profile_preference_title)); + } + Preference keyguardPref = findPreference(FaceSettingsKeyguardPreferenceController.KEY); Preference appPref = findPreference(FaceSettingsAppPreferenceController.KEY); Preference attentionPref = findPreference(FaceSettingsAttentionPreferenceController.KEY); From 7d4312596428e2a629da73f5a5524a6eda9da8db Mon Sep 17 00:00:00 2001 From: Mehdi Alizadeh Date: Wed, 22 May 2019 11:22:45 -0700 Subject: [PATCH 8/8] Show a dialog with a slider to set the back gesture's sensitivity Bug: 131447780 Test: Manual test on device Test: make RunSettingsRoboTests ROBOTEST_FILTER=RadioButtonPreferenceWithExtraWidgetTest Test: make RunSettingsRoboTests ROBOTEST_FILTER=SystemNavigationGestureSettingsTest Change-Id: I9fcd1a50c77689118857326de0cf8082e835b491 --- .../dialog_back_gesture_sensitivity.xml | 67 ++++++++ res/values/dimens.xml | 3 + res/values/strings.xml | 11 ++ ...estureNavigationBackSensitivityDialog.java | 81 ++++++++++ .../GestureNavigationNotAvailableDialog.java | 63 ++++++++ .../SystemNavigationGestureSettings.java | 150 ++++++++++++------ .../RadioButtonPreferenceWithExtraWidget.java | 10 ++ .../SystemNavigationGestureSettingsTest.java | 146 ++++++++++++++--- ...ioButtonPreferenceWithExtraWidgetTest.java | 13 ++ 9 files changed, 470 insertions(+), 74 deletions(-) create mode 100644 res/layout/dialog_back_gesture_sensitivity.xml create mode 100644 src/com/android/settings/gestures/GestureNavigationBackSensitivityDialog.java create mode 100644 src/com/android/settings/gestures/GestureNavigationNotAvailableDialog.java diff --git a/res/layout/dialog_back_gesture_sensitivity.xml b/res/layout/dialog_back_gesture_sensitivity.xml new file mode 100644 index 00000000000..37ef7714137 --- /dev/null +++ b/res/layout/dialog_back_gesture_sensitivity.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/res/values/dimens.xml b/res/values/dimens.xml index fbf1a24d7a9..f31a2667ca5 100755 --- a/res/values/dimens.xml +++ b/res/values/dimens.xml @@ -411,4 +411,7 @@ 480dp + + + 320dp diff --git a/res/values/strings.xml b/res/values/strings.xml index 6e92a3d6613..6df98f118ef 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -10225,6 +10225,17 @@ Information + + Low + + High + + + \nHigher sensitivity may conflict with any app gestures along the edges of the screen. + + + Back Sensitivity + Double-tap to check phone diff --git a/src/com/android/settings/gestures/GestureNavigationBackSensitivityDialog.java b/src/com/android/settings/gestures/GestureNavigationBackSensitivityDialog.java new file mode 100644 index 00000000000..164705bfe65 --- /dev/null +++ b/src/com/android/settings/gestures/GestureNavigationBackSensitivityDialog.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2019 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.app.AlertDialog; +import android.app.Dialog; +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.content.om.IOverlayManager; +import android.os.Bundle; +import android.os.ServiceManager; +import android.view.View; +import android.widget.SeekBar; + +import com.android.settings.R; +import com.android.settings.core.instrumentation.InstrumentedDialogFragment; + +/** + * Dialog to set the back gesture's sensitivity in Gesture navigation mode. + */ +public class GestureNavigationBackSensitivityDialog extends InstrumentedDialogFragment { + private static final String TAG = "GestureNavigationBackSensitivityDialog"; + private static final String KEY_BACK_SENSITIVITY = "back_sensitivity"; + + public static void show(SystemNavigationGestureSettings parent, int sensitivity) { + if (!parent.isAdded()) { + return; + } + + final GestureNavigationBackSensitivityDialog dialog = + new GestureNavigationBackSensitivityDialog(); + final Bundle bundle = new Bundle(); + bundle.putInt(KEY_BACK_SENSITIVITY, sensitivity); + dialog.setArguments(bundle); + dialog.setTargetFragment(parent, 0); + dialog.show(parent.getFragmentManager(), TAG); + } + + @Override + public int getMetricsCategory() { + // TODO(135211145): Use a separate metrics category for this dialog. + return SettingsEnums.SETTINGS_GESTURE_SWIPE_UP; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final View view = getActivity().getLayoutInflater().inflate( + R.layout.dialog_back_gesture_sensitivity, null); + final SeekBar seekBar = view.findViewById(R.id.back_sensitivity_seekbar); + seekBar.setProgress(getArguments().getInt(KEY_BACK_SENSITIVITY)); + return new AlertDialog.Builder(getContext()) + .setTitle(R.string.back_sensitivity_dialog_title) + .setMessage(R.string.back_sensitivity_dialog_message) + .setView(view) + .setPositiveButton(R.string.okay, (dialog, which) -> { + int sensitivity = seekBar.getProgress(); + getArguments().putInt(KEY_BACK_SENSITIVITY, sensitivity); + SystemNavigationGestureSettings.setBackSensitivity(getActivity(), + getOverlayManager(), sensitivity); + }) + .create(); + } + + private IOverlayManager getOverlayManager() { + return IOverlayManager.Stub.asInterface(ServiceManager.getService(Context.OVERLAY_SERVICE)); + } +} \ No newline at end of file diff --git a/src/com/android/settings/gestures/GestureNavigationNotAvailableDialog.java b/src/com/android/settings/gestures/GestureNavigationNotAvailableDialog.java new file mode 100644 index 00000000000..e69db274011 --- /dev/null +++ b/src/com/android/settings/gestures/GestureNavigationNotAvailableDialog.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2019 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.app.AlertDialog; +import android.app.Dialog; +import android.app.settings.SettingsEnums; +import android.content.Context; +import android.os.Bundle; + +import com.android.settings.R; +import com.android.settings.core.instrumentation.InstrumentedDialogFragment; + +/** + * Dialog to notify user that gesture navigation is not available because of unsupported launcher. + */ +public class GestureNavigationNotAvailableDialog extends InstrumentedDialogFragment { + private static final String TAG = "GestureNavigationNotAvailableDialog"; + + public static void show(SystemNavigationGestureSettings parent) { + if (!parent.isAdded()) { + return; + } + + final GestureNavigationNotAvailableDialog dialog = + new GestureNavigationNotAvailableDialog(); + dialog.setTargetFragment(parent, 0); + dialog.show(parent.getFragmentManager(), TAG); + } + + @Override + public int getMetricsCategory() { + // TODO(135211145): Use a separate metrics category for this dialog. + return SettingsEnums.SETTINGS_GESTURE_SWIPE_UP; + } + + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + final Context context = getActivity(); + final String defaultHomeAppName = SystemNavigationPreferenceController + .getDefaultHomeAppName(context); + final String message = getString(R.string.gesture_not_supported_dialog_message, + defaultHomeAppName); + return new AlertDialog.Builder(context) + .setMessage(message) + .setPositiveButton(R.string.okay, null) + .create(); + } +} \ No newline at end of file diff --git a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java index 28b76b2b011..b3d090d75f2 100644 --- a/src/com/android/settings/gestures/SystemNavigationGestureSettings.java +++ b/src/com/android/settings/gestures/SystemNavigationGestureSettings.java @@ -23,14 +23,15 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OV import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE; import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_INFO; +import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_SETTING; -import android.app.AlertDialog; import android.accessibilityservice.AccessibilityServiceInfo; import android.app.settings.SettingsEnums; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.om.IOverlayManager; +import android.content.om.OverlayInfo; import android.graphics.drawable.Drawable; import android.os.RemoteException; import android.os.ServiceManager; @@ -64,6 +65,11 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { private static final String TAG = "SystemNavigationGesture"; + @VisibleForTesting + static final String SHARED_PREFERENCES_NAME = "system_navigation_settings_preferences"; + @VisibleForTesting + static final String PREFS_BACK_SENSITIVITY_KEY = "system_navigation_back_sensitivity"; + @VisibleForTesting static final String KEY_SYSTEM_NAV_3BUTTONS = "system_nav_3buttons"; @VisibleForTesting @@ -74,6 +80,25 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { public static final String PREF_KEY_SUGGESTION_COMPLETE = "pref_system_navigation_suggestion_complete"; + @VisibleForTesting + static final String NAV_BAR_MODE_GESTURAL_OVERLAY_NARROW_BACK + = "com.android.internal.systemui.navbar.gestural_narrow_back"; + @VisibleForTesting + static final String NAV_BAR_MODE_GESTURAL_OVERLAY_WIDE_BACK + = "com.android.internal.systemui.navbar.gestural_wide_back"; + @VisibleForTesting + static final String NAV_BAR_MODE_GESTURAL_OVERLAY_EXTRA_WIDE_BACK + = "com.android.internal.systemui.navbar.gestural_extra_wide_back"; + @VisibleForTesting + static final String[] BACK_GESTURE_INSET_OVERLAYS = { + NAV_BAR_MODE_GESTURAL_OVERLAY_NARROW_BACK, + NAV_BAR_MODE_GESTURAL_OVERLAY, + NAV_BAR_MODE_GESTURAL_OVERLAY_WIDE_BACK, + NAV_BAR_MODE_GESTURAL_OVERLAY_EXTRA_WIDE_BACK + }; + @VisibleForTesting + static int BACK_GESTURE_INSET_DEFAULT_OVERLAY = 1; + private IOverlayManager mOverlayManager; private VideoPreference mVideoPreference; @@ -91,6 +116,9 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { mVideoPreference = new VideoPreference(context); setIllustrationVideo(mVideoPreference, getDefaultKey()); + mVideoPreference.setHeight( /* Illustration height in dp */ + getResources().getDimension(R.dimen.system_navigation_illustration_height) + / getResources().getDisplayMetrics().density); } @Override @@ -98,11 +126,6 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { return SettingsEnums.SETTINGS_GESTURE_SWIPE_UP; } - @Override - protected int getPreferenceScreenResId() { - return R.xml.system_navigation_gesture_settings; - } - @Override public void updateCandidates() { final String defaultKey = getDefaultKey(); @@ -125,6 +148,39 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { mayCheckOnlyRadioButton(); } + @Override + public void bindPreferenceExtra(RadioButtonPreference pref, + String key, CandidateInfo info, String defaultKey, String systemDefaultKey) { + if (!(info instanceof NavModeCandidateInfo) + || !(pref instanceof RadioButtonPreferenceWithExtraWidget)) { + return; + } + + pref.setSummary(((NavModeCandidateInfo) info).loadSummary()); + + RadioButtonPreferenceWithExtraWidget p = (RadioButtonPreferenceWithExtraWidget) pref; + if (info.getKey() == KEY_SYSTEM_NAV_GESTURAL) { + if (SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher( + getContext())) { + p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING); + p.setExtraWidgetOnClickListener((v) -> GestureNavigationBackSensitivityDialog + .show(this, getBackSensitivity(getContext(), mOverlayManager))); + } else { + p.setEnabled(false); + p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_INFO); + p.setExtraWidgetOnClickListener((v) -> + GestureNavigationNotAvailableDialog.show(this)); + } + } else { + p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE); + } + } + + @Override + protected int getPreferenceScreenResId() { + return R.xml.system_navigation_gesture_settings; + } + @Override protected List getCandidates() { final Context c = getContext(); @@ -169,7 +225,7 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { return false; } - setCurrentSystemNavigationMode(mOverlayManager, key); + setCurrentSystemNavigationMode(c, mOverlayManager, key); setIllustrationVideo(mVideoPreference, key); if (TextUtils.equals(KEY_SYSTEM_NAV_GESTURAL, key) && ( isAnyServiceSupportAccessibilityButton() || isNavBarMagnificationEnabled())) { @@ -180,6 +236,37 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { return true; } + @VisibleForTesting + static void setBackSensitivity(Context context, IOverlayManager overlayManager, + int sensitivity) { + if (sensitivity < 0 || sensitivity >= BACK_GESTURE_INSET_OVERLAYS.length) { + throw new IllegalArgumentException("Sensitivity out of range."); + } + + // Store the sensitivity level, to be able to restore when user returns to Gesture Nav mode + context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE).edit() + .putInt(PREFS_BACK_SENSITIVITY_KEY, sensitivity).apply(); + if (getCurrentSystemNavigationMode(context) == KEY_SYSTEM_NAV_GESTURAL) { + setNavBarInteractionMode(overlayManager, BACK_GESTURE_INSET_OVERLAYS[sensitivity]); + } + } + + @VisibleForTesting + static int getBackSensitivity(Context context, IOverlayManager overlayManager) { + for (int i = 0; i < BACK_GESTURE_INSET_OVERLAYS.length; i++) { + OverlayInfo info = null; + try { + info = overlayManager.getOverlayInfo(BACK_GESTURE_INSET_OVERLAYS[i], USER_CURRENT); + } catch (RemoteException e) { /* Do nothing */ } + if (info != null && info.isEnabled()) { + return i; + } + } + // If Gesture nav is not selected, read the value from shared preferences. + return context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_PRIVATE) + .getInt(PREFS_BACK_SENSITIVITY_KEY, BACK_GESTURE_INSET_DEFAULT_OVERLAY); + } + @VisibleForTesting static String getCurrentSystemNavigationMode(Context context) { if (SystemNavigationPreferenceController.isEdgeToEdgeEnabled(context)) { @@ -192,10 +279,12 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { } @VisibleForTesting - static void setCurrentSystemNavigationMode(IOverlayManager overlayManager, String key) { + static void setCurrentSystemNavigationMode(Context context, IOverlayManager overlayManager, + String key) { switch (key) { case KEY_SYSTEM_NAV_GESTURAL: - setNavBarInteractionMode(overlayManager, NAV_BAR_MODE_GESTURAL_OVERLAY); + int sensitivity = getBackSensitivity(context, overlayManager); + setNavBarInteractionMode(overlayManager, BACK_GESTURE_INSET_OVERLAYS[sensitivity]); break; case KEY_SYSTEM_NAV_2BUTTONS: setNavBarInteractionMode(overlayManager, NAV_BAR_MODE_2BUTTON_OVERLAY); @@ -206,10 +295,8 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { } } - /** - * Enables the specified overlay package. - */ - static void setNavBarInteractionMode(IOverlayManager overlayManager, String overlayPackage) { + private static void setNavBarInteractionMode(IOverlayManager overlayManager, + String overlayPackage) { try { overlayManager.setEnabledExclusiveInCategory(overlayPackage, USER_CURRENT); } catch (RemoteException e) { @@ -217,7 +304,7 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { } } - static void setIllustrationVideo(VideoPreference videoPref, String systemNavKey) { + private static void setIllustrationVideo(VideoPreference videoPref, String systemNavKey) { videoPref.setVideo(0, 0); switch (systemNavKey) { case KEY_SYSTEM_NAV_GESTURAL: @@ -233,41 +320,6 @@ public class SystemNavigationGestureSettings extends RadioButtonPickerFragment { } } - @Override - public void bindPreferenceExtra(RadioButtonPreference pref, - String key, CandidateInfo info, String defaultKey, String systemDefaultKey) { - if (!(info instanceof NavModeCandidateInfo) - || !(pref instanceof RadioButtonPreferenceWithExtraWidget)) { - return; - } - - pref.setSummary(((NavModeCandidateInfo) info).loadSummary()); - - RadioButtonPreferenceWithExtraWidget p = (RadioButtonPreferenceWithExtraWidget) pref; - if (info.getKey() == KEY_SYSTEM_NAV_GESTURAL - && !SystemNavigationPreferenceController.isGestureNavSupportedByDefaultLauncher( - getContext())) { - p.setEnabled(false); - p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_INFO); - p.setExtraWidgetOnClickListener((v) -> { - showGestureNavDisabledDialog(); - }); - } else { - p.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE); - } - } - - private void showGestureNavDisabledDialog() { - final String defaultHomeAppName = SystemNavigationPreferenceController - .getDefaultHomeAppName(getContext()); - final String message = getString(R.string.gesture_not_supported_dialog_message, - defaultHomeAppName); - AlertDialog d = new AlertDialog.Builder(getContext()) - .setMessage(message) - .setPositiveButton(R.string.okay, null) - .show(); - } - private boolean isAnyServiceSupportAccessibilityButton() { final AccessibilityManager ams = (AccessibilityManager) getContext().getSystemService( Context.ACCESSIBILITY_SERVICE); diff --git a/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidget.java b/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidget.java index 6a47ce516af..19fd92377c8 100644 --- a/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidget.java +++ b/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidget.java @@ -27,6 +27,7 @@ import com.android.settings.R; public class RadioButtonPreferenceWithExtraWidget extends RadioButtonPreference { public static final int EXTRA_WIDGET_VISIBILITY_GONE = 0; public static final int EXTRA_WIDGET_VISIBILITY_INFO = 1; + public static final int EXTRA_WIDGET_VISIBILITY_SETTING = 2; private View mExtraWidgetDivider; private ImageView mExtraWidget; @@ -66,6 +67,15 @@ public class RadioButtonPreferenceWithExtraWidget extends RadioButtonPreference mExtraWidget.setClickable(true); mExtraWidget.setVisibility(View.VISIBLE); mExtraWidgetDivider.setVisibility(View.VISIBLE); + if (mExtraWidgetVisibility == EXTRA_WIDGET_VISIBILITY_INFO) { + mExtraWidget.setImageResource(R.drawable.ic_settings_about); + mExtraWidget.setContentDescription( + getContext().getResources().getText(R.string.information_label)); + } else if (mExtraWidgetVisibility == EXTRA_WIDGET_VISIBILITY_SETTING) { + mExtraWidget.setImageResource(R.drawable.ic_settings_accent); + mExtraWidget.setContentDescription( + getContext().getResources().getText(R.string.settings_label)); + } } } diff --git a/tests/robotests/src/com/android/settings/gestures/SystemNavigationGestureSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/SystemNavigationGestureSettingsTest.java index 1f3a758fd0f..24cb9ed3253 100644 --- a/tests/robotests/src/com/android/settings/gestures/SystemNavigationGestureSettingsTest.java +++ b/tests/robotests/src/com/android/settings/gestures/SystemNavigationGestureSettingsTest.java @@ -24,21 +24,30 @@ import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVE import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL; import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL_OVERLAY; +import static com.android.settings.gestures.SystemNavigationGestureSettings.BACK_GESTURE_INSET_DEFAULT_OVERLAY; +import static com.android.settings.gestures.SystemNavigationGestureSettings.BACK_GESTURE_INSET_OVERLAYS; import static com.android.settings.gestures.SystemNavigationGestureSettings.KEY_SYSTEM_NAV_2BUTTONS; import static com.android.settings.gestures.SystemNavigationGestureSettings.KEY_SYSTEM_NAV_3BUTTONS; import static com.android.settings.gestures.SystemNavigationGestureSettings.KEY_SYSTEM_NAV_GESTURAL; +import static com.android.settings.gestures.SystemNavigationGestureSettings.NAV_BAR_MODE_GESTURAL_OVERLAY_EXTRA_WIDE_BACK; +import static com.android.settings.gestures.SystemNavigationGestureSettings.NAV_BAR_MODE_GESTURAL_OVERLAY_NARROW_BACK; +import static com.android.settings.gestures.SystemNavigationGestureSettings.NAV_BAR_MODE_GESTURAL_OVERLAY_WIDE_BACK; import static com.google.common.truth.Truth.assertThat; -import static org.mockito.Mockito.mock; +import static junit.framework.Assert.assertEquals; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; import android.content.Context; import android.content.om.IOverlayManager; -import android.os.ServiceManager; +import android.content.om.OverlayInfo; import android.provider.SearchIndexableResource; -import android.text.TextUtils; import com.android.internal.R; import com.android.settings.testutils.shadow.SettingsShadowResources; @@ -46,6 +55,8 @@ import com.android.settings.testutils.shadow.SettingsShadowResources; 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; import org.robolectric.annotation.Config; @@ -57,17 +68,25 @@ import java.util.List; public class SystemNavigationGestureSettingsTest { private Context mContext; - - private IOverlayManager mOverlayManager; - private SystemNavigationGestureSettings mSettings; - @Before - public void setUp() { - mContext = RuntimeEnvironment.application; - mOverlayManager = mock(IOverlayManager.class); + @Mock + private IOverlayManager mOverlayManager; + @Mock + private OverlayInfo mOverlayInfoEnabled; + @Mock + private OverlayInfo mOverlayInfoDisabled; + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mContext = RuntimeEnvironment.application; mSettings = new SystemNavigationGestureSettings(); + + when(mOverlayInfoDisabled.isEnabled()).thenReturn(false); + when(mOverlayInfoEnabled.isEnabled()).thenReturn(true); + when(mOverlayManager.getOverlayInfo(any(), anyInt())).thenReturn(mOverlayInfoDisabled); } @Test @@ -82,34 +101,111 @@ public class SystemNavigationGestureSettingsTest { @Test public void testGetCurrentSystemNavigationMode() { - SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode, - NAV_BAR_MODE_GESTURAL); - assertThat(TextUtils.equals(mSettings.getCurrentSystemNavigationMode(mContext), - KEY_SYSTEM_NAV_GESTURAL)).isTrue(); + SettingsShadowResources.overrideResource( + R.integer.config_navBarInteractionMode, NAV_BAR_MODE_GESTURAL); + assertEquals(KEY_SYSTEM_NAV_GESTURAL, mSettings.getCurrentSystemNavigationMode(mContext)); - SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode, - NAV_BAR_MODE_3BUTTON); - assertThat(TextUtils.equals(mSettings.getCurrentSystemNavigationMode(mContext), - KEY_SYSTEM_NAV_3BUTTONS)).isTrue(); + SettingsShadowResources.overrideResource( + R.integer.config_navBarInteractionMode, NAV_BAR_MODE_3BUTTON); + assertEquals(KEY_SYSTEM_NAV_3BUTTONS, mSettings.getCurrentSystemNavigationMode(mContext)); - SettingsShadowResources.overrideResource(R.integer.config_navBarInteractionMode, - NAV_BAR_MODE_2BUTTON); - assertThat(TextUtils.equals(mSettings.getCurrentSystemNavigationMode(mContext), - KEY_SYSTEM_NAV_2BUTTONS)).isTrue(); + SettingsShadowResources.overrideResource( + R.integer.config_navBarInteractionMode, NAV_BAR_MODE_2BUTTON); + assertEquals(KEY_SYSTEM_NAV_2BUTTONS, mSettings.getCurrentSystemNavigationMode(mContext)); } @Test public void testSetCurrentSystemNavigationMode() throws Exception { - mSettings.setCurrentSystemNavigationMode(mOverlayManager, KEY_SYSTEM_NAV_GESTURAL); + mSettings.setBackSensitivity(mContext, mOverlayManager, 0); + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_GESTURAL); + verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( + NAV_BAR_MODE_GESTURAL_OVERLAY_NARROW_BACK, USER_CURRENT); + + mSettings.setBackSensitivity(mContext, mOverlayManager, 1); + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_GESTURAL); verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( NAV_BAR_MODE_GESTURAL_OVERLAY, USER_CURRENT); - mSettings.setCurrentSystemNavigationMode(mOverlayManager, KEY_SYSTEM_NAV_2BUTTONS); + mSettings.setBackSensitivity(mContext, mOverlayManager, 2); + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_GESTURAL); + verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( + NAV_BAR_MODE_GESTURAL_OVERLAY_WIDE_BACK, USER_CURRENT); + + mSettings.setBackSensitivity(mContext, mOverlayManager, 3); + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_GESTURAL); + verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( + NAV_BAR_MODE_GESTURAL_OVERLAY_EXTRA_WIDE_BACK, USER_CURRENT); + + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_2BUTTONS); verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( NAV_BAR_MODE_2BUTTON_OVERLAY, USER_CURRENT); - mSettings.setCurrentSystemNavigationMode(mOverlayManager, KEY_SYSTEM_NAV_3BUTTONS); + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_3BUTTONS); verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT); } + + @Test + public void testSetCurrentSystemNavigationMode_backSensitivityValuePersists() throws Exception { + SettingsShadowResources.overrideResource( + R.integer.config_navBarInteractionMode, NAV_BAR_MODE_3BUTTON); + + mSettings.setBackSensitivity(mContext, mOverlayManager, 2); + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_3BUTTONS); + verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( + NAV_BAR_MODE_3BUTTON_OVERLAY, USER_CURRENT); + + // Return to Gesture navigation, without setting the sensitivity value. + mSettings.setCurrentSystemNavigationMode(mContext, mOverlayManager, + KEY_SYSTEM_NAV_GESTURAL); + verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( + NAV_BAR_MODE_GESTURAL_OVERLAY_WIDE_BACK, USER_CURRENT); + } + + @Test + public void testGetBackSensitivity_default() { + assertEquals(BACK_GESTURE_INSET_DEFAULT_OVERLAY, + mSettings.getBackSensitivity(mContext, mOverlayManager)); + } + + @Test + public void testBackSensitivitySetterAndGetter_currentNavModeNotGestural() throws Exception { + SettingsShadowResources.overrideResource( + R.integer.config_navBarInteractionMode, NAV_BAR_MODE_3BUTTON); + + mSettings.setBackSensitivity(mContext, mOverlayManager, 3); + assertEquals(3, mSettings.getBackSensitivity(mContext, mOverlayManager)); + mSettings.setBackSensitivity(mContext, mOverlayManager, 2); + assertEquals(2, mSettings.getBackSensitivity(mContext, mOverlayManager)); + + verify(mOverlayManager, never()).setEnabledExclusiveInCategory(any(), anyInt()); + } + + @Test + public void testBackSensitivitySetterAndGetter_currentNavModeIsGestural() throws Exception { + SettingsShadowResources.overrideResource( + R.integer.config_navBarInteractionMode, NAV_BAR_MODE_GESTURAL); + + when(mOverlayManager.getOverlayInfo(BACK_GESTURE_INSET_OVERLAYS[3], USER_CURRENT)) + .thenReturn(mOverlayInfoEnabled); + mSettings.setBackSensitivity(mContext, mOverlayManager, 3); + assertEquals(3, mSettings.getBackSensitivity(mContext, mOverlayManager)); + + when(mOverlayManager.getOverlayInfo(BACK_GESTURE_INSET_OVERLAYS[2], USER_CURRENT)) + .thenReturn(mOverlayInfoEnabled); + mSettings.setBackSensitivity(mContext, mOverlayManager, 2); + assertEquals(2, mSettings.getBackSensitivity(mContext, mOverlayManager)); + + verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( + NAV_BAR_MODE_GESTURAL_OVERLAY_WIDE_BACK, USER_CURRENT); + verify(mOverlayManager, times(1)).setEnabledExclusiveInCategory( + NAV_BAR_MODE_GESTURAL_OVERLAY_EXTRA_WIDE_BACK, USER_CURRENT); + } } diff --git a/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidgetTest.java b/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidgetTest.java index b84b3bb48d8..2e2d786787e 100644 --- a/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidgetTest.java +++ b/tests/robotests/src/com/android/settings/widget/RadioButtonPreferenceWithExtraWidgetTest.java @@ -18,6 +18,7 @@ package com.android.settings.widget; import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE; import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_INFO; +import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_SETTING; import static com.google.common.truth.Truth.assertThat; @@ -104,6 +105,18 @@ public class RadioButtonPreferenceWithExtraWidgetTest { assertEquals(View.VISIBLE, mExtraWidget.getVisibility()); assertEquals(View.VISIBLE, mExtraWidgetDivider.getVisibility()); assertThat(mExtraWidget.isClickable()).isTrue(); + assertEquals(mContext.getResources().getText(R.string.information_label), + mExtraWidget.getContentDescription()); + } + + @Test + public void testSetExtraWidgetVisibility_setting() { + mPreference.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING); + assertEquals(View.VISIBLE, mExtraWidget.getVisibility()); + assertEquals(View.VISIBLE, mExtraWidgetDivider.getVisibility()); + assertThat(mExtraWidget.isClickable()).isTrue(); + assertEquals(mContext.getResources().getText(R.string.settings_label), + mExtraWidget.getContentDescription()); } @Test