Merge "[Catalyst] Vibration and haptics screen migration" into main
diff --git a/Android.bp b/Android.bp
index 28c3148..8f7bd1b 100644
--- a/Android.bp
+++ b/Android.bp
@@ -98,6 +98,7 @@
"SettingsLibDataStore",
"SettingsLibMetadata",
"SettingsLibPreference",
+ "SettingsLibService",
"aconfig_settings_flags_lib",
"accessibility_settings_flags_lib",
"contextualcards",
@@ -107,7 +108,6 @@
"fuelgauge-protos-lite",
"settings-logtags",
"statslog-settings",
- "telephony_flags_core_java_lib",
"setupdesign-lottie-loading-layout",
"device_policy_aconfig_flags_lib",
"keyboard_flags_lib",
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6408ab1..11d9779 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -5293,12 +5293,36 @@
android:value="com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamConfirmDialog" />
</activity>
+ <activity
+ android:name="Settings$ContactsStorageSettingsActivity"
+ android:label="@string/contacts_storage_settings_title"
+ android:exported="true"
+ android:featureFlag="com.android.settings.flags.enable_contacts_default_account_in_settings">
+ <intent-filter>
+ <action android:name="android.provider.action.SET_DEFAULT_ACCOUNT" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.applications.contacts.ContactsStorageSettings"/>
+ </activity>
+
<service
android:name="com.android.settings.connecteddevice.audiosharing.audiostreams.AudioStreamMediaService"
android:foregroundServiceType="mediaPlayback"
android:enabled="true"
android:exported="false" />
+ <!-- Once b/364771256 is fixed, add android:featureFlag="com.android.settings.flags.catalyst_service". -->
+ <!-- Permission is not yet finalized, use READ_BASIC_PHONE_STATE temporarily. -->
+ <service
+ android:name=".SettingsService"
+ android:exported="true"
+ android:permission="android.permission.READ_BASIC_PHONE_STATE">
+ <intent-filter>
+ <action android:name="com.android.settingslib.PREFERENCE_SERVICE" />
+ </intent-filter>
+ </service>
+
<receiver android:name="com.android.settings.connecteddevice.audiosharing.AudioSharingReceiver"
android:exported="false">
<intent-filter>
diff --git a/aconfig/catalyst/battery.aconfig b/aconfig/catalyst/battery.aconfig
new file mode 100644
index 0000000..ce5c5c5
--- /dev/null
+++ b/aconfig/catalyst/battery.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.settings.flags"
+container: "system"
+
+flag {
+ name: "catalyst_battery_saver_screen"
+ namespace: "android_settings"
+ description: "Flag for Battery Saver"
+ bug: "323791114"
+}
diff --git a/aconfig/catalyst/network_and_internet.aconfig b/aconfig/catalyst/network_and_internet.aconfig
new file mode 100644
index 0000000..a3e1784
--- /dev/null
+++ b/aconfig/catalyst/network_and_internet.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.settings.flags"
+container: "system"
+
+flag {
+ name: "catalyst_network_provider_and_internet_screen"
+ namespace: "android_settings"
+ description: "Flag for Network & Internet"
+ bug: "323791114"
+}
diff --git a/aconfig/settings_datetime_flag_declarations.aconfig b/aconfig/settings_datetime_flag_declarations.aconfig
index 3d9d8b3..93d41d6 100644
--- a/aconfig/settings_datetime_flag_declarations.aconfig
+++ b/aconfig/settings_datetime_flag_declarations.aconfig
@@ -9,3 +9,11 @@
bug: "283239837"
}
+flag {
+ name: "revamp_toggles"
+ # "location" is used by the Android System Time team for feature flags.
+ namespace: "location"
+ description: "Makes the use location toggle dependent on automatic time zone detection"
+ bug: "296835792"
+}
+
diff --git a/aconfig/settings_flag_declarations.aconfig b/aconfig/settings_flag_declarations.aconfig
index a9c7bd5..6eb1e02 100644
--- a/aconfig/settings_flag_declarations.aconfig
+++ b/aconfig/settings_flag_declarations.aconfig
@@ -63,3 +63,10 @@
description: "Flag for all screens"
bug: "323791114"
}
+
+flag {
+ name: "catalyst_service"
+ namespace: "android_settings"
+ description: "Flag for catalyst service"
+ bug: "323791114"
+}
diff --git a/res/drawable/accessibility_contrast_button_background.xml b/res/drawable/accessibility_contrast_button_background.xml
index 281fcef..7e41aae 100644
--- a/res/drawable/accessibility_contrast_button_background.xml
+++ b/res/drawable/accessibility_contrast_button_background.xml
@@ -32,7 +32,7 @@
<item
android:width="24dp"
android:height="24dp"
- android:left="57dp"
+ android:start="57dp"
android:top="57dp">
<vector
android:width="24dp"
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 8e5519f..ed0bce4 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1551,7 +1551,7 @@
<item>@*android:drawable/ic_zen_mode_icon_snowflake</item>
<item>@*android:drawable/ic_zen_mode_icon_beach</item>
<item>@*android:drawable/ic_zen_mode_icon_workshop</item>
- <item>@*android:drawable/ic_zen_mode_icon_camping</item>
+ <item>@*android:drawable/ic_zen_mode_icon_piano</item>
<item>@*android:drawable/ic_zen_mode_type_theater</item> <!-- Film reel -->
<item>@*android:drawable/ic_zen_mode_icon_book</item>
<!-- Wellbeing -->
@@ -1602,7 +1602,7 @@
<item>Snowflake</item>
<item>Beach umbrella</item>
<item>Workshop tools</item>
- <item>Tent</item>
+ <item>Piano</item>
<item>Film reel</item>
<item>Book</item>
<!-- Wellbeing -->
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 1f9aa61..ed293ff 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -579,7 +579,7 @@
<!-- Date & time setting screen setting switch summary: whether the time zone should be determined automatically [CHAR LIMIT=100] -->
<string name="zone_auto_title_summary">Set automatically based on mobile networks near you</string>
<!-- Date & time setting screen setting switch summary for non-telephony devices [CHAR LIMIT=100] -->
- <string name="auto_zone_requires_location_summary">Set automatically using your device location, if available. An active Wifi connection may also be required.</string>
+ <string name="auto_zone_requires_location_summary">Set automatically using your device location, if available</string>
<!-- Date & time setting screen setting option summary text for the automatic 24 hour setting checkbox [CHAR LIMIT=100] -->
<string name="date_time_24hour_auto">Use locale default</string>
<!-- Date & time setting screen setting check box title -->
@@ -4705,9 +4705,13 @@
<!-- Summary for the button to trigger the 'Physical keyboard accessibility' page. [CHAR LIMIT=NONE] -->
<string name="keyboard_a11y_settings_summary">Sticky keys, Bounce keys, Mouse keys</string>
<!-- Title for the keyboard repeat key option. [CHAR LIMIT=60] -->
- <string name="keyboard_repeat_key_title">Repeat Keys</string>
+ <string name="keyboard_repeat_keys_title">Repeat Keys</string>
+ <!-- Title for the keyboard repeat key timeout option. [CHAR LIMIT=60] -->
+ <string name="keyboard_repeat_keys_timeout_title">Delay before repeat</string>
+ <!-- Title for the keyboard repeat key delay option. [CHAR LIMIT=60] -->
+ <string name="keyboard_repeat_keys_delay_title">Repeat Rate</string>
<!-- Summary for the keyboard repeat key option. [CHAR LIMIT=NONE] -->
- <string name="keyboard_repeat_key_summary">Hold down a key to repeat its character until the key is released</string>
+ <string name="keyboard_repeat_keys_summary">Hold down a key to repeat its character until the key is released</string>
<!-- Title text for per IME subtype keyboard layout. [CHAR LIMIT=35] -->
<string name="ime_label_title"><xliff:g id="ime_label" example="Gboard">%s</xliff:g> layout</string>
@@ -13704,7 +13708,6 @@
<!-- Learn more link for audio sharing qrcode [CHAR LIMIT=none]-->
<string name="audio_streams_qr_code_help_with_link"><annotation id="link">Need help?</annotation></string>
-
<!-- url for learning more about bluetooth audio sharing -->
<string name="help_url_audio_sharing" translatable="false"></string>
@@ -13725,4 +13728,11 @@
<string name="contacts_storage_no_account_set">No default set</string>
<!-- Text for add account selection message when no account has been added [CHAR LIMIT=100] -->
<string name="contacts_storage_first_time_add_account_message">Add an account to get started</string>
+
+ <!-- Circle to Search (shared between all entrypoints) -->
+ <!-- Name of Google's new feature to circle to search anything on your phone screen,
+ without switching apps. Also used as the setting title. [CHAR LIMIT=60] -->
+ <string name="search_gesture_feature_title">Circle to Search</string>
+ <!-- Summary text for press and hold nav handle OR home button to invoke Circle to Search. [CHAR LIMIT=NONE] -->
+ <string name="search_gesture_feature_summary">Touch and hold the Home button or the navigation handle to search using the content on your screen.</string>
</resources>
diff --git a/res/xml/accessibility_system_controls.xml b/res/xml/accessibility_system_controls.xml
index 460214f..a8cb1bb 100644
--- a/res/xml/accessibility_system_controls.xml
+++ b/res/xml/accessibility_system_controls.xml
@@ -20,6 +20,9 @@
android:persistent="false"
android:title="@string/accessibility_system_controls_title">
+ <!-- The item is not specific to Accessibility.
+ The same entry is under System, which is unlikely to be removed,
+ so this is not searchable. -->
<Preference
android:fragment="com.android.settings.gestures.SystemNavigationGestureSettings"
android:key="gesture_system_navigation_input_summary_accessibility"
@@ -28,6 +31,9 @@
settings:searchable="false"
settings:controller="com.android.settings.gestures.SystemNavigationPreferenceController"/>
+ <!-- The item is not specific to Accessibility.
+ The same entry is under System > Gesture, which is unlikely to be removed,
+ so this is not searchable. -->
<Preference
android:fragment="com.android.settings.gestures.OneHandedSettings"
android:key="gesture_system_navigation_one_handed_accessibility"
@@ -43,21 +49,28 @@
settings:controller="com.android.settings.accessibility.PowerButtonEndsCallPreferenceController"/>
<!-- Standard auto-rotation preference that will be shown when device state based auto-rotation
- settings are NOT available. -->
+ settings are NOT available.
+ The item is not specific to Accessibility.
+ The same entry is under Display & touch, which is unlikely to be removed,
+ so this is not searchable.-->
<SwitchPreferenceCompat
android:key="toggle_lock_screen_rotation_preference"
android:persistent="false"
android:title="@string/accelerometer_title"
+ settings:searchable="false"
settings:controller="com.android.settings.accessibility.LockScreenRotationPreferenceController"/>
<!-- Auto-rotation preference that will be shown when device state based auto-rotation settings
- are available. -->
+ are available.
+ The item is not specific to Accessibility.
+ The same entry is under Display & touch, which is unlikely to be removed,
+ so this is not searchable. -->
<Preference
android:key="device_state_auto_rotate_accessibility"
android:persistent="false"
android:title="@string/accelerometer_title"
android:fragment="com.android.settings.display.DeviceStateAutoRotateDetailsFragment"
- settings:keywords="@string/keywords_auto_rotate"
+ settings:searchable="false"
settings:controller="com.android.settings.display.DeviceStateAutoRotateOverviewController"/>
</PreferenceScreen>
diff --git a/res/xml/button_navigation_settings.xml b/res/xml/button_navigation_settings.xml
index 1de011c..1f89539 100644
--- a/res/xml/button_navigation_settings.xml
+++ b/res/xml/button_navigation_settings.xml
@@ -28,7 +28,8 @@
settings:searchable="false"
settings:dynamicColor="true"
settings:lottie_imageAssetsFolder="button_nav_menu"
- settings:lottie_rawRes="@raw/lottie_button_nav_menu"/>
+ settings:lottie_rawRes="@raw/lottie_button_nav_menu"
+ settings:controller="com.android.settings.gestures.ButtonNavigationSettingsAssistController"/>
<SwitchPreferenceCompat
android:key="assistant_long_press_home_gesture"
diff --git a/res/xml/date_time_prefs_revamped.xml b/res/xml/date_time_prefs_revamped.xml
new file mode 100644
index 0000000..fe0fd7e
--- /dev/null
+++ b/res/xml/date_time_prefs_revamped.xml
@@ -0,0 +1,104 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2024 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.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/date_and_time"
+ settings:keywords="@string/keywords_date_and_time">
+
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="auto_time"
+ android:title="@string/date_time_auto"
+ android:summary="@string/summary_placeholder"
+ settings:userRestriction="no_config_date_time"
+ settings:controller="com.android.settings.datetime.AutoTimePreferenceController" />
+
+ <com.android.settingslib.RestrictedPreference
+ android:key="date"
+ android:title="@string/date_time_set_date_title"
+ android:summary="@string/summary_placeholder"
+ settings:userRestriction="no_config_date_time"
+ settings:controller="com.android.settings.datetime.DatePreferenceController" />
+
+ <com.android.settingslib.RestrictedPreference
+ android:key="time"
+ android:title="@string/date_time_set_time_title"
+ android:summary="@string/summary_placeholder"
+ settings:userRestriction="no_config_date_time"
+ settings:controller="com.android.settings.datetime.TimePreferenceController" />
+
+ <PreferenceCategory
+ android:key="timezone_preference_category"
+ android:title="@string/date_time_set_timezone_title">
+
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="auto_zone"
+ android:title="@string/zone_auto_title"
+ android:summary="@string/summary_placeholder"
+ settings:userRestriction="no_config_date_time"
+ settings:controller="com.android.settings.datetime.AutoTimeZonePreferenceController" />
+
+ <com.android.settingslib.widget.BannerMessagePreference
+ android:key="location_time_zone_detection_status"
+ android:title="@string/location_time_zone_detection_status_title"
+ settings:controller="com.android.settings.datetime.LocationProviderStatusPreferenceController"/>
+
+ <!-- This preference gets removed if location-based time zone detection is not supported -->
+ <SwitchPreferenceCompat
+ android:key="location_time_zone_detection"
+ android:title="@string/location_time_zone_detection_toggle_title"
+ android:summary="@string/summary_placeholder"
+ settings:controller="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceController"/>
+
+ <com.android.settingslib.RestrictedPreference
+ android:key="timezone"
+ android:title="@string/date_time_set_timezone_title"
+ android:summary="@string/summary_placeholder"
+ android:fragment="com.android.settings.datetime.timezone.TimeZoneSettings"
+ settings:userRestriction="no_config_date_time"
+ settings:keywords="@string/keywords_time_zone"
+ settings:controller="com.android.settings.datetime.TimeZonePreferenceController" />
+
+ </PreferenceCategory>
+
+ <!-- An optional preference category for feedback. Only displayed up if enabled via flags and config. -->
+ <PreferenceCategory
+ android:key="time_feedback_preference_category"
+ android:title="@string/time_feedback_category_title"
+ settings:keywords="@string/keywords_time_feedback_category"
+ settings:controller="com.android.settings.datetime.TimeFeedbackPreferenceCategoryController">
+
+ <Preference
+ android:key="time_feedback"
+ android:title="@string/time_feedback_title"
+ settings:keywords="@string/keywords_time_feedback"
+ settings:controller="com.android.settings.datetime.TimeFeedbackPreferenceController" />
+
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="time_format_preference_category"
+ android:title="@string/time_format_category_title"
+ settings:keywords="@string/keywords_time_format">
+
+ <SwitchPreferenceCompat
+ android:key="24 hour"
+ android:title="@string/date_time_24hour"
+ settings:controller="com.android.settings.datetime.TimeFormatPreferenceController" />
+ </PreferenceCategory>
+
+</PreferenceScreen>
diff --git a/res/xml/physical_keyboard_settings.xml b/res/xml/physical_keyboard_settings.xml
index 5d2c5fc..5691405 100644
--- a/res/xml/physical_keyboard_settings.xml
+++ b/res/xml/physical_keyboard_settings.xml
@@ -33,11 +33,12 @@
android:summary="@string/modifier_keys_settings_summary"
android:fragment="com.android.settings.inputmethod.ModifierKeysSettings" />
- <SwitchPreferenceCompat
- android:key="physical_keyboard_repeat_key"
- android:title="@string/keyboard_repeat_key_title"
- android:summary="@string/keyboard_repeat_key_summary"
+ <com.android.settingslib.PrimarySwitchPreference
+ android:key="physical_keyboard_repeat_keys"
+ android:title="@string/keyboard_repeat_keys_title"
+ android:summary="@string/keyboard_repeat_keys_summary"
android:defaultValue="false"
+ android:fragment="com.android.settings.inputmethod.KeyboardRepeatKeysMainFragment"
settings:controller="com.android.settings.inputmethod.KeyboardRepeatKeysController" />
<Preference
diff --git a/res/xml/repeat_key_main_page.xml b/res/xml/repeat_key_main_page.xml
new file mode 100644
index 0000000..c33eba7
--- /dev/null
+++ b/res/xml/repeat_key_main_page.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright 2024 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.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/keyboard_repeat_keys_title"
+ android:key="repeat_keys_main_page">
+
+ <com.android.settingslib.widget.MainSwitchPreference
+ android:key="repeat_keys_main_switch"
+ android:title="@string/keyboard_repeat_keys_title"
+ settings:controller="com.android.settings.inputmethod.KeyboardRepeatKeysController"/>
+ <com.android.settings.widget.LabeledSeekBarPreference
+ android:key="repeat_keys_timeout_preference"
+ android:title="@string/keyboard_repeat_keys_timeout_title"
+ android:min="0"
+ android:max="6"
+ settings:seekBarIncrement="1"
+ settings:controller= "com.android.settings.inputmethod.KeyboardRepeatKeysTimeOutPreferenceController" />
+ <com.android.settings.widget.LabeledSeekBarPreference
+ android:key="repeat_keys_delay_preference"
+ android:title="@string/keyboard_repeat_keys_delay_title"
+ android:min="0"
+ android:max="8"
+ settings:seekBarIncrement="1"
+ settings:controller= "com.android.settings.inputmethod.KeyboardRepeatKeysDelayPreferenceController" />
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/system_navigation_gesture_settings.xml b/res/xml/system_navigation_gesture_settings.xml
index a75875b..8919a40 100644
--- a/res/xml/system_navigation_gesture_settings.xml
+++ b/res/xml/system_navigation_gesture_settings.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
- Copyright (C) 2018 The Android Open Source Project
+ Copyright (C) 2024 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.
@@ -19,4 +19,15 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/system_navigation_title"
- settings:keywords="@string/keywords_system_navigation"/>
+ settings:keywords="@string/keywords_system_navigation">
+
+ <SwitchPreferenceCompat
+ android:key="search_gesture_press_hold"
+ android:title="@string/search_gesture_feature_title"
+ android:summary="@string/search_gesture_feature_summary"
+ android:order="100"
+ settings:allowDividerAbove="true"
+ settings:controller="com.android.settings.gestures.NavigationSettingsContextualSearchController"
+ settings:highlightableMenuKey="@string/menu_key_system" />
+
+</PreferenceScreen>
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index f86e29f..2178b60 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -47,7 +47,6 @@
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
-import com.android.internal.telephony.flags.Flags;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.network.ResetNetworkRestrictionViewBuilder;
@@ -142,13 +141,10 @@
Context context = getContext();
boolean resetSims = false;
- // TODO(b/317276437) Simplify the logic once flag is released
int resetOptions = ResetNetworkRequest.RESET_CONNECTIVITY_MANAGER
- | ResetNetworkRequest.RESET_VPN_MANAGER;
- if (Flags.resetMobileNetworkSettings()) {
- resetOptions |= ResetNetworkRequest.RESET_IMS_STACK;
- resetOptions |= ResetNetworkRequest.RESET_PHONE_PROCESS;
- }
+ | ResetNetworkRequest.RESET_VPN_MANAGER
+ | ResetNetworkRequest.RESET_IMS_STACK
+ | ResetNetworkRequest.RESET_PHONE_PROCESS;
ResetNetworkRequest request = new ResetNetworkRequest(resetOptions);
if (mSubscriptions != null && mSubscriptions.size() > 0) {
int selectedIndex = mSubscriptionSpinner.getSelectedItemPosition();
@@ -156,9 +152,7 @@
int subId = subscription.getSubscriptionId();
request.setResetTelephonyAndNetworkPolicyManager(subId)
.setResetApn(subId);
- if (Flags.resetMobileNetworkSettings()) {
- request.setResetImsSubId(subId);
- }
+ request.setResetImsSubId(subId);
}
if (mEsimContainer.getVisibility() == View.VISIBLE && mEsimCheckbox.isChecked()) {
resetSims = true;
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index f7110b4..b04f3af 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -514,4 +514,5 @@
public static class HearingDevicesActivity extends SettingsActivity { /* empty */ }
public static class HearingDevicesPairingActivity extends SettingsActivity { /* empty */ }
+ public static class ContactsStorageSettingsActivity extends SettingsActivity { /* empty */ }
}
diff --git a/src/com/android/settings/SettingsService.kt b/src/com/android/settings/SettingsService.kt
new file mode 100644
index 0000000..2cd706b
--- /dev/null
+++ b/src/com/android/settings/SettingsService.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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
+
+import android.content.Intent
+import android.os.IBinder
+import com.android.settings.flags.Flags
+import com.android.settingslib.service.PreferenceService
+
+/** Service to expose settings APIs. */
+class SettingsService : PreferenceService({ _, _, _ -> true }) {
+
+ override fun onBind(intent: Intent): IBinder? {
+ return if (!Flags.catalystService()) null else super.onBind(intent)
+ }
+}
diff --git a/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt b/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt
index ba6d1a6..f4992da 100644
--- a/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt
+++ b/src/com/android/settings/bluetooth/ui/model/DeviceSettingPreferenceModel.kt
@@ -44,6 +44,7 @@
val icon: DeviceSettingIcon? = null,
val checked: Boolean,
val onCheckedChange: ((Boolean) -> Unit),
+ val disabled: Boolean = false,
val action: DeviceSettingActionModel? = null,
) : DeviceSettingPreferenceModel
diff --git a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt
index 5418a04..ad4176f 100644
--- a/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt
+++ b/src/com/android/settings/bluetooth/ui/view/DeviceDetailsFragmentFormatter.kt
@@ -139,7 +139,7 @@
viewModel
.getItems(fragmentType)
?.filterIsInstance<DeviceSettingConfigItemModel.BuiltinItem.BluetoothProfilesItem>()
- ?.first()
+ ?.firstOrNull()
?.invisibleProfiles
}
@@ -306,6 +306,7 @@
override val onCheckedChange = { newChecked: Boolean ->
model.onCheckedChange(newChecked)
}
+ override val changeable = { !model.disabled }
override val icon: (@Composable () -> Unit)?
get() {
if (model.icon == null) {
diff --git a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt
index a9444a5..3b7a582 100644
--- a/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt
+++ b/src/com/android/settings/bluetooth/ui/viewmodel/BluetoothDeviceDetailsViewModel.kt
@@ -58,6 +58,8 @@
deviceSettingRepository.getDeviceSettingsConfig(cachedDevice)
}
+ private val spatialAudioModel by lazy { spatialAudioInteractor.getDeviceSetting(cachedDevice) }
+
suspend fun getItems(fragment: FragmentTypeModel): List<DeviceSettingConfigItemModel>? =
when (fragment) {
is FragmentTypeModel.DeviceDetailsMainFragment -> items.await()?.mainItems
@@ -81,7 +83,7 @@
}
return when (settingId) {
DeviceSettingId.DEVICE_SETTING_ID_SPATIAL_AUDIO_MULTI_TOGGLE ->
- spatialAudioInteractor.getDeviceSetting(cachedDevice)
+ spatialAudioModel
else -> deviceSettingRepository.getDeviceSetting(cachedDevice, settingId)
}.map { it?.toPreferenceModel() }
}
@@ -101,6 +103,7 @@
DeviceSettingStateModel.ActionSwitchPreferenceState(newState)
)
},
+ disabled = !isAllowedChangingState,
action = action,
)
} else {
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 3e92d5f..117364f 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -60,6 +60,7 @@
import com.android.settings.applications.appinfo.WriteSettingsDetails;
import com.android.settings.applications.appops.BackgroundCheckSummary;
import com.android.settings.applications.assist.ManageAssist;
+import com.android.settings.applications.contacts.ContactsStorageSettings;
import com.android.settings.applications.manageapplications.ManageApplications;
import com.android.settings.applications.managedomainurls.ManageDomainUrls;
import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminSettings;
@@ -401,7 +402,8 @@
AccessibilityHearingAidsFragment.class.getName(),
HearingDevicePairingFragment.class.getName(),
ZenModesListFragment.class.getName(),
- ZenModeFragment.class.getName()
+ ZenModeFragment.class.getName(),
+ ContactsStorageSettings.class.getName()
};
public static final String[] SETTINGS_FOR_RESTRICTED = {
diff --git a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
index 2f06289..3d8f801 100644
--- a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
@@ -32,6 +32,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.flags.Flags;
public class AutoTimeZonePreferenceController extends TogglePreferenceController {
@@ -46,7 +47,7 @@
// setTimeAndDateCallback() isn't called, e.g. for slices and other cases where the
// controller is instantiated outside of the context of the real Date & Time settings
// screen.
- mCallback = (c) -> {};
+ mCallback = (c) -> {};
}
/**
@@ -103,10 +104,25 @@
@Override
public boolean setChecked(boolean isChecked) {
- TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
- .setAutoDetectionEnabled(isChecked)
- .build();
- boolean result = mTimeManager.updateTimeZoneConfiguration(configuration);
+ TimeZoneConfiguration.Builder configuration = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(isChecked);
+
+ if (Flags.revampToggles()) {
+ // "Use location for time zone" is only used if "Automatic time zone" is enabled. If
+ // the user toggles off automatic time zone, set the toggle off and disable the toggle.
+ int geoDetectionCapability = mTimeManager
+ .getTimeZoneCapabilitiesAndConfig()
+ .getCapabilities()
+ .getConfigureGeoDetectionEnabledCapability();
+
+ if (!isChecked
+ && (geoDetectionCapability == CAPABILITY_NOT_APPLICABLE
+ || geoDetectionCapability == CAPABILITY_POSSESSED)) {
+ configuration.setGeoDetectionEnabled(false);
+ }
+ }
+
+ boolean result = mTimeManager.updateTimeZoneConfiguration(configuration.build());
mCallback.updateTimeAndDateDisplay(mContext);
return result;
@@ -138,8 +154,10 @@
@VisibleForTesting
boolean isEnabled() {
- TimeZoneConfiguration config = getTimeZoneCapabilitiesAndConfig().getConfiguration();
- return config.isAutoDetectionEnabled();
+ return mTimeManager
+ .getTimeZoneCapabilitiesAndConfig()
+ .getConfiguration()
+ .isAutoDetectionEnabled();
}
private TimeZoneCapabilitiesAndConfig getTimeZoneCapabilitiesAndConfig() {
diff --git a/src/com/android/settings/datetime/DateTimeSettings.java b/src/com/android/settings/datetime/DateTimeSettings.java
index f3c11d4..e5c13bf 100644
--- a/src/com/android/settings/datetime/DateTimeSettings.java
+++ b/src/com/android/settings/datetime/DateTimeSettings.java
@@ -23,6 +23,7 @@
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
@@ -49,6 +50,9 @@
@Override
protected int getPreferenceScreenResId() {
+ if (Flags.revampToggles()) {
+ return R.xml.date_time_prefs_revamped;
+ }
return R.xml.date_time_prefs;
}
@@ -119,5 +123,6 @@
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.date_time_prefs);
+ new BaseSearchIndexProvider(
+ Flags.revampToggles() ? R.xml.date_time_prefs_revamped : R.xml.date_time_prefs);
}
diff --git a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
index a50ce4c..52d49ac 100644
--- a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
+++ b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
@@ -32,6 +32,7 @@
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.flags.Flags;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -64,8 +65,10 @@
@Override
public boolean isChecked() {
+ // forceRefresh set to true as the location toggle may have been turned off by switching off
+ // automatic time zone
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
- getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/false);
+ getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/ Flags.revampToggles());
TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
return configuration.isGeoDetectionEnabled();
}
@@ -73,7 +76,7 @@
@Override
public boolean setChecked(boolean isChecked) {
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
- getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/false);
+ getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/ false);
boolean isLocationEnabled =
timeZoneCapabilitiesAndConfig.getCapabilities().isUseLocationEnabled();
if (isChecked && !isLocationEnabled) {
@@ -130,18 +133,31 @@
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false).getCapabilities();
int capability = timeZoneCapabilities.getConfigureGeoDetectionEnabledCapability();
- // The preference only has two states: present and not present. The preference is never
- // present but disabled.
+ // The preference can be present and enabled, present and disabled or not present.
if (capability == CAPABILITY_NOT_SUPPORTED || capability == CAPABILITY_NOT_ALLOWED) {
return UNSUPPORTED_ON_DEVICE;
} else if (capability == CAPABILITY_NOT_APPLICABLE || capability == CAPABILITY_POSSESSED) {
- return AVAILABLE;
+ if (Flags.revampToggles()) {
+ return isAutoTimeZoneEnabled() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
+ } else {
+ return AVAILABLE;
+ }
} else {
throw new IllegalStateException("Unknown capability=" + capability);
}
}
@Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ if (Flags.revampToggles()) {
+ // enable / disable the toggle based on automatic time zone being enabled or not
+ preference.setEnabled(isAutoTimeZoneEnabled());
+ }
+ }
+
+ @Override
public CharSequence getSummary() {
TimeZoneCapabilitiesAndConfig timeZoneCapabilitiesAndConfig =
getTimeZoneCapabilitiesAndConfig(/* forceRefresh= */ false);
@@ -212,4 +228,13 @@
}
return mTimeZoneCapabilitiesAndConfig;
}
+
+ /**
+ * Returns whether the user can select this preference or not, as it is a sub toggle of
+ * automatic time zone.
+ */
+ private boolean isAutoTimeZoneEnabled() {
+ return mTimeManager.getTimeZoneCapabilitiesAndConfig().getConfiguration()
+ .isAutoDetectionEnabled();
+ }
}
diff --git a/src/com/android/settings/datetime/TimeFormatPreferenceController.java b/src/com/android/settings/datetime/TimeFormatPreferenceController.java
index 19805ad..2dee76e 100644
--- a/src/com/android/settings/datetime/TimeFormatPreferenceController.java
+++ b/src/com/android/settings/datetime/TimeFormatPreferenceController.java
@@ -25,6 +25,7 @@
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.flags.Flags;
import java.util.Calendar;
import java.util.Date;
@@ -72,8 +73,10 @@
if (mIsFromSUW) {
return DISABLED_DEPENDENT_SETTING;
}
- if (AutoTimeFormatPreferenceController.isAutoTimeFormatSelection(mContext)) {
- return DISABLED_DEPENDENT_SETTING;
+ if (!Flags.revampToggles()) {
+ if (AutoTimeFormatPreferenceController.isAutoTimeFormatSelection(mContext)) {
+ return DISABLED_DEPENDENT_SETTING;
+ }
}
return AVAILABLE;
}
@@ -130,7 +133,7 @@
timeFormatPreference = Intent.EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT;
} else {
timeFormatPreference = is24Hour ? Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR
- : Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR;
+ : Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR;
}
timeChanged.putExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, timeFormatPreference);
context.sendBroadcast(timeChanged);
@@ -138,7 +141,7 @@
static void set24Hour(Context context, Boolean is24Hour) {
String value = is24Hour == null ? null :
- is24Hour ? HOURS_24 : HOURS_12;
+ is24Hour ? HOURS_24 : HOURS_12;
Settings.System.putString(context.getContentResolver(),
Settings.System.TIME_12_24, value);
}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScreen.kt b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScreen.kt
new file mode 100644
index 0000000..2226e37
--- /dev/null
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScreen.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 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.fuelgauge.batterysaver
+
+import android.content.Context
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class BatterySaverScreen : PreferenceScreenCreator {
+ override val key: String
+ get() = KEY
+
+ override val title: Int
+ get() = R.string.battery_saver
+
+ override val keywords: Int
+ get() = R.string.keywords_battery_saver
+
+ override fun isFlagEnabled(context: Context) = Flags.catalystBatterySaverScreen()
+
+ override fun fragmentClass() = BatterySaverSettings::class.java
+
+ override fun hasCompleteHierarchy() = false
+
+ override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+ companion object {
+ const val KEY = "battery_saver_screen"
+ }
+}
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
index 8e281de..8373d03 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverSettings.java
@@ -17,8 +17,11 @@
package com.android.settings.fuelgauge.batterysaver;
import android.app.settings.SettingsEnums;
+import android.content.Context;
import android.text.TextUtils;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import com.android.settings.R;
@@ -93,4 +96,10 @@
pref.setLearnMoreText(getString(R.string.battery_saver_link_a11y));
}
}
+
+ @Nullable
+ @Override
+ public String getPreferenceScreenBindingKey(@NonNull Context context) {
+ return BatterySaverScreen.KEY;
+ }
}
diff --git a/src/com/android/settings/gestures/ButtonNavigationSettingsAssistController.java b/src/com/android/settings/gestures/ButtonNavigationSettingsAssistController.java
index 4c5e28c..72f8339 100644
--- a/src/com/android/settings/gestures/ButtonNavigationSettingsAssistController.java
+++ b/src/com/android/settings/gestures/ButtonNavigationSettingsAssistController.java
@@ -16,6 +16,7 @@
package com.android.settings.gestures;
+import static android.app.contextualsearch.ContextualSearchManager.FEATURE_CONTEXTUAL_SEARCH;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON_OVERLAY;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_3BUTTON_OVERLAY;
@@ -50,6 +51,11 @@
@Override
public int getAvailabilityStatus() {
+ // Hide the existing assistant UI elements when contextual search is available.
+ if (mContext.getPackageManager().hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+
if (SystemNavigationPreferenceController.isOverlayPackageAvailable(mContext,
NAV_BAR_MODE_2BUTTON_OVERLAY)
|| SystemNavigationPreferenceController.isOverlayPackageAvailable(mContext,
diff --git a/src/com/android/settings/gestures/NavigationSettingsContextualSearchController.java b/src/com/android/settings/gestures/NavigationSettingsContextualSearchController.java
new file mode 100644
index 0000000..5938b5f
--- /dev/null
+++ b/src/com/android/settings/gestures/NavigationSettingsContextualSearchController.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import static android.app.contextualsearch.ContextualSearchManager.FEATURE_CONTEXTUAL_SEARCH;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+
+import com.android.settings.core.TogglePreferenceController;
+
+/**
+ * Configures behaviour of Contextual Search setting.
+ */
+public class NavigationSettingsContextualSearchController extends TogglePreferenceController {
+
+ public NavigationSettingsContextualSearchController(@NonNull Context context,
+ @NonNull String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public boolean isChecked() {
+ boolean onByDefault = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_searchAllEntrypointsEnabledDefault);
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED, onByDefault ? 1 : 0)
+ == 1;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED, isChecked ? 1 : 0);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (mContext.getPackageManager().hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)) {
+ return AVAILABLE;
+ }
+ return UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return false;
+ }
+
+ @Override
+ public int getSliceHighlightMenuRes() {
+ return NO_RES;
+ }
+}
diff --git a/src/com/android/settings/inputmethod/KeyboardRepeatKeysController.java b/src/com/android/settings/inputmethod/KeyboardRepeatKeysController.java
index a232098..28392be 100644
--- a/src/com/android/settings/inputmethod/KeyboardRepeatKeysController.java
+++ b/src/com/android/settings/inputmethod/KeyboardRepeatKeysController.java
@@ -25,14 +25,20 @@
import androidx.annotation.Nullable;
import androidx.lifecycle.LifecycleObserver;
import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreferenceCompat;
+
+import com.android.settingslib.PrimarySwitchPreference;
+import com.android.settingslib.widget.MainSwitchPreference;
public class KeyboardRepeatKeysController extends
InputSettingPreferenceController implements
LifecycleObserver {
+ private static final String KEY_REPEAT_KEY = "physical_keyboard_repeat_keys";
+ private static final String KEY_REPEAT_KEY_MAIN_PAGE = "repeat_key_main_switch";
@Nullable
- private SwitchPreferenceCompat mSwitchPreferenceCompat;
+ private PrimarySwitchPreference mPrimarySwitchPreference;
+ @Nullable
+ private MainSwitchPreference mMainSwitchPreference;
public KeyboardRepeatKeysController(@NonNull Context context,
@NonNull String key) {
@@ -42,7 +48,11 @@
@Override
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
- mSwitchPreferenceCompat = screen.findPreference(getPreferenceKey());
+ if (KEY_REPEAT_KEY.equals(getPreferenceKey())) {
+ mPrimarySwitchPreference = screen.findPreference(getPreferenceKey());
+ } else if (KEY_REPEAT_KEY_MAIN_PAGE.equals(getPreferenceKey())) {
+ mMainSwitchPreference = screen.findPreference(getPreferenceKey());
+ }
}
@Override
@@ -63,8 +73,10 @@
@Override
protected void onInputSettingUpdated() {
- if (mSwitchPreferenceCompat != null) {
- mSwitchPreferenceCompat.setChecked(InputSettings.isRepeatKeysEnabled(mContext));
+ if (mPrimarySwitchPreference != null) {
+ mPrimarySwitchPreference.setChecked(InputSettings.isRepeatKeysEnabled(mContext));
+ } else if (mMainSwitchPreference != null) {
+ mMainSwitchPreference.setChecked(InputSettings.isRepeatKeysEnabled(mContext));
}
}
diff --git a/src/com/android/settings/inputmethod/KeyboardRepeatKeysDelayPreferenceController.java b/src/com/android/settings/inputmethod/KeyboardRepeatKeysDelayPreferenceController.java
new file mode 100644
index 0000000..bb074fd
--- /dev/null
+++ b/src/com/android/settings/inputmethod/KeyboardRepeatKeysDelayPreferenceController.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2024 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.inputmethod;
+
+import android.content.Context;
+import android.hardware.input.InputSettings;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.core.SliderPreferenceController;
+
+import com.google.common.collect.ImmutableList;
+
+public class KeyboardRepeatKeysDelayPreferenceController extends SliderPreferenceController {
+ @VisibleForTesting
+ static final ImmutableList<Integer> REPEAT_KEY_DELAY_VALUE_LIST = ImmutableList.of(2000, 1000,
+ 500, 300, 200, 100, 50, 30, 20);
+
+ public KeyboardRepeatKeysDelayPreferenceController(@NonNull Context context,
+ @NonNull String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getSliderPosition() {
+ return REPEAT_KEY_DELAY_VALUE_LIST.indexOf(InputSettings.getRepeatKeysDelay(mContext));
+ }
+
+ @Override
+ public boolean setSliderPosition(int position) {
+ InputSettings.setRepeatKeysDelay(mContext, REPEAT_KEY_DELAY_VALUE_LIST.get(position));
+ return true;
+ }
+
+ @Override
+ public int getMax() {
+ return REPEAT_KEY_DELAY_VALUE_LIST.size() - 1;
+ }
+
+ @Override
+ public int getMin() {
+ return 0;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return InputSettings.isRepeatKeysFeatureFlagEnabled()
+ ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+}
diff --git a/src/com/android/settings/inputmethod/KeyboardRepeatKeysMainFragment.java b/src/com/android/settings/inputmethod/KeyboardRepeatKeysMainFragment.java
new file mode 100644
index 0000000..39e605d
--- /dev/null
+++ b/src/com/android/settings/inputmethod/KeyboardRepeatKeysMainFragment.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2024 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.inputmethod;
+
+import static com.android.settings.inputmethod.PhysicalKeyboardFragment.getHardKeyboards;
+
+import android.app.settings.SettingsEnums;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.hardware.input.InputManager;
+import android.hardware.input.InputSettings;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.provider.Settings;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.internal.util.Preconditions;
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.keyboard.Flags;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.LabeledSeekBarPreference;
+import com.android.settingslib.utils.ThreadUtils;
+
+import java.util.List;
+
+public class KeyboardRepeatKeysMainFragment extends DashboardFragment
+ implements InputManager.InputDeviceListener {
+ private static final String TAG = "RepeatKeysMainFragment";
+ private static final String TIME_OUT_KEY = "repeat_keys_timeout_preference";
+ private static final String DELAY_KEY = "repeat_keys_delay_preference";
+
+ private final Uri mRepeatKeyUri = Settings.Secure.getUriFor(
+ Settings.Secure.KEY_REPEAT_ENABLED);
+ private final ContentObserver mContentObserver = new ContentObserver(new Handler(true)) {
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ if (mRepeatKeyUri.equals(uri)) {
+ updatePreferencesState();
+ }
+ }
+ };
+ private InputManager mInputManager;
+ private ContentResolver mContentResolver;
+ @Nullable
+ private LabeledSeekBarPreference mRepeatTimeoutPreference;
+ @Nullable
+ private LabeledSeekBarPreference mRepeatDelayPreference;
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.PHYSICAL_KEYBOARD_A11Y;
+ }
+
+ @Override
+ public void onAttach(@NonNull Context context) {
+ super.onAttach(context);
+ mInputManager = Preconditions.checkNotNull(getActivity()
+ .getSystemService(InputManager.class));
+ mContentResolver = context.getContentResolver();
+ }
+
+ @Override
+ public void onCreatePreferences(Bundle bundle, String s) {
+ super.onCreatePreferences(bundle, s);
+ mRepeatTimeoutPreference = findPreference(TIME_OUT_KEY);
+ mRepeatDelayPreference = findPreference(DELAY_KEY);
+ updatePreferencesState();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ finishEarlyIfNeeded();
+ mInputManager.registerInputDeviceListener(this, null);
+ registerSettingsObserver();
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ mInputManager.unregisterInputDeviceListener(this);
+ unregisterSettingsObserver();
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.repeat_key_main_page;
+ }
+
+ private void updatePreferencesState() {
+ boolean isRepeatKeyEnabled = InputSettings.isRepeatKeysEnabled(getContext());
+ if (mRepeatTimeoutPreference != null && mRepeatDelayPreference != null) {
+ mRepeatTimeoutPreference.setEnabled(isRepeatKeyEnabled);
+ mRepeatDelayPreference.setEnabled(isRepeatKeyEnabled);
+ }
+ }
+
+ private void registerSettingsObserver() {
+ unregisterSettingsObserver();
+ mContentResolver.registerContentObserver(
+ mRepeatKeyUri,
+ false,
+ mContentObserver,
+ UserHandle.myUserId());
+ }
+
+ private void unregisterSettingsObserver() {
+ mContentResolver.unregisterContentObserver(mContentObserver);
+ }
+
+ @Override
+ public void onInputDeviceAdded(int deviceId) {
+ finishEarlyIfNeeded();
+ }
+
+ @Override
+ public void onInputDeviceRemoved(int deviceId) {
+ finishEarlyIfNeeded();
+ }
+
+ @Override
+ public void onInputDeviceChanged(int deviceId) {
+ finishEarlyIfNeeded();
+ }
+
+ private void finishEarlyIfNeeded() {
+ final Context context = getContext();
+ ThreadUtils.postOnBackgroundThread(() -> {
+ final List<PhysicalKeyboardFragment.HardKeyboardDeviceInfo> newHardKeyboards =
+ getHardKeyboards(context);
+ if (newHardKeyboards.isEmpty()) {
+ getActivity().finish();
+ }
+ });
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.repeat_key_main_page) {
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ return Flags.keyboardAndTouchpadA11yNewPageEnabled()
+ && !getHardKeyboards(context).isEmpty();
+ }
+ };
+}
diff --git a/src/com/android/settings/inputmethod/KeyboardRepeatKeysTimeOutPreferenceController.java b/src/com/android/settings/inputmethod/KeyboardRepeatKeysTimeOutPreferenceController.java
new file mode 100644
index 0000000..e766d48
--- /dev/null
+++ b/src/com/android/settings/inputmethod/KeyboardRepeatKeysTimeOutPreferenceController.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2024 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.inputmethod;
+
+import android.content.Context;
+import android.hardware.input.InputSettings;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.core.SliderPreferenceController;
+
+import com.google.common.collect.ImmutableList;
+
+public class KeyboardRepeatKeysTimeOutPreferenceController extends SliderPreferenceController {
+ @VisibleForTesting
+ static final ImmutableList<Integer> REPEAT_KEY_TIMEOUT_VALUE_LIST = ImmutableList.of(2000, 1500,
+ 1000, 400, 300, 200, 150);
+
+ public KeyboardRepeatKeysTimeOutPreferenceController(
+ @NonNull Context context,
+ @NonNull String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getSliderPosition() {
+ return REPEAT_KEY_TIMEOUT_VALUE_LIST.indexOf(InputSettings.getRepeatKeysTimeout(mContext));
+ }
+
+ @Override
+ public boolean setSliderPosition(int position) {
+ InputSettings.setRepeatKeysTimeout(mContext, REPEAT_KEY_TIMEOUT_VALUE_LIST.get(position));
+ return true;
+ }
+
+ @Override
+ public int getMax() {
+ return REPEAT_KEY_TIMEOUT_VALUE_LIST.size() - 1;
+ }
+
+ @Override
+ public int getMin() {
+ return 0;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return InputSettings.isRepeatKeysFeatureFlagEnabled()
+ ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ }
+}
diff --git a/src/com/android/settings/network/NetworkDashboardFragment.java b/src/com/android/settings/network/NetworkDashboardFragment.java
index ee7d440..3ba3dc6 100644
--- a/src/com/android/settings/network/NetworkDashboardFragment.java
+++ b/src/com/android/settings/network/NetworkDashboardFragment.java
@@ -19,6 +19,7 @@
import android.content.Context;
import android.content.Intent;
+import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.android.settings.R;
@@ -115,4 +116,10 @@
return buildPreferenceControllers(context, null /* lifecycle */);
}
};
+
+ @Nullable
+ @Override
+ public String getPreferenceScreenBindingKey(@NonNull Context context) {
+ return NetworkDashboardScreen.KEY;
+ }
}
diff --git a/src/com/android/settings/network/NetworkDashboardScreen.kt b/src/com/android/settings/network/NetworkDashboardScreen.kt
new file mode 100644
index 0000000..dcdc37f
--- /dev/null
+++ b/src/com/android/settings/network/NetworkDashboardScreen.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2024 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.network
+
+import android.content.Context
+import com.android.settings.R
+import com.android.settings.flags.Flags
+import com.android.settingslib.metadata.ProvidePreferenceScreen
+import com.android.settingslib.metadata.preferenceHierarchy
+import com.android.settingslib.preference.PreferenceScreenCreator
+
+@ProvidePreferenceScreen
+class NetworkDashboardScreen : PreferenceScreenCreator {
+ override val key: String
+ get() = KEY
+
+ override val title: Int
+ get() = R.string.network_dashboard_title
+
+ override val icon: Int
+ get() = R.drawable.ic_settings_wireless_filled
+
+ override fun isFlagEnabled(context: Context) = Flags.catalystNetworkProviderAndInternetScreen()
+
+ override fun hasCompleteHierarchy() = false
+
+ override fun fragmentClass() = NetworkDashboardFragment::class.java
+
+ override fun getPreferenceHierarchy(context: Context) = preferenceHierarchy(this) {}
+
+ companion object {
+ const val KEY = "network_provider_and_internet_screen"
+ }
+}
diff --git a/tests/robotests/Android.bp b/tests/robotests/Android.bp
index 84c84b0..1cac363 100644
--- a/tests/robotests/Android.bp
+++ b/tests/robotests/Android.bp
@@ -109,7 +109,10 @@
java_library {
name: "Settings-robo-testutils",
- srcs: ["testutils/**/*.java"],
+ srcs: [
+ "testutils/**/*.java",
+ "testutils/**/*.kt",
+ ],
libs: [
"Robolectric_all-target_upstream",
"Settings-core",
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index 8f983de..df2ab45 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -63,12 +63,14 @@
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.SystemProperty;
import com.android.settings.widget.RingProgressBar;
import com.airbnb.lottie.LottieAnimationView;
import com.airbnb.lottie.LottieTask;
import com.google.android.setupdesign.GlifLayout;
+import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
@@ -111,15 +113,23 @@
private final int[] mSfpsStageThresholds = new int[]{0, 9, 13, 19, 25};
private final int[] mUdfpsStageThresholds = new int[]{0, 13, 17, 22};
+ private final SystemProperty mSystemProperty = new SystemProperty();
+
private FingerprintEnrollEnrolling mActivity;
private Context mContext;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ mSystemProperty.override("robolectric.createActivityContexts", "true");
FakeFeatureFactory.setupForTest();
}
+ @After
+ public void tearDown() {
+ mSystemProperty.close();
+ }
+
@Test
public void fingerprintUdfpsEnrollSuccessProgress_shouldNotVibrate() {
initializeActivityFor(TYPE_UDFPS_OPTICAL);
@@ -645,7 +655,6 @@
}
private void createActivity() {
- System.setProperty("robolectric.createActivityContexts", "true");
final Bundle savedInstanceState = new Bundle();
savedInstanceState.putInt(KEY_STATE_PREVIOUS_ROTATION, Surface.ROTATION_90);
diff --git a/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java
index 651915b..7bf8d52 100644
--- a/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java
@@ -40,12 +40,17 @@
import android.app.time.TimeZoneDetectorStatus;
import android.content.Context;
import android.os.UserHandle;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.preference.Preference;
import com.android.settings.R;
+import com.android.settings.flags.Flags;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -57,6 +62,9 @@
@RunWith(RobolectricTestRunner.class)
public class AutoTimeZonePreferenceControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Mock
private UpdateTimeAndDateCallback mCallback;
private Context mContext;
@@ -238,8 +246,53 @@
mContext.getString(R.string.auto_zone_requires_location_summary));
}
+ @Test
+ @EnableFlags({Flags.FLAG_REVAMP_TOGGLES})
+ public void toggleOff_revampFlagOn_shouldToggleOffUseLocation() {
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(
+ /* autoSupported= */ true,
+ /* autoEnabled= */ true,
+ /* telephonySupported= */ true,
+ /* locationSupported= */ true);
+ when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
+
+ mController.setChecked(false);
+
+ TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(false)
+ .setGeoDetectionEnabled(false)
+ .build();
+
+ verify(mTimeManager).updateTimeZoneConfiguration(configuration);
+ }
+
+ @Test
+ @DisableFlags({Flags.FLAG_REVAMP_TOGGLES})
+ public void toggleOff_revampFlagOff_shouldToggleOffUseLocation() {
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(
+ /* autoSupported= */ true,
+ /* autoEnabled= */ true,
+ /* telephonySupported= */ true,
+ /* locationSupported= */ true);
+ when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
+
+ mController.setChecked(false);
+
+ TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
+ .setAutoDetectionEnabled(false)
+ .build();
+
+ verify(mTimeManager).updateTimeZoneConfiguration(configuration);
+ }
+
private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig(
boolean autoSupported, boolean autoEnabled, boolean telephonySupported) {
+ return createCapabilitiesAndConfig(autoSupported, autoEnabled, telephonySupported, false);
+ }
+
+ private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig(
+ boolean autoSupported, boolean autoEnabled, boolean telephonySupported,
+ boolean locationSupported) {
TimeZoneDetectorStatus status = new TimeZoneDetectorStatus(DETECTOR_STATUS_RUNNING,
new TelephonyTimeZoneAlgorithmStatus(
telephonySupported ? DETECTION_ALGORITHM_STATUS_RUNNING
@@ -253,12 +306,14 @@
TimeZoneCapabilities capabilities = new TimeZoneCapabilities.Builder(UserHandle.SYSTEM)
.setConfigureAutoDetectionEnabledCapability(configureAutoDetectionEnabledCapability)
.setUseLocationEnabled(true)
- .setConfigureGeoDetectionEnabledCapability(Capabilities.CAPABILITY_NOT_SUPPORTED)
+ .setConfigureGeoDetectionEnabledCapability(
+ locationSupported ? Capabilities.CAPABILITY_POSSESSED
+ : Capabilities.CAPABILITY_NOT_SUPPORTED)
.setSetManualTimeZoneCapability(Capabilities.CAPABILITY_POSSESSED)
.build();
TimeZoneConfiguration config = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(autoEnabled)
- .setGeoDetectionEnabled(false)
+ .setGeoDetectionEnabled(locationSupported)
.build();
return new TimeZoneCapabilitiesAndConfig(status, capabilities, config);
}
diff --git a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
index cd89c0c..40794d2 100644
--- a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
@@ -25,6 +25,8 @@
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_PRESENT;
import static android.app.time.LocationTimeZoneAlgorithmStatus.PROVIDER_STATUS_NOT_READY;
+import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -43,11 +45,17 @@
import android.app.time.TimeZoneDetectorStatus;
import android.content.Context;
import android.os.UserHandle;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
+import com.android.settings.flags.Flags;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -62,9 +70,14 @@
com.android.settings.testutils.shadow.ShadowFragment.class,
})
public class LocationTimeZoneDetectionPreferenceControllerTest {
+
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Mock
private TimeManager mTimeManager;
private Context mContext;
+ private SwitchPreference mPreference;
private LocationTimeZoneDetectionPreferenceController mController;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private InstrumentedPreferenceFragment mFragment;
@@ -76,6 +89,9 @@
when(mContext.getSystemService(TimeManager.class)).thenReturn(mTimeManager);
mController = new LocationTimeZoneDetectionPreferenceController(mContext);
mController.setFragment(mFragment);
+
+ mPreference = new SwitchPreference(mContext);
+ mPreference.setKey("location_time_zone_detection");
}
@Test
@@ -115,6 +131,17 @@
}
@Test
+ @EnableFlags({Flags.FLAG_REVAMP_TOGGLES})
+ public void flagRevampTogglesOn_toggleOff_automaticTimeZone_disablesLocationToggle() {
+ TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
+ createTimeZoneCapabilitiesAndConfig(/* useLocationEnabled= */ true,
+ CAPABILITY_POSSESSED, /* setAutoDetectionEnabled= */ false);
+ when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
public void setChecked_withFalse_shouldUpdateSetting() {
boolean useLocationEnabled = false;
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
@@ -181,7 +208,14 @@
private static TimeZoneCapabilitiesAndConfig createTimeZoneCapabilitiesAndConfig(
boolean useLocationEnabled,
@CapabilityState int configureGeoDetectionEnabledCapability) {
+ return createTimeZoneCapabilitiesAndConfig(useLocationEnabled,
+ configureGeoDetectionEnabledCapability, /* setAutoDetectionEnabled= */ true);
+ }
+ private static TimeZoneCapabilitiesAndConfig createTimeZoneCapabilitiesAndConfig(
+ boolean useLocationEnabled,
+ @CapabilityState int configureGeoDetectionEnabledCapability,
+ boolean setAutoDetectionEnabled) {
// Create a status that matches the user's capability state.
LocationTimeZoneAlgorithmStatus locationAlgorithmStatus;
switch (configureGeoDetectionEnabledCapability) {
@@ -213,7 +247,7 @@
.build();
TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
- .setAutoDetectionEnabled(true)
+ .setAutoDetectionEnabled(setAutoDetectionEnabled)
.setGeoDetectionEnabled(true)
.build();
diff --git a/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java
index e1ea8f9..c5aac84 100644
--- a/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java
@@ -23,11 +23,16 @@
import android.content.Context;
import android.content.Intent;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
+import com.android.settings.flags.Flags;
+
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -41,6 +46,9 @@
@RunWith(RobolectricTestRunner.class)
public class TimeFormatPreferenceControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Mock
private UpdateTimeAndDateCallback mCallback;
@@ -97,6 +105,7 @@
}
@Test
+ @DisableFlags({Flags.FLAG_REVAMP_TOGGLES})
public void updateState_autoSet_shouldNotEnablePreference() {
Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24, null);
diff --git a/tests/robotests/src/com/android/settings/display/DisplayScreenTest.kt b/tests/robotests/src/com/android/settings/display/DisplayScreenTest.kt
index d869b84..61c3b19 100644
--- a/tests/robotests/src/com/android/settings/display/DisplayScreenTest.kt
+++ b/tests/robotests/src/com/android/settings/display/DisplayScreenTest.kt
@@ -21,6 +21,7 @@
import com.android.internal.widget.LockPatternUtils
import com.android.settings.flags.Flags
import com.android.settings.testutils.FakeFeatureFactory
+import com.android.settings.testutils.SystemProperty
import com.android.settingslib.preference.CatalystScreenTestCase
import com.google.common.truth.Truth.assertThat
import org.junit.Test
@@ -67,13 +68,14 @@
override fun migration() {
// avoid UnsupportedOperationException when getDisplay from context
- System.setProperty("robolectric.createActivityContexts", "true")
+ SystemProperty("robolectric.createActivityContexts", "true").use {
+ val lockPatternUtils =
+ mock<LockPatternUtils> { on { isSecure(anyInt()) } doReturn true }
+ FakeFeatureFactory.setupForTest().securityFeatureProvider.stub {
+ on { getLockPatternUtils(any()) } doReturn lockPatternUtils
+ }
- val lockPatternUtils = mock<LockPatternUtils> { on { isSecure(anyInt()) } doReturn true }
- FakeFeatureFactory.setupForTest().securityFeatureProvider.stub {
- on { getLockPatternUtils(any()) } doReturn lockPatternUtils
+ super.migration()
}
-
- super.migration()
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScreenTest.kt b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScreenTest.kt
new file mode 100644
index 0000000..a034e52
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScreenTest.kt
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2024 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.fuelgauge.batterysaver
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class BatterySaverScreenTest : CatalystScreenTestCase() {
+
+ override val preferenceScreenCreator = BatterySaverScreen()
+
+ override val flagName: String
+ get() = Flags.FLAG_CATALYST_BATTERY_SAVER_SCREEN
+
+ @Test
+ fun key() {
+ assertThat(preferenceScreenCreator.key).isEqualTo(BatterySaverScreen.KEY)
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsAssistControllerTest.java b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsAssistControllerTest.java
index d961cdf..493fb01 100644
--- a/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsAssistControllerTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/ButtonNavigationSettingsAssistControllerTest.java
@@ -16,6 +16,8 @@
package com.android.settings.gestures;
+import static android.app.contextualsearch.ContextualSearchManager.FEATURE_CONTEXTUAL_SEARCH;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.mock;
@@ -23,6 +25,7 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.provider.Settings;
@@ -40,13 +43,16 @@
"assistant_long_press_home_gesture";
private Context mContext;
+ private PackageManager mPackageManager;
private Resources mResources;
private ButtonNavigationSettingsAssistController mController;
@Before
public void setUp() {
mContext = spy(ApplicationProvider.getApplicationContext());
+ mPackageManager = mock(PackageManager.class);
mResources = mock(Resources.class);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
when(mContext.getResources()).thenReturn(mResources);
mController = new ButtonNavigationSettingsAssistController(
@@ -97,4 +103,23 @@
Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, -1)).isEqualTo(1);
}
+ @Test
+ public void onPreferenceChange_preferenceChecked_valueTrue() {
+ mController.onPreferenceChange(null, true);
+ assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, -1)).isEqualTo(1);
+ }
+
+ @Test
+ public void onPreferenceChange_preferenceUnchecked_valueFalse() {
+ mController.onPreferenceChange(null, false);
+ assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, -1)).isEqualTo(0);
+ }
+
+ @Test
+ public void isAvailable_hasContextualSearchSystemFeature_shouldReturnFalse() {
+ when(mPackageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)).thenReturn(true);
+ assertThat(mController.isAvailable()).isFalse();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/gestures/NavigationSettingsContextualSearchControllerTest.java b/tests/robotests/src/com/android/settings/gestures/NavigationSettingsContextualSearchControllerTest.java
new file mode 100644
index 0000000..a4744db
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/gestures/NavigationSettingsContextualSearchControllerTest.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.gestures;
+
+import static android.app.contextualsearch.ContextualSearchManager.FEATURE_CONTEXTUAL_SEARCH;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.provider.Settings;
+
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.testutils.shadow.ShadowDeviceConfig;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = ShadowDeviceConfig.class)
+public class NavigationSettingsContextualSearchControllerTest {
+
+ private static final String KEY_PRESS_HOLD_FOR_SEARCH = "search_gesture_press_hold";
+
+ private NavigationSettingsContextualSearchController mController;
+ private Context mContext;
+ private PackageManager mPackageManager;
+
+ @Before
+ public void setUp() {
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mPackageManager = mock(PackageManager.class);
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ mController = new NavigationSettingsContextualSearchController(
+ mContext, KEY_PRESS_HOLD_FOR_SEARCH);
+ }
+
+ @Test
+ public void isAvailable_hasContextualSearchSystemFeature_shouldReturnTrue() {
+ when(mPackageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)).thenReturn(true);
+ assertThat(mController.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_doesNotHaveContextualSearchSystemFeature_shouldReturnFalse() {
+ when(mPackageManager.hasSystemFeature(FEATURE_CONTEXTUAL_SEARCH)).thenReturn(false);
+ assertThat(mController.isAvailable()).isFalse();
+ }
+
+ @Test
+ public void isChecked_noDefault_true() {
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void isChecked_valueFalse_shouldReturnFalse() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED, 0);
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_valueTrue_shouldReturnTrue() {
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED, 1);
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void onPreferenceChange_preferenceChecked_valueTrue() {
+ mController.onPreferenceChange(null, true);
+ assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED, -1)).isEqualTo(1);
+ }
+
+ @Test
+ public void onPreferenceChange_preferenceUnchecked_valueFalse() {
+ mController.onPreferenceChange(null, false);
+ assertThat(Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.SEARCH_ALL_ENTRYPOINTS_ENABLED, -1)).isEqualTo(0);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysControllerTest.java
index e1b4ffd..d511edc 100644
--- a/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysControllerTest.java
+++ b/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysControllerTest.java
@@ -51,7 +51,7 @@
public void setUp() {
mContext = RuntimeEnvironment.application;
mKeyboardRepeatKeysController = new KeyboardRepeatKeysController(mContext,
- "physical_keyboard_repeat_key");
+ "physical_keyboard_repeat_keys");
}
@Test
diff --git a/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysDelayPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysDelayPreferenceControllerTest.java
new file mode 100644
index 0000000..0f2deac
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysDelayPreferenceControllerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2024 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.inputmethod;
+
+import static com.android.input.flags.Flags.FLAG_KEYBOARD_REPEAT_KEYS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.hardware.input.InputSettings;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+ com.android.settings.testutils.shadow.ShadowFragment.class,
+})
+public class KeyboardRepeatKeysDelayPreferenceControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ private Context mContext;
+ private KeyboardRepeatKeysDelayPreferenceController mRepeatKeysDelayPreferenceController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mRepeatKeysDelayPreferenceController = new KeyboardRepeatKeysDelayPreferenceController(
+ mContext, "repeat_keys_delay_preference");
+ }
+
+ @Test
+ @EnableFlags(FLAG_KEYBOARD_REPEAT_KEYS)
+ public void getAvailabilityStatus_flagIsEnabled_isAvailable() {
+ assertThat(mRepeatKeysDelayPreferenceController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ @DisableFlags(FLAG_KEYBOARD_REPEAT_KEYS)
+ public void getAvailabilityStatus_flagIsDisabled_notSupport() {
+ assertThat(mRepeatKeysDelayPreferenceController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void setSliderPosition_updatesInputSettingValue() {
+ int sliderPosition = 1;
+ mRepeatKeysDelayPreferenceController.setSliderPosition(sliderPosition);
+ assertThat(InputSettings.getRepeatKeysDelay(mContext)).isEqualTo(
+ KeyboardRepeatKeysDelayPreferenceController.REPEAT_KEY_DELAY_VALUE_LIST.get(
+ sliderPosition));
+ }
+
+ @Test
+ public void getSliderPosition_matchesWithDelayValue() {
+ int timeout = InputSettings.getRepeatKeysDelay(mContext);
+ assertThat(mRepeatKeysDelayPreferenceController.getSliderPosition()).isEqualTo(
+ KeyboardRepeatKeysDelayPreferenceController.REPEAT_KEY_DELAY_VALUE_LIST.indexOf(
+ timeout));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysTimeOutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysTimeOutPreferenceControllerTest.java
new file mode 100644
index 0000000..f192c0c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/inputmethod/KeyboardRepeatKeysTimeOutPreferenceControllerTest.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright 2024 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.inputmethod;
+
+import static com.android.input.flags.Flags.FLAG_KEYBOARD_REPEAT_KEYS;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.hardware.input.InputSettings;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import com.android.settings.core.BasePreferenceController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {
+ com.android.settings.testutils.shadow.ShadowFragment.class,
+})
+public class KeyboardRepeatKeysTimeOutPreferenceControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+ private Context mContext;
+ private KeyboardRepeatKeysTimeOutPreferenceController
+ mKeyboardRepeatKeysTimeOutPreferenceController;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mKeyboardRepeatKeysTimeOutPreferenceController =
+ new KeyboardRepeatKeysTimeOutPreferenceController(mContext,
+ "repeat_keys_timeout_preference");
+ }
+
+ @Test
+ @EnableFlags(FLAG_KEYBOARD_REPEAT_KEYS)
+ public void getAvailabilityStatus_flagIsEnabled_isAvailable() {
+ assertThat(mKeyboardRepeatKeysTimeOutPreferenceController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.AVAILABLE);
+ }
+
+ @Test
+ @DisableFlags(FLAG_KEYBOARD_REPEAT_KEYS)
+ public void getAvailabilityStatus_flagIsDisabled_notSupport() {
+ assertThat(mKeyboardRepeatKeysTimeOutPreferenceController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
+ public void setSliderPosition_updatesInputSettingValue() {
+ int sliderPosition = 1;
+ mKeyboardRepeatKeysTimeOutPreferenceController.setSliderPosition(sliderPosition);
+ assertThat(InputSettings.getRepeatKeysTimeout(mContext)).isEqualTo(
+ KeyboardRepeatKeysTimeOutPreferenceController.REPEAT_KEY_TIMEOUT_VALUE_LIST.get(
+ sliderPosition));
+ }
+
+ @Test
+ public void getSliderPosition_matchesWithTimeoutValue() {
+ int timeout = InputSettings.getRepeatKeysTimeout(mContext);
+ assertThat(mKeyboardRepeatKeysTimeOutPreferenceController.getSliderPosition()).isEqualTo(
+ KeyboardRepeatKeysTimeOutPreferenceController.REPEAT_KEY_TIMEOUT_VALUE_LIST.indexOf(
+ timeout));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/network/NetworkDashboardScreenTest.kt b/tests/robotests/src/com/android/settings/network/NetworkDashboardScreenTest.kt
new file mode 100644
index 0000000..bb80f19
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/network/NetworkDashboardScreenTest.kt
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2024 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.network
+
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.flags.Flags
+import com.android.settingslib.preference.CatalystScreenTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@RunWith(AndroidJUnit4::class)
+class NetworkDashboardScreenTest : CatalystScreenTestCase() {
+ override val preferenceScreenCreator = NetworkDashboardScreen()
+
+ override val flagName: String
+ get() = Flags.FLAG_CATALYST_NETWORK_PROVIDER_AND_INTERNET_SCREEN
+
+ @Test
+ fun key() {
+ assertThat(preferenceScreenCreator.key).isEqualTo(NetworkDashboardScreen.KEY)
+ }
+
+ override fun migration() {
+ }
+}
diff --git a/tests/robotests/testutils/com/android/settings/testutils/SystemProperty.kt b/tests/robotests/testutils/com/android/settings/testutils/SystemProperty.kt
new file mode 100644
index 0000000..9c2574e
--- /dev/null
+++ b/tests/robotests/testutils/com/android/settings/testutils/SystemProperty.kt
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2024 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.testutils
+
+/**
+ * Helper class to override system properties.
+ *
+ * [System.setProperty] changes the static state in the JVM, which is shared by all tests. Hence,
+ * there is chance that test cases are dependent/interfered due to system property unexpectedly.
+ * This helper class backs up the old properties when invoking [override] and restore the old
+ * properties in [close] to avoid flaky testing.
+ */
+class SystemProperty(overrides: Map<String, String?> = mapOf()) : AutoCloseable {
+ private val oldProperties = mutableMapOf<String, String?>()
+
+ constructor(key: String, value: String?) : this(mapOf(key to value))
+
+ init {
+ override(overrides)
+ }
+
+ fun override(key: String, value: String?) = override(mapOf(key to value))
+
+ fun override(overrides: Map<String, String?>) {
+ // back up system properties for the overrides
+ for (key in overrides.keys) {
+ // only back up the oldest property
+ if (!oldProperties.containsKey(key)) {
+ oldProperties[key] = System.getProperty(key)
+ }
+ }
+ overrides.overrideProperties()
+ }
+
+ override fun close() {
+ // restore the backed up properties
+ oldProperties.overrideProperties()
+ oldProperties.clear()
+ }
+
+ private fun Map<String, String?>.overrideProperties() {
+ for ((key, value) in this) {
+ if (value != null) {
+ System.setProperty(key, value)
+ } else {
+ System.clearProperty(key)
+ }
+ }
+ }
+}
diff --git a/tests/spa_unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.kt b/tests/spa_unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.kt
new file mode 100644
index 0000000..8524ef4
--- /dev/null
+++ b/tests/spa_unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2024 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.deviceinfo
+
+import android.content.Context
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import androidx.preference.Preference
+import androidx.preference.PreferenceCategory
+import androidx.preference.PreferenceManager
+import androidx.test.core.app.ApplicationProvider
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import com.android.settings.R
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.kotlin.any
+import org.mockito.kotlin.doReturn
+import org.mockito.kotlin.mock
+import org.mockito.kotlin.spy
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+class PhoneNumberPreferenceControllerTest {
+
+ private val mockTelephonyManager = mock<TelephonyManager>()
+ private val mockSubscriptionManager = mock<SubscriptionManager>()
+
+ private val context: Context =
+ spy(ApplicationProvider.getApplicationContext()) {
+ on { getSystemService(SubscriptionManager::class.java) } doReturn
+ mockSubscriptionManager
+
+ on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
+ }
+
+ private val subscriptionInfo = mock<SubscriptionInfo>()
+ private val preference = spy(Preference(context))
+ private val secondPreference = mock<Preference>()
+ private var category = PreferenceCategory(context)
+ private var preferenceScreen = PreferenceManager(context).createPreferenceScreen(context)
+
+ private var controller = spy(PhoneNumberPreferenceController(context, "phone_number"))
+
+ @Before
+ fun setup() {
+ preference.setKey(controller.preferenceKey)
+ preference.isVisible = true
+ preferenceScreen.addPreference(preference)
+ category.key = "basic_info_category"
+ preferenceScreen.addPreference(category)
+
+ doReturn(secondPreference).whenever(controller).createNewPreference(context)
+ }
+
+ @Test
+ fun displayPreference_multiSim_shouldAddSecondPreference() {
+ whenever(mockTelephonyManager.phoneCount).thenReturn(2)
+
+ val sim1Preference = Preference(context)
+ category.addItemFromInflater(sim1Preference)
+ controller.displayPreference(preferenceScreen)
+
+ assertThat(category.preferenceCount).isEqualTo(2)
+ }
+
+ @Test
+ fun updateState_singleSim_shouldUpdateTitleAndPhoneNumber() {
+ val phoneNumber = "1111111111"
+ doReturn(subscriptionInfo).whenever(controller).getSubscriptionInfo(any())
+ doReturn(phoneNumber).whenever(controller).getFormattedPhoneNumber(subscriptionInfo)
+ whenever(mockTelephonyManager.phoneCount).thenReturn(1)
+ controller.displayPreference(preferenceScreen)
+
+ controller.updateState(preference)
+
+ verify(preference).title = context.getString(R.string.status_number)
+ verify(preference).summary = phoneNumber
+ }
+
+ @Test
+ fun updateState_multiSim_shouldUpdateTitleAndPhoneNumberOfMultiplePreferences() {
+ val phoneNumber = "1111111111"
+ doReturn(subscriptionInfo).whenever(controller).getSubscriptionInfo(any())
+ doReturn(phoneNumber).whenever(controller).getFormattedPhoneNumber(subscriptionInfo)
+ whenever(mockTelephonyManager.phoneCount).thenReturn(2)
+ controller.displayPreference(preferenceScreen)
+
+ controller.updateState(preference)
+
+ verify(preference).title =
+ context.getString(R.string.status_number_sim_slot, 1 /* sim slot */)
+ verify(preference).summary = phoneNumber
+ verify(secondPreference).title =
+ context.getString(R.string.status_number_sim_slot, 2 /* sim slot */)
+ verify(secondPreference).summary = phoneNumber
+ }
+
+ @Test
+ fun getSummary_cannotGetActiveSubscriptionInfo_shouldShowNotAvailable() {
+ whenever(mockSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null)
+ controller.displayPreference(preferenceScreen)
+
+ controller.updateState(preference)
+
+ verify(preference).summary = context.getString(R.string.device_info_not_available)
+ }
+
+ @Test
+ fun getSummary_getEmptySubscriptionInfo_shouldShowNotAvailable() {
+ whenever(mockSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(emptyList())
+ controller.displayPreference(preferenceScreen)
+
+ controller.updateState(preference)
+
+ verify(preference).summary = context.getString(R.string.device_info_not_available)
+ }
+}
diff --git a/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
deleted file mode 100644
index 05e2f24..0000000
--- a/tests/unit/src/com/android/settings/deviceinfo/PhoneNumberPreferenceControllerTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * Copyright (C) 2017 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.deviceinfo;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.R;
-import com.android.settings.testutils.ResourcesUtils;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-import java.util.ArrayList;
-import java.util.List;
-
-@RunWith(AndroidJUnit4.class)
-public class PhoneNumberPreferenceControllerTest {
-
- private Preference mPreference;
- @Mock
- private Preference mSecondPreference;
- @Mock
- private TelephonyManager mTelephonyManager;
- @Mock
- private SubscriptionInfo mSubscriptionInfo;
- @Mock
- private SubscriptionManager mSubscriptionManager;
- private PreferenceCategory mCategory;
- private PreferenceScreen mScreen;
-
- private Context mContext;
- private PhoneNumberPreferenceController mController;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- mContext = spy(ApplicationProvider.getApplicationContext());
- when(mContext.getSystemService(SubscriptionManager.class)).thenReturn(mSubscriptionManager);
- when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
- mController = spy(new PhoneNumberPreferenceController(mContext, "phone_number"));
-
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
- final PreferenceManager preferenceManager = new PreferenceManager(mContext);
- mScreen = preferenceManager.createPreferenceScreen(mContext);
- mPreference = spy(new Preference(mContext));
- mPreference.setKey(mController.getPreferenceKey());
- mPreference.setVisible(true);
- mScreen.addPreference(mPreference);
- final String categoryKey = "basic_info_category";
- mCategory = new PreferenceCategory(mContext);
- mCategory.setKey(categoryKey);
- mScreen.addPreference(mCategory);
-
- doReturn(mSecondPreference).when(mController).createNewPreference(mContext);
- }
-
- @Test
- public void displayPreference_multiSim_shouldAddSecondPreference() {
- when(mTelephonyManager.getPhoneCount()).thenReturn(2);
-
- final Preference sim1Preference = new Preference(mContext);
- mCategory.addItemFromInflater(sim1Preference);
- mController.displayPreference(mScreen);
-
- assertThat(mCategory.getPreferenceCount()).isEqualTo(2);
- }
-
- @Test
- public void updateState_singleSim_shouldUpdateTitleAndPhoneNumber() {
- final String phoneNumber = "1111111111";
- doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(anyInt());
- doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
- when(mTelephonyManager.getPhoneCount()).thenReturn(1);
- mController.displayPreference(mScreen);
-
- mController.updateState(mPreference);
-
- verify(mPreference).setTitle(ResourcesUtils.getResourcesString(mContext, "status_number"));
- verify(mPreference).setSummary(phoneNumber);
- }
-
- @Test
- public void updateState_multiSim_shouldUpdateTitleAndPhoneNumberOfMultiplePreferences() {
- final String phoneNumber = "1111111111";
- doReturn(mSubscriptionInfo).when(mController).getSubscriptionInfo(anyInt());
- doReturn(phoneNumber).when(mController).getFormattedPhoneNumber(mSubscriptionInfo);
- when(mTelephonyManager.getPhoneCount()).thenReturn(2);
- mController.displayPreference(mScreen);
-
- mController.updateState(mPreference);
-
- verify(mPreference).setTitle(ResourcesUtils.getResourcesString(
- mContext, "status_number_sim_slot", 1 /* sim slot */));
- verify(mPreference).setSummary(phoneNumber);
- verify(mSecondPreference).setTitle(ResourcesUtils.getResourcesString(
- mContext, "status_number_sim_slot", 2 /* sim slot */));
- verify(mSecondPreference).setSummary(phoneNumber);
- }
-
- @Test
- public void getSummary_cannotGetActiveSubscriptionInfo_shouldShowNotAvailable() {
- when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(null);
- mController.displayPreference(mScreen);
-
- mController.updateState(mPreference);
-
- verify(mPreference).setSummary(mContext.getString(R.string.device_info_not_available));
- }
-
- @Test
- public void getSummary_getEmptySubscriptionInfo_shouldShowNotAvailable() {
- List<SubscriptionInfo> infos = new ArrayList<>();
- when(mSubscriptionManager.getActiveSubscriptionInfoList()).thenReturn(infos);
-
- mController.displayPreference(mScreen);
- mController.updateState(mPreference);
-
- verify(mPreference).setSummary(mContext.getString(R.string.device_info_not_available));
- }
-}