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 7c97ec83948..e077ff8de6a 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 @@ -10235,6 +10237,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 @@ -10658,12 +10671,21 @@ 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_default @string/game_driver_app_preference_game_driver + @string/game_driver_app_preference_prerelease_driver @string/game_driver_app_preference_system 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"/> + + - - + 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/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceController.java b/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceController.java index dd48f6946f3..290e4b2a1d0 100644 --- a/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceController.java +++ b/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceController.java @@ -18,15 +18,17 @@ package com.android.settings.development.gamedriver; import android.content.ContentResolver; import android.content.Context; +import android.content.res.Resources; import android.os.Handler; import android.os.Looper; import android.provider.Settings; import androidx.annotation.VisibleForTesting; +import androidx.preference.ListPreference; import androidx.preference.Preference; import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; +import com.android.settings.R; import com.android.settings.core.BasePreferenceController; import com.android.settingslib.core.lifecycle.LifecycleObserver; import com.android.settingslib.core.lifecycle.events.OnStart; @@ -43,19 +45,30 @@ public class GameDriverEnableForAllAppsPreferenceController extends BasePreferen public static final int GAME_DRIVER_DEFAULT = 0; public static final int GAME_DRIVER_ALL_APPS = 1; - public static final int GAME_DRIVER_OFF = 2; + public static final int GAME_DRIVER_PRERELEASE_ALL_APPS = 2; + public static final int GAME_DRIVER_OFF = 3; private final Context mContext; private final ContentResolver mContentResolver; + private final String mPreferenceDefault; + private final String mPreferenceGameDriver; + private final String mPreferencePrereleaseDriver; @VisibleForTesting GameDriverContentObserver mGameDriverContentObserver; - private SwitchPreference mPreference; + private ListPreference mPreference; public GameDriverEnableForAllAppsPreferenceController(Context context, String key) { super(context, key); mContext = context; mContentResolver = context.getContentResolver(); + + final Resources resources = context.getResources(); + 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); mGameDriverContentObserver = new GameDriverContentObserver(new Handler(Looper.getMainLooper()), this); } @@ -89,31 +102,44 @@ public class GameDriverEnableForAllAppsPreferenceController extends BasePreferen @Override public void updateState(Preference preference) { - final SwitchPreference switchPreference = (SwitchPreference) preference; - switchPreference.setVisible(isAvailable()); - switchPreference.setChecked( - Settings.Global.getInt( - mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT) - == GAME_DRIVER_ALL_APPS); + final ListPreference listPref = (ListPreference) preference; + listPref.setVisible(isAvailable()); + final int currentChoice = Settings.Global.getInt( + mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); + if (currentChoice == GAME_DRIVER_ALL_APPS) { + listPref.setValue(mPreferenceGameDriver); + listPref.setSummary(mPreferenceGameDriver); + } else if (currentChoice == GAME_DRIVER_PRERELEASE_ALL_APPS) { + listPref.setValue(mPreferencePrereleaseDriver); + listPref.setSummary(mPreferencePrereleaseDriver); + } else { + listPref.setValue(mPreferenceDefault); + listPref.setSummary(mPreferenceDefault); + } } @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - final boolean isChecked = (boolean) newValue; - final int gameDriver = Settings.Global.getInt( + final ListPreference listPref = (ListPreference) preference; + final String value = newValue.toString(); + final int currentChoice = Settings.Global.getInt( mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); - - if (isChecked && gameDriver == GAME_DRIVER_ALL_APPS) { - return true; + final int userChoice; + if (value.equals(mPreferenceGameDriver)) { + userChoice = GAME_DRIVER_ALL_APPS; + } else if (value.equals(mPreferencePrereleaseDriver)) { + userChoice = GAME_DRIVER_PRERELEASE_ALL_APPS; + } else { + userChoice = GAME_DRIVER_DEFAULT; } + listPref.setValue(value); + listPref.setSummary(value); - if (!isChecked && (gameDriver == GAME_DRIVER_DEFAULT || gameDriver == GAME_DRIVER_OFF)) { - return true; + if (userChoice != currentChoice) { + Settings.Global.putInt( + mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, userChoice); } - Settings.Global.putInt(mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, - isChecked ? GAME_DRIVER_ALL_APPS : GAME_DRIVER_DEFAULT); - return true; } diff --git a/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarController.java b/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarController.java index d84c28f3f5b..15f71e0375d 100644 --- a/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarController.java +++ b/src/com/android/settings/development/gamedriver/GameDriverGlobalSwitchBarController.java @@ -19,6 +19,7 @@ package com.android.settings.development.gamedriver; import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS; import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT; import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF; +import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_PRERELEASE_ALL_APPS; import android.content.ContentResolver; import android.content.Context; @@ -83,7 +84,8 @@ public class GameDriverGlobalSwitchBarController mContentResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); if (isChecked - && (gameDriver == GAME_DRIVER_DEFAULT || gameDriver == GAME_DRIVER_ALL_APPS)) { + && (gameDriver == GAME_DRIVER_DEFAULT || gameDriver == GAME_DRIVER_ALL_APPS + || gameDriver == GAME_DRIVER_PRERELEASE_ALL_APPS)) { return true; } diff --git a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java index ab7465cfd3f..0e2358c806b 100644 --- a/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java +++ b/src/com/android/settings/display/AdaptiveSleepDetailPreferenceController.java @@ -21,11 +21,9 @@ import android.content.Context; import androidx.preference.Preference; public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPreferenceController { - private final Context mContext; public AdaptiveSleepDetailPreferenceController(Context context, String key) { super(context, key); - mContext = context; } @Override @@ -45,7 +43,6 @@ public class AdaptiveSleepDetailPreferenceController extends AdaptiveSleepPrefer @Override public void updateState(Preference preference) { super.updateState(preference); - preference.setEnabled(AdaptiveSleepPreferenceController.hasSufficientPermission( - mContext.getPackageManager())); + preference.setEnabled(hasSufficientPermission(mContext.getPackageManager())); } } \ No newline at end of file diff --git a/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceController.java b/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceController.java new file mode 100644 index 00000000000..9e6bca453e4 --- /dev/null +++ b/src/com/android/settings/display/AdaptiveSleepPermissionPreferenceController.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.display; + +import static com.android.settings.display.AdaptiveSleepPreferenceController.hasSufficientPermission; + +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.text.TextUtils; + +import androidx.preference.Preference; + +import com.android.settings.core.BasePreferenceController; + +public class AdaptiveSleepPermissionPreferenceController extends BasePreferenceController { + final static String PREF_NAME = "adaptive_sleep_permission"; + private final Intent mIntent; + + public AdaptiveSleepPermissionPreferenceController(Context context, String key) { + super(context, key); + final String packageName = context.getPackageManager().getAttentionServicePackageName(); + mIntent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + mIntent.setData(Uri.parse("package:" + packageName)); + } + + @Override + @AvailabilityStatus + public int getAvailabilityStatus() { + return AVAILABLE_UNSEARCHABLE; + } + + @Override + public boolean handlePreferenceTreeClick(Preference preference) { + if (TextUtils.equals(getPreferenceKey(), preference.getKey())) { + mContext.startActivity(mIntent); + return true; + } + return super.handlePreferenceTreeClick(preference); + } + + @Override + public void updateState(Preference preference) { + super.updateState(preference); + if (TextUtils.equals(getPreferenceKey(), preference.getKey())) { + preference.setVisible(!hasSufficientPermission(mContext.getPackageManager())); + } + } +} diff --git a/src/com/android/settings/display/AdaptiveSleepSettings.java b/src/com/android/settings/display/AdaptiveSleepSettings.java index 94abe1aba0d..66e20b4b8fd 100644 --- a/src/com/android/settings/display/AdaptiveSleepSettings.java +++ b/src/com/android/settings/display/AdaptiveSleepSettings.java @@ -16,21 +16,16 @@ package com.android.settings.display; -import static com.android.settings.display.AdaptiveSleepPreferenceController.hasSufficientPermission; import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF; import static com.android.settings.homepage.contextualcards.slices.ContextualAdaptiveSleepSlice.PREF_KEY_INTERACTED; import android.app.settings.SettingsEnums; import android.content.Context; -import android.content.Intent; -import android.content.pm.PackageManager; -import android.net.Uri; import android.os.Bundle; import android.provider.SearchIndexableResource; import androidx.preference.Preference; -import com.android.internal.annotations.VisibleForTesting; import com.android.settings.R; import com.android.settings.dashboard.DashboardFragment; import com.android.settings.search.BaseSearchIndexProvider; @@ -45,11 +40,6 @@ public class AdaptiveSleepSettings extends DashboardFragment { private static final String TAG = "AdaptiveSleepSettings"; private Context mContext; - private String mPackageName; - private PackageManager mPackageManager; - - @VisibleForTesting - Preference mPermissionRequiredPreference; @Override public void onCreate(Bundle icicle) { @@ -57,32 +47,22 @@ public class AdaptiveSleepSettings extends DashboardFragment { final FooterPreference footerPreference = mFooterPreferenceMixin.createFooterPreference(); mContext = getContext(); - mPermissionRequiredPreference = createPermissionMissionPreference(); footerPreference.setIcon(R.drawable.ic_privacy_shield_24dp); footerPreference.setTitle(R.string.adaptive_sleep_privacy); - getPreferenceScreen().addPreference(mPermissionRequiredPreference); - mPermissionRequiredPreference.setVisible(false); - mPackageManager = mContext.getPackageManager(); - mPackageName = mPackageManager.getAttentionServicePackageName(); + Preference permissionPreference = findPreference( + AdaptiveSleepPermissionPreferenceController.PREF_NAME); + if (permissionPreference != null) { + permissionPreference.setVisible(false); + } + mContext.getSharedPreferences(PREF, Context.MODE_PRIVATE) .edit() .putBoolean(PREF_KEY_INTERACTED, true) .apply(); } - @Override - public void onResume() { - super.onResume(); - if (!hasSufficientPermission(mPackageManager)) { - mPermissionRequiredPreference.setVisible(true); - } - else { - mPermissionRequiredPreference.setVisible(false); - } - } - @Override protected int getPreferenceScreenResId() { return R.xml.adaptive_sleep_detail; @@ -113,29 +93,4 @@ public class AdaptiveSleepSettings extends DashboardFragment { return Arrays.asList(sir); } }; - - private Preference createPermissionMissionPreference() { - Preference preference = new Preference(mContext, null); - preference.setIcon(R.drawable.ic_info_outline_24); - // Makes sure it's above the toggle. - preference.setOrder(1); - preference.setPersistent(true); - preference.setTitle(R.string.adaptive_sleep_title_no_permission); - preference.setSummary(R.string.adaptive_sleep_summary_no_permission); - preference.setOnPreferenceClickListener(p -> { - 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/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/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/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/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 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/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"); diff --git a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceControllerTest.java index 3d418d9da92..df599713b6e 100644 --- a/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/development/gamedriver/GameDriverEnableForAllAppsPreferenceControllerTest.java @@ -21,6 +21,7 @@ import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_U import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_ALL_APPS; import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_DEFAULT; import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_OFF; +import static com.android.settings.development.gamedriver.GameDriverEnableForAllAppsPreferenceController.GAME_DRIVER_PRERELEASE_ALL_APPS; import static com.google.common.truth.Truth.assertThat; @@ -30,10 +31,13 @@ import static org.mockito.Mockito.when; import android.content.ContentResolver; import android.content.Context; +import android.content.res.Resources; import android.provider.Settings; +import androidx.preference.ListPreference; import androidx.preference.PreferenceScreen; -import androidx.preference.SwitchPreference; + +import com.android.settings.R; import org.junit.Before; import org.junit.Test; @@ -49,13 +53,16 @@ public class GameDriverEnableForAllAppsPreferenceControllerTest { @Mock private PreferenceScreen mScreen; @Mock - private SwitchPreference mPreference; + private ListPreference mPreference; @Mock private GameDriverContentObserver mGameDriverContentObserver; private Context mContext; private ContentResolver mResolver; private GameDriverEnableForAllAppsPreferenceController mController; + private String mPreferenceDefault; + private String mPreferenceGameDriver; + private String mPreferencePrereleaseDriver; @Before public void setUp() { @@ -63,6 +70,13 @@ public class GameDriverEnableForAllAppsPreferenceControllerTest { mContext = RuntimeEnvironment.application; mResolver = mContext.getContentResolver(); + final Resources resources = mContext.getResources(); + 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); + Settings.Global.putInt(mResolver, Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 1); Settings.Global.putInt( mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); @@ -95,12 +109,13 @@ public class GameDriverEnableForAllAppsPreferenceControllerTest { } @Test - public void displayPreference_shouldAddSwitchPreference() { + public void displayPreference_shouldAddListPreference() { Settings.Global.putInt( mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); mController.updateState(mPreference); - verify(mPreference).setChecked(false); + verify(mPreference).setValue(mPreferenceDefault); + verify(mPreference).setSummary(mPreferenceDefault); } @Test @@ -120,39 +135,64 @@ public class GameDriverEnableForAllAppsPreferenceControllerTest { } @Test - public void updateState_availableAndGameDriverDefault_visibleAndUncheck() { + public void updateState_availableAndDefault_visibleAndDefault() { Settings.Global.putInt( mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); mController.updateState(mPreference); verify(mPreference, atLeastOnce()).setVisible(true); - verify(mPreference).setChecked(false); + verify(mPreference).setValue(mPreferenceDefault); + verify(mPreference).setSummary(mPreferenceDefault); } @Test - public void updateState_availableAndGameDriverAllApps_visibleAndCheck() { + public void updateState_availableAndGameDriver_visibleAndGameDriver() { Settings.Global.putInt( mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_ALL_APPS); mController.updateState(mPreference); verify(mPreference, atLeastOnce()).setVisible(true); - verify(mPreference).setChecked(true); + verify(mPreference).setValue(mPreferenceGameDriver); + verify(mPreference).setSummary(mPreferenceGameDriver); } @Test - public void updateState_gameDriverOff_notVisibleAndUncheck() { + public void updateState_availableAndPrereleaseDriver_visibleAndPrereleaseDriver() { + Settings.Global.putInt( + mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_PRERELEASE_ALL_APPS); + mController.updateState(mPreference); + + verify(mPreference, atLeastOnce()).setVisible(true); + verify(mPreference).setValue(mPreferencePrereleaseDriver); + verify(mPreference).setSummary(mPreferencePrereleaseDriver); + } + + @Test + public void updateState_gameDriverOff_notVisibleAndSystemDriver() { Settings.Global.putInt(mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_OFF); mController.updateState(mPreference); verify(mPreference).setVisible(false); - verify(mPreference).setChecked(false); + verify(mPreference).setValue(mPreferenceDefault); + verify(mPreference).setSummary(mPreferenceDefault); } @Test - public void onPreferenceChange_check_shouldUpdateSettingsGlobal() { + public void onPreferenceChange_default_shouldUpdateSettingsGlobal() { + Settings.Global.putInt( + mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_ALL_APPS); + mController.onPreferenceChange(mPreference, mPreferenceDefault); + + assertThat(Settings.Global.getInt( + mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT)) + .isEqualTo(GAME_DRIVER_DEFAULT); + } + + @Test + public void onPreferenceChange_gameDriver_shouldUpdateSettingsGlobal() { Settings.Global.putInt( mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); - mController.onPreferenceChange(mPreference, true); + mController.onPreferenceChange(mPreference, mPreferenceGameDriver); assertThat(Settings.Global.getInt( mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT)) @@ -160,13 +200,13 @@ public class GameDriverEnableForAllAppsPreferenceControllerTest { } @Test - public void onPreferenceChange_uncheck_shouldUpdateSettingsGlobal() { + public void onPreferenceChange_prereleaseDriver_shouldUpdateSettingsGlobal() { Settings.Global.putInt( - mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_ALL_APPS); - mController.onPreferenceChange(mPreference, false); + mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT); + mController.onPreferenceChange(mPreference, mPreferencePrereleaseDriver); assertThat(Settings.Global.getInt( mResolver, Settings.Global.GAME_DRIVER_ALL_APPS, GAME_DRIVER_DEFAULT)) - .isEqualTo(GAME_DRIVER_DEFAULT); + .isEqualTo(GAME_DRIVER_PRERELEASE_ALL_APPS); } } 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); } } 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/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"); 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); 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