Snap for 9446745 from 2451afc0df to udc-release
Change-Id: Ib1306a9668829d0d306962b8282576fbc4b5e2f7
This commit is contained in:
@@ -354,6 +354,24 @@
|
||||
<!-- Description for introduction of the locale selection supported of app list [CHAR LIMIT=NONE]-->
|
||||
<string name="desc_app_locale_selection_supported">Only apps that support language selection are shown here.</string>
|
||||
|
||||
<!-- Regional Preferences begin -->
|
||||
<!-- The title of the menu entry of regional preferences. [CHAR LIMIT=50] -->
|
||||
<string name="regional_preferences_title">Regional preferences</string>
|
||||
<!-- The summary of the menu entry of regional preferences. [CHAR LIMIT=NONE] -->
|
||||
<string name="regional_preferences_summary">Set units and number preferences</string>
|
||||
<!-- The subtitle of main page of regional preferences. [CHAR LIMIT=NONE] -->
|
||||
<string name="regional_preferences_main_page_sub_title">Apps can use your regional preferences to personalize your experience</string>
|
||||
<!-- The title of menu entry of Temperature unit preference. [CHAR LIMIT=50] -->
|
||||
<string name="temperature_preferences_title">Temperature</string>
|
||||
<!-- The title of the menu entry of Calendar type preference. [CHAR LIMIT=50] -->
|
||||
<string name="calendar_preferences_title">Calendar</string>
|
||||
<!-- The title of the menu entry of First day of week preference. [CHAR LIMIT=50] -->
|
||||
<string name="first_day_of_week_preferences_title">First day of week</string>
|
||||
<!-- The title of the menu entry of Numbers system preference. [CHAR LIMIT=50] -->
|
||||
<string name="numbers_preferences_title">Numbers</string>
|
||||
<!-- The summary of default string for each regional preference. [CHAR LIMIT=50] -->
|
||||
<string name="default_string_of_regional_preference">[No preference]</string>
|
||||
|
||||
<!-- The title of the confirmation dialog shown when the user selects one / several languages and tries to remove them [CHAR LIMIT=60] -->
|
||||
<string name="dlg_remove_locales_title">{count, plural,
|
||||
=1 {Remove selected language?}
|
||||
@@ -492,10 +510,10 @@
|
||||
<!-- Used in the location settings to control turning on/off the feature entirely [CHAR LIMIT=60] -->
|
||||
<string name="location_settings_primary_switch_title">Use location</string>
|
||||
<!-- Summary for Location settings when location is on, explaining how many apps have location permission [CHAR LIMIT=NONE]-->
|
||||
<plurals name="location_settings_summary_location_on">
|
||||
<item quantity="one">On - <xliff:g id="count">%1$d</xliff:g> app has access to location</item>
|
||||
<item quantity="other">On - <xliff:g id="count">%1$d</xliff:g> apps have access to location</item>
|
||||
</plurals>
|
||||
<string name="location_settings_summary_location_on">{count, plural,
|
||||
=1 {On - # app has access to location}
|
||||
other {On - # apps have access to location}
|
||||
}</string>
|
||||
<!-- Location settings, loading the number of apps which have location permission [CHAR LIMIT=30] -->
|
||||
<string name="location_settings_loading_app_permission_stats">Loading\u2026</string>
|
||||
<!-- Location settings footer warning text when location is on [CHAR LIMIT=NONE] -->
|
||||
@@ -677,10 +695,10 @@
|
||||
<!-- Preference to add another fingerprint -->
|
||||
<string name="fingerprint_add_title">Add fingerprint</string>
|
||||
<!-- Message showing the current number of fingerprints set up. Shown for a menu item that launches fingerprint settings or enrollment. -->
|
||||
<plurals name="security_settings_fingerprint_preference_summary">
|
||||
<item quantity="one">Fingerprint added</item>
|
||||
<item quantity="other"><xliff:g id="count">%1$d</xliff:g> fingerprints added</item>
|
||||
</plurals>
|
||||
<string name="security_settings_fingerprint_preference_summary">{count, plural,
|
||||
=1 {Fingerprint added}
|
||||
other {# fingerprints added}
|
||||
}</string>
|
||||
<!-- message shown in summary field when no fingerprints are registered -->
|
||||
<string name="security_settings_fingerprint_preference_summary_none"></string>
|
||||
<!-- Introduction title shown in fingerprint enrollment to introduce the fingerprint feature [CHAR LIMIT=29] -->
|
||||
@@ -4453,27 +4471,26 @@
|
||||
<string name="reduce_bright_colors_persist_preference_title">Keep on after device restarts</string>
|
||||
|
||||
<!-- Subtitle for the accessibility preference to configure feature that performs click action soon after mouse/trackpad pointer stops moving, in case delay before click is extremely short. Placeholder will be set to the number of milliseconds to which the delay amounts. [CHAR LIMIT=NONE] -->
|
||||
<plurals name="accessibilty_autoclick_preference_subtitle_short_delay">
|
||||
<item quantity="one">Short (<xliff:g id="click_delay_label" example="200">%1$s</xliff:g> second)</item>
|
||||
<item quantity="other">Short (<xliff:g id="click_delay_label" example="200">%1$s</xliff:g> seconds)</item>
|
||||
</plurals>
|
||||
<string name="accessibilty_autoclick_preference_subtitle_short_delay">{count, plural,
|
||||
=1 {Short ({time} second)}
|
||||
other {Short ({time} seconds)}
|
||||
}</string>
|
||||
<!-- Subtitle for the accessibility preference to configure feature that performs click action soon after mouse/trackpad pointer stops moving, in case delay before click is extremely short. Placeholder will be set to the number of milliseconds to which the delay amounts. [CHAR LIMIT=NONE] -->
|
||||
<plurals name="accessibilty_autoclick_preference_subtitle_medium_delay">
|
||||
<item quantity="one">Medium (<xliff:g id="click_delay_label" example="200">%1$s</xliff:g> second)</item>
|
||||
<item quantity="other">Medium (<xliff:g id="click_delay_label" example="200">%1$s</xliff:g> seconds)</item>
|
||||
</plurals>
|
||||
<string name="accessibilty_autoclick_preference_subtitle_medium_delay">{count, plural,
|
||||
=1 {Medium ({time} second)}
|
||||
other {Medium ({time} seconds)}
|
||||
}</string>
|
||||
<!-- Subtitle for the accessibility preference to configure feature that performs click action soon after mouse/trackpad pointer stops moving, in case delay before click is extremely short. Placeholder will be set to the number of milliseconds to which the delay amounts. [CHAR LIMIT=NONE] -->
|
||||
<plurals name="accessibilty_autoclick_preference_subtitle_long_delay">
|
||||
<item quantity="one">Long (<xliff:g id="click_delay_label" example="200">%1$s</xliff:g> second)</item>
|
||||
<item quantity="other">Long (<xliff:g id="click_delay_label" example="200">%1$s</xliff:g> seconds)</item>
|
||||
</plurals>
|
||||
<string name="accessibilty_autoclick_preference_subtitle_long_delay">{count, plural,
|
||||
=1 {Long ({time} second)}
|
||||
other {Long ({time} seconds)}
|
||||
}</string>
|
||||
|
||||
<!-- Summary for autoclick seekbar settings preference when user selected custom item. [CHAR LIMIT=35] -->
|
||||
<plurals name="accessibilty_autoclick_delay_unit_second">
|
||||
<item quantity="one"><xliff:g id="click_delay_label" example="1">%1$s</xliff:g> second</item>
|
||||
<item quantity="few"><xliff:g id="click_delay_label" example="0.6">%1$s</xliff:g> seconds</item>
|
||||
<item quantity="other"><xliff:g id="click_delay_label">%1$s</xliff:g> seconds</item>
|
||||
</plurals>
|
||||
<string name="accessibilty_autoclick_delay_unit_second">{count, plural,
|
||||
=1 {{time} second}
|
||||
other {{time} seconds}
|
||||
}</string>
|
||||
|
||||
<!-- Title for accessibility menu item to launch a settings activity. [CHAR LIMIT=15] -->
|
||||
<string name="accessibility_menu_item_settings">Settings</string>
|
||||
@@ -4672,16 +4689,16 @@
|
||||
<string name="print_settings">Printing</string>
|
||||
|
||||
<!-- Print setting summary in settings screen [CHAR LIMIT=50] -->
|
||||
<plurals name="print_settings_summary">
|
||||
<item quantity="one">1 print service on</item>
|
||||
<item quantity="other"><xliff:g id="count">%1$d</xliff:g> print services on</item>
|
||||
</plurals>
|
||||
<string name="print_settings_summary">{count, plural,
|
||||
=1 {1 print service on}
|
||||
other {# print services on}
|
||||
}</string>
|
||||
|
||||
<!-- Print setting summary in settings screenm indicating how many print jobs are active [CHAR LIMIT=None] -->
|
||||
<plurals name="print_jobs_summary">
|
||||
<item quantity="one">1 print job</item>
|
||||
<item quantity="other"><xliff:g id="count">%1$d</xliff:g> print jobs</item>
|
||||
</plurals>
|
||||
<string name="print_jobs_summary">{count, plural,
|
||||
=1 {1 print job}
|
||||
other {# print jobs}
|
||||
}</string>
|
||||
|
||||
<!-- Title for print service settings screen [CHAR LIMIT=25] -->
|
||||
<string name="print_settings_title">Print services</string>
|
||||
@@ -4878,31 +4895,31 @@
|
||||
<!-- Footer message for battery tip dialog to show the status about the battery [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_dialog_message_footer">Includes high-power background activity</string>
|
||||
<!-- Title for restricted app preference, showing how many app need to be restricted [CHAR LIMIT=NONE] -->
|
||||
<plurals name="battery_tip_restrict_title">
|
||||
<item quantity="one">Restrict %1$d app</item>
|
||||
<item quantity="other">Restrict %1$d apps</item>
|
||||
</plurals>
|
||||
<string name="battery_tip_restrict_title">{count, plural,
|
||||
=1 {Restrict # app}
|
||||
other {Restrict # apps}
|
||||
}</string>
|
||||
<!-- Title for restricted app preference, showing how many app been restricted [CHAR LIMIT=NONE] -->
|
||||
<plurals name="battery_tip_restrict_handled_title">
|
||||
<item quantity="one">%1$s recently restricted</item>
|
||||
<item quantity="other">%2$d apps recently restricted</item>
|
||||
</plurals>
|
||||
<string name="battery_tip_restrict_handled_title">{count, plural,
|
||||
=1 {{label} recently restricted}
|
||||
other {# apps recently restricted}
|
||||
}</string>
|
||||
<!-- Summary for restricted app preference, showing the impact of the apps [CHAR LIMIT=NONE] -->
|
||||
<plurals name="battery_tip_restrict_summary">
|
||||
<item quantity="one">%1$s has high background battery usage</item>
|
||||
<item quantity="other">%2$d apps have high background battery usage</item>
|
||||
</plurals>
|
||||
<string name="battery_tip_restrict_summary">{count, plural,
|
||||
=1 {{label} has high background battery usage}
|
||||
other {# apps have high background battery usage}
|
||||
}</string>
|
||||
<!-- Summary for restricted app preference, showing the impact of the apps [CHAR LIMIT=NONE] -->
|
||||
<plurals name="battery_tip_restrict_handled_summary">
|
||||
<item quantity="one">This app can\'t run in the background</item>
|
||||
<item quantity="other">These apps can\'t run in the background</item>
|
||||
</plurals>
|
||||
<string name="battery_tip_restrict_handled_summary">{count, plural,
|
||||
=1 {This app can\'t run in the background}
|
||||
other {These apps can\'t run in the background}
|
||||
}</string>
|
||||
|
||||
<!-- Title for dialog to restrict the app [CHAR LIMIT=NONE] -->
|
||||
<plurals name="battery_tip_restrict_app_dialog_title">
|
||||
<item quantity="one">Restrict app?</item>
|
||||
<item quantity="other">Restrict %1$d apps?</item>
|
||||
</plurals>
|
||||
<string name="battery_tip_restrict_app_dialog_title">{count, plural,
|
||||
=1 {Restrict app?}
|
||||
other {Restrict # apps?}
|
||||
}</string>
|
||||
<!-- Message for battery tip dialog to show the info to restrict the app [CHAR LIMIT=NONE] -->
|
||||
<string name="battery_tip_restrict_app_dialog_message">To save battery, stop <xliff:g id="app">%1$s</xliff:g> from using battery in the background. This app may not work properly and notifications may be delayed.</string>
|
||||
<!-- Message for battery tip dialog to show the info to restrict the app, below it app list will be shown as a view [CHAR LIMIT=NONE] -->
|
||||
@@ -4931,10 +4948,10 @@
|
||||
<!-- Title for restricted app preference, clicking it will goes to restricted app list [CHAR LIMIT=NONE] -->
|
||||
<string name="restricted_app_title">Restricted apps</string>
|
||||
<!-- Summary for restricted app preference, clicking it will goes to restricted app list [CHAR LIMIT=NONE] -->
|
||||
<plurals name="restricted_app_summary">
|
||||
<item quantity="one">Limiting battery usage for %1$d app</item>
|
||||
<item quantity="other">Limiting battery usage for %1$d apps</item>
|
||||
</plurals>
|
||||
<string name="restricted_app_summary">{count, plural,
|
||||
=1 {Limiting battery usage for # app}
|
||||
other {Limiting battery usage for # apps}
|
||||
}</string>
|
||||
|
||||
<!-- Summary for restricted app to show the restriction time [CHAR LIMIT=NONE] -->
|
||||
<string name="restricted_app_time_summary">Restricted <xliff:g id="time" example="5 days ago">%1$s</xliff:g></string>
|
||||
@@ -4953,10 +4970,10 @@
|
||||
<string name="battery_manager_summary_unsupported">Detecting when apps drain battery</string>
|
||||
|
||||
<!-- Summary for battery manager, showing app restricted -->
|
||||
<plurals name="battery_manager_app_restricted">
|
||||
<item quantity="one">%1$d app restricted</item>
|
||||
<item quantity="other">%1$d apps restricted</item>
|
||||
</plurals>
|
||||
<string name="battery_manager_app_restricted">{count, plural,
|
||||
=1 {# app restricted}
|
||||
other {# apps restricted}
|
||||
}</string>
|
||||
|
||||
<!-- Title to display the battery percentage. [CHAR LIMIT=24] -->
|
||||
<string name="battery_header_title_alternate"><xliff:g id="number" example="88">^1</xliff:g><small> <font size="20"><xliff:g id="unit" example="%">%</xliff:g></font></small></string>
|
||||
@@ -5406,10 +5423,10 @@
|
||||
<!-- Dialog message for button to remove the credential management app [CHAR LIMIT=NONE] -->
|
||||
<string name="remove_credential_management_app_dialog_message">This app won\u2019t manage certificates, but it will stay on your device. Any certificates installed by the app will be uninstalled.</string>
|
||||
<!-- List item found in the credential management app's authentication policy [CHAR LIMIT=NONE] -->
|
||||
<plurals name="number_of_urls">
|
||||
<item quantity="one"><xliff:g id="number">%d</xliff:g> URL</item>
|
||||
<item quantity="other"><xliff:g id="number">%d</xliff:g> URLs</item>
|
||||
</plurals>
|
||||
<string name="number_of_urls">{count, plural,
|
||||
=1 {# URL}
|
||||
other {# URLs}
|
||||
}</string>
|
||||
|
||||
<!-- Sound settings screen, setting check box label -->
|
||||
<string name="emergency_tone_title">Emergency dialing signal</string>
|
||||
@@ -5510,10 +5527,10 @@
|
||||
<string name="notification_history_dismiss">Recently dismissed</string>
|
||||
|
||||
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
|
||||
<plurals name="notification_history_count">
|
||||
<item quantity="one"><xliff:g id="number">%d</xliff:g> notification</item>
|
||||
<item quantity="other"><xliff:g id="number">%d</xliff:g> notifications</item>
|
||||
</plurals>
|
||||
<string name="notification_history_count">{count, plural,
|
||||
=1 {# notification}
|
||||
other {# notifications}
|
||||
}</string>
|
||||
|
||||
<!-- Category title for phone call's ringtone and vibration settings in the Sound Setting.
|
||||
[CHAR LIMIT=40] -->
|
||||
@@ -5954,10 +5971,10 @@
|
||||
<!-- Button to close the SSL CA cert warning dialog box, meaning the user is done reading. [CHAR LIMIT=NONE] -->
|
||||
<string name="done_button">Done</string>
|
||||
<!-- Title of Dialog warning users of SSL monitoring. [CHAR LIMIT=NONE] -->
|
||||
<plurals name="ssl_ca_cert_dialog_title">
|
||||
<item quantity="one">Trust or remove certificate</item>
|
||||
<item quantity="other">Trust or remove certificates</item>
|
||||
</plurals>
|
||||
<string name="ssl_ca_cert_dialog_title">{count, plural,
|
||||
=1 {Trust or remove certificate}
|
||||
other {Trust or remove certificates}
|
||||
}</string>
|
||||
<!-- Text of message to show to device owner user whose administrator has installed a SSL CA Cert. [CHAR LIMIT=NONE] -->
|
||||
<string name="ssl_ca_cert_info_message_device_owner"> {numberOfCertificates, plural,
|
||||
=1 {{orgName} has installed a certificate authority on your device, which may allow them to monitor your device network activity, including emails, apps, and secure websites.\n\nFor more information about this certificate, contact your admin.}
|
||||
@@ -5971,10 +5988,10 @@
|
||||
<!-- Text of warning to show to users that have a SSL CA Cert installed. [CHAR LIMIT=NONE] -->
|
||||
<string name="ssl_ca_cert_warning_message">A third party is capable of monitoring your network activity, including emails, apps, and secure websites.\n\nA trusted credential installed on your device is making this possible.</string>
|
||||
<!-- Label on button that will take the user to the Trusted Credentials settings page. [CHAR LIMIT=NONE]-->
|
||||
<plurals name="ssl_ca_cert_settings_button">
|
||||
<item quantity="one">Check certificate</item>
|
||||
<item quantity="other">Check certificates</item>
|
||||
</plurals>
|
||||
<string name="ssl_ca_cert_settings_button">{count, plural,
|
||||
=1 {Check certificate}
|
||||
other {Check certificates}
|
||||
}</string>
|
||||
|
||||
<!-- User settings screen title [CHAR LIMIT=40] -->
|
||||
<string name="user_settings_title">Multiple users</string>
|
||||
@@ -7434,10 +7451,10 @@
|
||||
<string name="priority_conversation_count_zero">No priority conversations</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] summary text on link to 'all conversations' page, some conversations are priority -->
|
||||
<plurals name="priority_conversation_count">
|
||||
<item quantity="one"><xliff:g id="count" example="1">%d</xliff:g> priority conversation</item>
|
||||
<item quantity="other"><xliff:g id="count" example="10">%d</xliff:g> priority conversations</item>
|
||||
</plurals>
|
||||
<string name="priority_conversation_count">{count, plural,
|
||||
=1 {# priority conversation}
|
||||
other {# priority conversations}
|
||||
}</string>
|
||||
|
||||
<!-- [CHAR LIMIT=100] preference category title -->
|
||||
<string name="important_conversations">Priority conversations</string>
|
||||
@@ -7530,14 +7547,14 @@
|
||||
<string name="notification_app_switch_label">All <xliff:g id="app_name" example="Android Services">%1$s</xliff:g> notifications</string>
|
||||
|
||||
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
|
||||
<plurals name="notifications_sent_daily">
|
||||
<item quantity="one">About <xliff:g id="number">%d</xliff:g> notification per day</item>
|
||||
<item quantity="other">About <xliff:g id="number">%,d</xliff:g> notifications per day</item>
|
||||
</plurals>
|
||||
<plurals name="notifications_sent_weekly">
|
||||
<item quantity="one">About <xliff:g id="number">%d</xliff:g> notification per week</item>
|
||||
<item quantity="other">About <xliff:g id="number">%,d</xliff:g> notifications per week</item>
|
||||
</plurals>
|
||||
<string name="notifications_sent_daily">{count, plural,
|
||||
=1 {About # notification per day}
|
||||
other {About # notifications per day}
|
||||
}</string>
|
||||
<string name="notifications_sent_weekly">{count, plural,
|
||||
=1 {About # notification per week}
|
||||
other {About # notifications per week}
|
||||
}</string>
|
||||
<!-- app summary of notification app list screen [CHAR LIMIT=100] -->
|
||||
<string name="notifications_sent_never">Never</string>
|
||||
|
||||
@@ -7734,10 +7751,10 @@
|
||||
<string name="interact_across_profiles_number_of_connected_apps_none">No apps connected</string>
|
||||
|
||||
<!-- Summary of preference to manage connected work and personal apps, informing the user how many apps are connected -->
|
||||
<plurals name="interact_across_profiles_number_of_connected_apps">
|
||||
<item quantity="one"><xliff:g id="count">%d</xliff:g> app connected</item>
|
||||
<item quantity="other"><xliff:g id="count">%d</xliff:g> apps connected</item>
|
||||
</plurals>
|
||||
<string name="interact_across_profiles_number_of_connected_apps">{count, plural,
|
||||
=1 {# app connected}
|
||||
other {# apps connected}
|
||||
}</string>
|
||||
|
||||
<!-- Banner title. This banner lets a user know that they need to install an app in their
|
||||
work profile in order to connect it to the corresponding personal app.
|
||||
@@ -7788,10 +7805,10 @@
|
||||
<string name="app_settings_link">Additional settings in the app</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] Footer listing a count of deleted channels. -->
|
||||
<plurals name="deleted_channels">
|
||||
<item quantity="one"><xliff:g id="count" example="1">%d</xliff:g> category deleted</item>
|
||||
<item quantity="other"><xliff:g id="count" example="10">%d</xliff:g> categories deleted</item>
|
||||
</plurals>
|
||||
<string name="deleted_channels">{count, plural,
|
||||
=1 {# category deleted}
|
||||
other {# categories deleted}
|
||||
}</string>
|
||||
|
||||
<!-- [CHAR LIMIT=NONE] App notification settings: Block option title -->
|
||||
<string name="app_notification_block_title">Block all</string>
|
||||
|
||||
@@ -38,6 +38,15 @@
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.applications.appinfo.AppLocaleDetails" />
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
android:key="regional_preferences"
|
||||
android:title="@string/regional_preferences_title"
|
||||
android:summary="@string/regional_preferences_summary"
|
||||
android:fragment="com.android.settings.regionalpreferences.RegionalPreferencesEntriesFragment"
|
||||
settings:controller="com.android.settings.regionalpreferences.RegionalPreferencesController">
|
||||
</Preference>
|
||||
|
||||
</PreferenceCategory>
|
||||
|
||||
<PreferenceCategory
|
||||
|
||||
49
res/xml/regional_preference_main_page.xml
Normal file
49
res/xml/regional_preference_main_page.xml
Normal file
@@ -0,0 +1,49 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2022 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/regional_preferences_title">
|
||||
|
||||
<com.android.settingslib.widget.TopIntroPreference
|
||||
android:title="@string/regional_preferences_main_page_sub_title"
|
||||
android:persistent="false" />
|
||||
|
||||
<Preference
|
||||
android:key="key_temperature_unit"
|
||||
android:title="@string/temperature_preferences_title"
|
||||
android:summary="@string/default_string_of_regional_preference"
|
||||
settings:controller="com.android.settings.regionalpreferences.TemperatureUnitController"/>
|
||||
|
||||
<Preference
|
||||
android:key="key_calendar_type"
|
||||
android:title="@string/calendar_preferences_title"
|
||||
android:summary="@string/default_string_of_regional_preference"
|
||||
settings:controller="com.android.settings.regionalpreferences.CalendarTypeController"/>
|
||||
|
||||
<Preference
|
||||
android:key="key_first_day_of_week"
|
||||
android:title="@string/first_day_of_week_preferences_title"
|
||||
android:summary="@string/default_string_of_regional_preference"
|
||||
settings:controller="com.android.settings.regionalpreferences.FirstDayOfWeekController"/>
|
||||
|
||||
<Preference
|
||||
android:key="key_numbering_system"
|
||||
android:title="@string/numbers_preferences_title"
|
||||
android:summary="@string/default_string_of_regional_preference"
|
||||
settings:controller="com.android.settings.regionalpreferences.NumberingSystemController"/>
|
||||
|
||||
</PreferenceScreen>
|
||||
@@ -33,6 +33,7 @@ import android.provider.Settings;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Locale;
|
||||
@@ -65,16 +66,17 @@ public class MonitoringCertInfoActivity extends Activity implements OnClickListe
|
||||
final int numberOfCertificates = getIntent().getIntExtra(
|
||||
Settings.EXTRA_NUMBER_OF_CERTIFICATES, 1);
|
||||
final int titleId = RestrictedLockUtils.getProfileOrDeviceOwner(this, user) != null
|
||||
? R.plurals.ssl_ca_cert_settings_button // Check certificate
|
||||
: R.plurals.ssl_ca_cert_dialog_title; // Trust or remove certificate
|
||||
final CharSequence title = getResources().getQuantityText(titleId, numberOfCertificates);
|
||||
? R.string.ssl_ca_cert_settings_button // Check certificate
|
||||
: R.string.ssl_ca_cert_dialog_title; // Trust or remove certificate
|
||||
final CharSequence title = StringUtil.getIcuPluralsString(this, numberOfCertificates,
|
||||
titleId);
|
||||
setTitle(title);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(title);
|
||||
builder.setCancelable(true);
|
||||
builder.setPositiveButton(getResources().getQuantityText(
|
||||
R.plurals.ssl_ca_cert_settings_button, numberOfCertificates) , this);
|
||||
builder.setPositiveButton(StringUtil.getIcuPluralsString(this, numberOfCertificates,
|
||||
R.string.ssl_ca_cert_settings_button) , this);
|
||||
builder.setNeutralButton(R.string.cancel, null);
|
||||
builder.setOnDismissListener(this);
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ public class AutoclickPreferenceController extends BasePreferenceController {
|
||||
* placeholder for integer delay value.
|
||||
*/
|
||||
private static final int[] AUTOCLICK_PREFERENCE_SUMMARIES = {
|
||||
R.plurals.accessibilty_autoclick_preference_subtitle_short_delay,
|
||||
R.plurals.accessibilty_autoclick_preference_subtitle_medium_delay,
|
||||
R.plurals.accessibilty_autoclick_preference_subtitle_long_delay
|
||||
R.string.accessibilty_autoclick_preference_subtitle_short_delay,
|
||||
R.string.accessibilty_autoclick_preference_subtitle_medium_delay,
|
||||
R.string.accessibilty_autoclick_preference_subtitle_long_delay
|
||||
};
|
||||
|
||||
public AutoclickPreferenceController(Context context, String preferenceKey) {
|
||||
@@ -59,7 +59,7 @@ public class AutoclickPreferenceController extends BasePreferenceController {
|
||||
Settings.Secure.ACCESSIBILITY_AUTOCLICK_DELAY,
|
||||
AccessibilityManager.AUTOCLICK_DELAY_DEFAULT);
|
||||
final int summaryIndex = getAutoclickPreferenceSummaryIndex(delayMillis);
|
||||
return AutoclickUtils.getAutoclickDelaySummary(mContext.getResources(),
|
||||
return AutoclickUtils.getAutoclickDelaySummary(mContext,
|
||||
AUTOCLICK_PREFERENCE_SUMMARIES[summaryIndex], delayMillis);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,9 +20,16 @@ import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.PluralsRes;
|
||||
import android.annotation.StringRes;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/** Provides utility methods related auto click. */
|
||||
public final class AutoclickUtils {
|
||||
@@ -58,20 +65,23 @@ public final class AutoclickUtils {
|
||||
/**
|
||||
* Gets string that should be used for provided autoclick delay.
|
||||
*
|
||||
* @param resources Resources from which string should be retrieved.
|
||||
* @param context context from which string should be retrieved.
|
||||
* @param id The desired resource identifier, as generated by the aapt
|
||||
* tool. This integer encodes the package, type, and resource
|
||||
* entry. The value 0 is an invalid identifier.
|
||||
* @param delayMillis Delay for whose value summary should be retrieved.
|
||||
*/
|
||||
public static CharSequence getAutoclickDelaySummary(Resources resources,
|
||||
@PluralsRes int id, int delayMillis) {
|
||||
public static CharSequence getAutoclickDelaySummary(Context context,
|
||||
@StringRes int id, int delayMillis) {
|
||||
final int quantity = (delayMillis == 1000) ? Quantity.ONE : Quantity.FEW;
|
||||
final float delaySecond = (float) delayMillis / 1000;
|
||||
// Only show integer when delay time is 1.
|
||||
final String decimalFormat = (delaySecond == 1) ? "%.0f" : "%.1f";
|
||||
|
||||
return resources.getQuantityString(id, quantity, String.format(decimalFormat, delaySecond));
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
arguments.put("count", quantity);
|
||||
arguments.put("time", String.format(decimalFormat, delaySecond));
|
||||
return StringUtil.getIcuPluralsString(context, arguments, id);
|
||||
}
|
||||
|
||||
private AutoclickUtils(){}
|
||||
|
||||
@@ -176,7 +176,7 @@ public class ToggleAutoclickCustomSeekbarController extends BasePreferenceContro
|
||||
}
|
||||
}
|
||||
private CharSequence delayTimeToString(int delayMillis) {
|
||||
return AutoclickUtils.getAutoclickDelaySummary(mContext.getResources(),
|
||||
R.plurals.accessibilty_autoclick_delay_unit_second, delayMillis);
|
||||
return AutoclickUtils.getAutoclickDelaySummary(mContext,
|
||||
R.string.accessibilty_autoclick_delay_unit_second, delayMillis);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,11 +110,11 @@ public class AppStateNotificationBridge extends AppStateBaseBridge {
|
||||
context, System.currentTimeMillis() - state.lastSent, true);
|
||||
} else if (sortOrder == R.id.sort_order_frequent_notification) {
|
||||
if (state.avgSentDaily > 0) {
|
||||
return context.getResources().getQuantityString(
|
||||
R.plurals.notifications_sent_daily, state.avgSentDaily, state.avgSentDaily);
|
||||
return StringUtil.getIcuPluralsString(context, state.avgSentDaily,
|
||||
R.string.notifications_sent_daily);
|
||||
}
|
||||
return context.getResources().getQuantityString(R.plurals.notifications_sent_weekly,
|
||||
state.avgSentWeekly, state.avgSentWeekly);
|
||||
return StringUtil.getIcuPluralsString(context, state.avgSentWeekly,
|
||||
R.string.notifications_sent_weekly);
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import android.os.UserManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -66,9 +67,7 @@ public class InteractAcrossProfilesController extends BasePreferenceController {
|
||||
return connectedApps == 0
|
||||
? mContext.getResources().getString(
|
||||
R.string.interact_across_profiles_number_of_connected_apps_none)
|
||||
: mContext.getResources().getQuantityString(
|
||||
R.plurals.interact_across_profiles_number_of_connected_apps,
|
||||
connectedApps,
|
||||
connectedApps);
|
||||
: StringUtil.getIcuPluralsString(mContext, connectedApps,
|
||||
R.string.interact_across_profiles_number_of_connected_apps);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.android.settings.Settings;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.ParentalControlsUtils;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
/**
|
||||
* Utilities for combined biometric details shared between Security Settings and Safety Center.
|
||||
@@ -102,9 +103,8 @@ public class CombinedBiometricStatusUtils {
|
||||
} else if (faceEnrolled) {
|
||||
return mContext.getString(R.string.security_settings_face_preference_summary);
|
||||
} else if (numFingerprintsEnrolled > 0) {
|
||||
return mContext.getResources().getQuantityString(
|
||||
R.plurals.security_settings_fingerprint_preference_summary,
|
||||
numFingerprintsEnrolled, numFingerprintsEnrolled);
|
||||
return StringUtil.getIcuPluralsString(mContext, numFingerprintsEnrolled,
|
||||
R.string.security_settings_fingerprint_preference_summary);
|
||||
} else {
|
||||
return mContext.getString(
|
||||
R.string.security_settings_biometric_preference_summary_none_enrolled);
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.android.settings.Utils;
|
||||
import com.android.settings.biometrics.ParentalControlsUtils;
|
||||
import com.android.settings.biometrics2.ui.view.FingerprintEnrollmentActivity;
|
||||
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
/**
|
||||
* Utilities for fingerprint details shared between Security Settings and Safety Center.
|
||||
@@ -69,9 +70,8 @@ public class FingerprintStatusUtils {
|
||||
public String getSummary() {
|
||||
if (hasEnrolled()) {
|
||||
final int numEnrolled = mFingerprintManager.getEnrolledFingerprints(mUserId).size();
|
||||
return mContext.getResources().getQuantityString(
|
||||
R.plurals.security_settings_fingerprint_preference_summary,
|
||||
numEnrolled, numEnrolled);
|
||||
return StringUtil.getIcuPluralsString(mContext, numEnrolled,
|
||||
R.string.security_settings_fingerprint_preference_summary);
|
||||
} else {
|
||||
return mContext.getString(
|
||||
R.string.security_settings_fingerprint_preference_summary_none);
|
||||
|
||||
@@ -341,9 +341,7 @@ public class BluetoothDeviceDetailsFragment extends RestrictedDashboardFragment
|
||||
|
||||
@VisibleForTesting
|
||||
void setTitleForInputDevice() {
|
||||
// TODO(b/254835745) once source filter for bt stylus merged
|
||||
// && mInputDevice.supportsSource(InputDevice.SOURCE_BLUETOOTH_STYLUS))
|
||||
if (mInputDevice != null) {
|
||||
if (StylusDevicesController.isDeviceStylus(mInputDevice, mCachedDevice)) {
|
||||
// This will override the default R.string.device_details_title "Device Details"
|
||||
// that will show on non-stylus bluetooth devices.
|
||||
// That title is set via the manifest and also from BluetoothDeviceUpdater.
|
||||
|
||||
@@ -17,8 +17,6 @@
|
||||
package com.android.settings.development.featureflags;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
import android.util.FeatureFlagUtils;
|
||||
|
||||
import androidx.preference.SwitchPreference;
|
||||
@@ -51,13 +49,5 @@ public class FeatureFlagPreference extends SwitchPreference {
|
||||
} else {
|
||||
FeatureFlagUtils.setEnabled(getContext(), mKey, isChecked);
|
||||
}
|
||||
|
||||
// A temporary logic for settings_hide_second_layer_page_navigate_up_button_in_two_pane
|
||||
// Remove it before Android T release.
|
||||
if (TextUtils.equals(mKey,
|
||||
FeatureFlagUtils.SETTINGS_HIDE_SECOND_LAYER_PAGE_NAVIGATE_UP_BUTTON_IN_TWO_PANE)) {
|
||||
Settings.Global.putString(getContext().getContentResolver(),
|
||||
mKey, String.valueOf(isChecked));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import com.android.settings.core.InstrumentedPreferenceFragment;
|
||||
import com.android.settings.fuelgauge.batterytip.AppInfo;
|
||||
import com.android.settings.fuelgauge.batterytip.BatteryTipUtils;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -75,9 +76,8 @@ public class RestrictAppPreferenceController extends BasePreferenceController {
|
||||
final int num = mAppInfos.size();
|
||||
// Fragment change RestrictedAppsList after onPause(), UI needs to be updated in onResume()
|
||||
preference.setVisible(num > 0);
|
||||
preference.setSummary(
|
||||
mContext.getResources().getQuantityString(R.plurals.restricted_app_summary, num,
|
||||
num));
|
||||
preference.setSummary(StringUtil.getIcuPluralsString(mContext, num,
|
||||
R.string.restricted_app_summary));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
|
||||
import com.android.settings.overlay.FeatureFactory;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
/** Preference controller to control the battery manager */
|
||||
public class BatteryManagerPreferenceController extends BasePreferenceController {
|
||||
@@ -66,8 +67,8 @@ public class BatteryManagerPreferenceController extends BasePreferenceController
|
||||
@VisibleForTesting
|
||||
void updateSummary(Preference preference, int num) {
|
||||
if (num > 0) {
|
||||
preference.setSummary(mContext.getResources().getQuantityString(
|
||||
R.plurals.battery_manager_app_restricted, num, num));
|
||||
preference.setSummary(StringUtil.getIcuPluralsString(mContext, num,
|
||||
R.string.battery_manager_app_restricted));
|
||||
} else {
|
||||
preference.setSummary(
|
||||
mPowerUsageFeatureProvider.isAdaptiveChargingSupported()
|
||||
|
||||
@@ -42,6 +42,7 @@ import com.android.settings.fuelgauge.batterytip.tips.BatteryTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.HighUsageTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.RestrictAppTip;
|
||||
import com.android.settings.fuelgauge.batterytip.tips.UnrestrictAppTip;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -107,8 +108,8 @@ public class BatteryTipDialogFragment extends InstrumentedDialogFragment impleme
|
||||
restrictedAppList.get(0).packageName);
|
||||
|
||||
final AlertDialog.Builder builder = new AlertDialog.Builder(context)
|
||||
.setTitle(context.getResources().getQuantityString(
|
||||
R.plurals.battery_tip_restrict_app_dialog_title, num, num))
|
||||
.setTitle(StringUtil.getIcuPluralsString(context, num,
|
||||
R.string.battery_tip_restrict_app_dialog_title))
|
||||
.setPositiveButton(R.string.battery_tip_restrict_app_dialog_ok, this)
|
||||
.setNegativeButton(android.R.string.cancel, null);
|
||||
if (num == 1) {
|
||||
|
||||
@@ -28,9 +28,12 @@ import com.android.settings.R;
|
||||
import com.android.settings.Utils;
|
||||
import com.android.settings.fuelgauge.batterytip.AppInfo;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Tip to suggest user to restrict some bad apps
|
||||
@@ -62,12 +65,15 @@ public class RestrictAppTip extends BatteryTip {
|
||||
final int num = mRestrictAppList.size();
|
||||
final CharSequence appLabel = num > 0 ? Utils.getApplicationLabel(context,
|
||||
mRestrictAppList.get(0).packageName) : "";
|
||||
final Resources resources = context.getResources();
|
||||
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
arguments.put("count", num);
|
||||
arguments.put("label", appLabel);
|
||||
return mState == StateType.HANDLED
|
||||
? resources.getQuantityString(R.plurals.battery_tip_restrict_handled_title, num,
|
||||
appLabel, num)
|
||||
: resources.getQuantityString(R.plurals.battery_tip_restrict_title, num, num);
|
||||
? StringUtil.getIcuPluralsString(context, arguments,
|
||||
R.string.battery_tip_restrict_handled_title)
|
||||
: StringUtil.getIcuPluralsString(context, arguments,
|
||||
R.string.battery_tip_restrict_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -76,9 +82,12 @@ public class RestrictAppTip extends BatteryTip {
|
||||
final CharSequence appLabel = num > 0 ? Utils.getApplicationLabel(context,
|
||||
mRestrictAppList.get(0).packageName) : "";
|
||||
final int resId = mState == StateType.HANDLED
|
||||
? R.plurals.battery_tip_restrict_handled_summary
|
||||
: R.plurals.battery_tip_restrict_summary;
|
||||
return context.getResources().getQuantityString(resId, num, appLabel, num);
|
||||
? R.string.battery_tip_restrict_handled_summary
|
||||
: R.string.battery_tip_restrict_summary;
|
||||
Map<String, Object> arguments = new HashMap<>();
|
||||
arguments.put("count", num);
|
||||
arguments.put("label", appLabel);
|
||||
return StringUtil.getIcuPluralsString(context, arguments, resId);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,7 @@ import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -63,8 +64,8 @@ public class TopLevelLocationPreferenceController extends BasePreferenceControll
|
||||
|
||||
@VisibleForTesting
|
||||
void setLocationAppCount(int numApps) {
|
||||
sSummary = mContext.getResources().getQuantityString(
|
||||
R.plurals.location_settings_summary_location_on, numApps, numApps);
|
||||
sSummary = StringUtil.getIcuPluralsString(mContext, numApps,
|
||||
R.string.location_settings_summary_location_on);
|
||||
refreshSummary(mPreference);
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ import java.util.concurrent.atomic.AtomicReference;
|
||||
*/
|
||||
@SearchIndexable
|
||||
public class TetherSettings extends RestrictedSettingsFragment
|
||||
implements DataSaverBackend.Listener {
|
||||
implements DataSaverBackend.Listener, TetheringManager.TetheringEventCallback {
|
||||
|
||||
@VisibleForTesting
|
||||
static final String KEY_TETHER_PREFS_SCREEN = "tether_prefs_screen";
|
||||
@@ -111,7 +111,6 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
private OnStartTetheringCallback mStartTetheringCallback;
|
||||
private ConnectivityManager mCm;
|
||||
private EthernetManager mEm;
|
||||
private TetheringEventCallback mTetheringEventCallback;
|
||||
private EthernetListener mEthernetListener;
|
||||
private final HashSet<String> mAvailableInterfaces = new HashSet<>();
|
||||
|
||||
@@ -133,6 +132,7 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
Context mContext;
|
||||
@VisibleForTesting
|
||||
TetheringManager mTm;
|
||||
private TetheringHelper mTetheringHelper;
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
@@ -148,6 +148,8 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
super.onAttach(context);
|
||||
mWifiTetherPreferenceController =
|
||||
new WifiTetherPreferenceController(context, getSettingsLifecycle());
|
||||
mTetheringHelper = TetheringHelper.getInstance(context, this /* TetheringEventCallback */,
|
||||
getSettingsLifecycle());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -186,7 +188,7 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
mDataSaverBackend.addListener(this);
|
||||
|
||||
mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
mTm = (TetheringManager) getSystemService(Context.TETHERING_SERVICE);
|
||||
mTm = mTetheringHelper.getTetheringManager();
|
||||
// Some devices do not have available EthernetManager. In that case getSystemService will
|
||||
// return null.
|
||||
mEm = mContext.getSystemService(EthernetManager.class);
|
||||
@@ -364,15 +366,14 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
|
||||
|
||||
mStartTetheringCallback = new OnStartTetheringCallback(this);
|
||||
mTetheringEventCallback = new TetheringEventCallback(this);
|
||||
mTm.registerTetheringEventCallback(r -> mHandler.post(r), mTetheringEventCallback);
|
||||
|
||||
mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState());
|
||||
registerReceiver();
|
||||
|
||||
mEthernetListener = new EthernetListener(this);
|
||||
if (mEm != null) {
|
||||
mEm.addInterfaceStateListener(r -> mHandler.post(r), mEthernetListener);
|
||||
mEm.addInterfaceStateListener(mContext.getApplicationContext().getMainExecutor(),
|
||||
mEthernetListener);
|
||||
}
|
||||
|
||||
updateUsbState();
|
||||
@@ -387,13 +388,11 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
return;
|
||||
}
|
||||
getActivity().unregisterReceiver(mTetherChangeReceiver);
|
||||
mTm.unregisterTetheringEventCallback(mTetheringEventCallback);
|
||||
if (mEm != null) {
|
||||
mEm.removeInterfaceStateListener(mEthernetListener);
|
||||
}
|
||||
mTetherChangeReceiver = null;
|
||||
mStartTetheringCallback = null;
|
||||
mTetheringEventCallback = null;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -688,25 +687,8 @@ public class TetherSettings extends RestrictedSettingsFragment
|
||||
}
|
||||
}
|
||||
|
||||
private static final class TetheringEventCallback implements
|
||||
TetheringManager.TetheringEventCallback {
|
||||
final WeakReference<TetherSettings> mTetherSettings;
|
||||
|
||||
TetheringEventCallback(TetherSettings settings) {
|
||||
mTetherSettings = new WeakReference<>(settings);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTetheredInterfacesChanged(List<String> interfaces) {
|
||||
final TetherSettings tetherSettings = mTetherSettings.get();
|
||||
if (tetherSettings == null) {
|
||||
return;
|
||||
}
|
||||
tetherSettings.onTetheredInterfacesChanged(interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
void onTetheredInterfacesChanged(List<String> interfaces) {
|
||||
@Override
|
||||
public void onTetheredInterfacesChanged(List<String> interfaces) {
|
||||
Log.d(TAG, "onTetheredInterfacesChanged() interfaces : " + interfaces.toString());
|
||||
final String[] tethered = interfaces.toArray(new String[interfaces.size()]);
|
||||
updateUsbState(tethered);
|
||||
|
||||
157
src/com/android/settings/network/tether/TetheringHelper.java
Normal file
157
src/com/android/settings/network/tether/TetheringHelper.java
Normal file
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.tether;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.TestApi;
|
||||
import android.content.Context;
|
||||
import android.net.TetheringManager;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.VisibleForTesting;
|
||||
import androidx.lifecycle.DefaultLifecycleObserver;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Helper class for TetheringManager.
|
||||
*/
|
||||
public class TetheringHelper implements DefaultLifecycleObserver {
|
||||
private static final String TAG = "TetheringHelper";
|
||||
|
||||
private static final Object sInstanceLock = new Object();
|
||||
@TestApi
|
||||
@GuardedBy("sInstanceLock")
|
||||
private static Map<Context, TetheringHelper> sTestInstances;
|
||||
|
||||
protected static Context sAppContext;
|
||||
protected static TetheringManager sTetheringManager;
|
||||
protected static TetheringEventCallback sTetheringEventCallback = new TetheringEventCallback();
|
||||
protected static ArrayList<TetheringManager.TetheringEventCallback> sEventCallbacks =
|
||||
new ArrayList<>();
|
||||
|
||||
protected TetheringManager.TetheringEventCallback mCallback;
|
||||
|
||||
/**
|
||||
* Static method to create a singleton class for TetheringHelper.
|
||||
*
|
||||
* @param context The Context this is associated with.
|
||||
* @return an instance of {@link TetheringHelper} object.
|
||||
*/
|
||||
@NonNull
|
||||
public static TetheringHelper getInstance(@NonNull Context context,
|
||||
@NonNull TetheringManager.TetheringEventCallback callback,
|
||||
@NonNull Lifecycle lifecycle) {
|
||||
synchronized (sInstanceLock) {
|
||||
if (sTestInstances != null && sTestInstances.containsKey(context)) {
|
||||
TetheringHelper testInstance = sTestInstances.get(context);
|
||||
Log.w(TAG, "The context owner use a test instance:" + testInstance);
|
||||
return testInstance;
|
||||
}
|
||||
|
||||
if (sAppContext == null) {
|
||||
sAppContext = context.getApplicationContext();
|
||||
sTetheringManager = sAppContext.getSystemService(TetheringManager.class);
|
||||
}
|
||||
TetheringHelper helper = new TetheringHelper();
|
||||
helper.mCallback = callback;
|
||||
lifecycle.addObserver(helper);
|
||||
return helper;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A convenience method to set pre-prepared instance or mock class for testing.
|
||||
*
|
||||
* @param context The Context this is associated with.
|
||||
* @param instance of {@link TetheringHelper} object.
|
||||
* @hide
|
||||
*/
|
||||
@TestApi
|
||||
@VisibleForTesting
|
||||
public static void setTestInstance(@NonNull Context context, TetheringHelper instance) {
|
||||
synchronized (sInstanceLock) {
|
||||
if (sTestInstances == null) sTestInstances = new ConcurrentHashMap<>();
|
||||
Log.w(TAG, "Set a test instance by context:" + context);
|
||||
sTestInstances.put(context, instance);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The constructor can only be accessed from static method inside the class itself, this is
|
||||
* to avoid creating a class by adding a private constructor.
|
||||
*/
|
||||
private TetheringHelper() {
|
||||
// Do nothing.
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the TetheringManager If the system service is successfully obtained.
|
||||
*/
|
||||
public TetheringManager getTetheringManager() {
|
||||
return sTetheringManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart(@NonNull LifecycleOwner owner) {
|
||||
if (sEventCallbacks.contains(mCallback)) {
|
||||
Log.w(TAG, "The callback already contains, don't register callback:" + mCallback);
|
||||
return;
|
||||
}
|
||||
sEventCallbacks.add(mCallback);
|
||||
if (sEventCallbacks.size() == 1) {
|
||||
sTetheringManager.registerTetheringEventCallback(sAppContext.getMainExecutor(),
|
||||
sTetheringEventCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop(@NonNull LifecycleOwner owner) {
|
||||
if (!sEventCallbacks.remove(mCallback)) {
|
||||
Log.w(TAG, "The callback does not contain, don't unregister callback:" + mCallback);
|
||||
return;
|
||||
}
|
||||
if (sEventCallbacks.size() == 0) {
|
||||
sTetheringManager.unregisterTetheringEventCallback(sTetheringEventCallback);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy(@NonNull LifecycleOwner owner) {
|
||||
mCallback = null;
|
||||
}
|
||||
|
||||
protected static final class TetheringEventCallback implements
|
||||
TetheringManager.TetheringEventCallback {
|
||||
@Override
|
||||
public void onTetheredInterfacesChanged(List<String> interfaces) {
|
||||
for (TetheringManager.TetheringEventCallback callback : sEventCallbacks) {
|
||||
if (callback == null) continue;
|
||||
callback.onTetheredInterfacesChanged(interfaces);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import android.content.Context;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
public class ConversationListSummaryPreferenceController extends BasePreferenceController {
|
||||
|
||||
@@ -41,9 +42,8 @@ public class ConversationListSummaryPreferenceController extends BasePreferenceC
|
||||
if (count == 0) {
|
||||
return mContext.getText(R.string.priority_conversation_count_zero);
|
||||
}
|
||||
return mContext.getResources().getQuantityString(
|
||||
R.plurals.priority_conversation_count,
|
||||
count, count);
|
||||
return StringUtil.getIcuPluralsString(mContext, count,
|
||||
R.string.priority_conversation_count);
|
||||
}
|
||||
|
||||
void setBackend(NotificationBackend backend) {
|
||||
|
||||
@@ -509,11 +509,11 @@ public class NotificationBackend {
|
||||
context, System.currentTimeMillis() - state.lastSent, true);
|
||||
} else {
|
||||
if (state.avgSentDaily > 0) {
|
||||
return context.getResources().getQuantityString(R.plurals.notifications_sent_daily,
|
||||
state.avgSentDaily, state.avgSentDaily);
|
||||
return StringUtil.getIcuPluralsString(context, state.avgSentDaily,
|
||||
R.string.notifications_sent_daily);
|
||||
}
|
||||
return context.getResources().getQuantityString(R.plurals.notifications_sent_weekly,
|
||||
state.avgSentWeekly, state.avgSentWeekly);
|
||||
return StringUtil.getIcuPluralsString(context, state.avgSentWeekly,
|
||||
R.string.notifications_sent_weekly);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ import androidx.preference.Preference;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.PreferenceControllerMixin;
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
public class DeletedChannelsPreferenceController extends NotificationPreferenceController
|
||||
implements PreferenceControllerMixin {
|
||||
@@ -59,8 +60,8 @@ public class DeletedChannelsPreferenceController extends NotificationPreferenceC
|
||||
public void updateState(Preference preference) {
|
||||
if (mAppRow != null) {
|
||||
int deletedChannelCount = mBackend.getDeletedChannelCount(mAppRow.pkg, mAppRow.uid);
|
||||
preference.setTitle(mContext.getResources().getQuantityString(
|
||||
R.plurals.deleted_channels, deletedChannelCount, deletedChannelCount));
|
||||
preference.setTitle(StringUtil.getIcuPluralsString(mContext, deletedChannelCount,
|
||||
R.string.deleted_channels));
|
||||
}
|
||||
preference.setSelectable(false);
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ import com.android.internal.widget.NotificationExpandButton;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.notification.NotificationBackend;
|
||||
import com.android.settingslib.collapsingtoolbar.CollapsingToolbarBaseActivity;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
import com.android.settingslib.utils.ThreadUtils;
|
||||
import com.android.settingslib.widget.MainSwitchBar;
|
||||
import com.android.settingslib.widget.OnMainSwitchChangeListener;
|
||||
@@ -203,16 +204,15 @@ public class NotificationHistoryActivity extends CollapsingToolbarBaseActivity {
|
||||
icon.setImageDrawable(nhp.icon);
|
||||
|
||||
TextView count = viewForPackage.findViewById(R.id.count);
|
||||
count.setText(getResources().getQuantityString(R.plurals.notification_history_count,
|
||||
nhp.notifications.size(), nhp.notifications.size()));
|
||||
count.setText(StringUtil.getIcuPluralsString(this, nhp.notifications.size(),
|
||||
R.string.notification_history_count));
|
||||
|
||||
final NotificationHistoryRecyclerView rv =
|
||||
viewForPackage.findViewById(R.id.notification_list);
|
||||
rv.setAdapter(new NotificationHistoryAdapter(mNm, rv,
|
||||
newCount -> {
|
||||
count.setText(getResources().getQuantityString(
|
||||
R.plurals.notification_history_count,
|
||||
newCount, newCount));
|
||||
count.setText(StringUtil.getIcuPluralsString(this, newCount,
|
||||
R.string.notification_history_count));
|
||||
if (newCount == 0) {
|
||||
viewForPackage.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.core.lifecycle.LifecycleObserver;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStart;
|
||||
import com.android.settingslib.core.lifecycle.events.OnStop;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -110,17 +111,16 @@ public class PrintSettingPreferenceController extends BasePreferenceController i
|
||||
}
|
||||
|
||||
if (numActivePrintJobs > 0) {
|
||||
return mContext.getResources().getQuantityString(
|
||||
R.plurals.print_jobs_summary, numActivePrintJobs, numActivePrintJobs);
|
||||
return StringUtil.getIcuPluralsString(mContext, numActivePrintJobs,
|
||||
R.string.print_jobs_summary);
|
||||
} else {
|
||||
final List<PrintServiceInfo> services =
|
||||
mPrintManager.getPrintServices(PrintManager.ENABLED_SERVICES);
|
||||
if (services == null || services.isEmpty()) {
|
||||
return mContext.getText(R.string.off);
|
||||
} else {
|
||||
final int count = services.size();
|
||||
return mContext.getResources().getQuantityString(
|
||||
R.plurals.print_settings_summary, count, count);
|
||||
return StringUtil.getIcuPluralsString(mContext, services.size(),
|
||||
R.string.print_settings_summary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A controller for the entry of Calendar types' page
|
||||
*/
|
||||
public class CalendarTypeController extends BasePreferenceController {
|
||||
public CalendarTypeController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link AvailabilityStatus} for the Setting. This status is used to determine if the
|
||||
* Setting should be shown or disabled in Settings. Further, it can be used to produce
|
||||
* appropriate error / warning Slice in the case of unavailability.
|
||||
* </p>
|
||||
* The status is used for the convenience methods: {@link #isAvailable()}, {@link
|
||||
* #isSupported()}
|
||||
* </p>
|
||||
* The inherited class doesn't need to check work profile if android:forWork="true" is set in
|
||||
* preference xml.
|
||||
*/
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
String record = Settings.System.getString(
|
||||
mContext.getContentResolver(), Settings.System.LOCALE_PREFERENCES);
|
||||
String result = "";
|
||||
if (record != null) {
|
||||
result = LocalePreferences.getCalendarType(Locale.forLanguageTag(record), false);
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
result = LocalePreferences.getCalendarType(false);
|
||||
}
|
||||
return result.isEmpty()
|
||||
? mContext.getString(R.string.default_string_of_regional_preference) : result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/** A controller for the entry of First Day of Week's page */
|
||||
public class FirstDayOfWeekController extends BasePreferenceController {
|
||||
public FirstDayOfWeekController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link AvailabilityStatus} for the Setting. This status is used to determine if the
|
||||
* Setting should be shown or disabled in Settings. Further, it can be used to produce
|
||||
* appropriate error / warning Slice in the case of unavailability.
|
||||
* </p>
|
||||
* The status is used for the convenience methods: {@link #isAvailable()}, {@link
|
||||
* #isSupported()}
|
||||
* </p>
|
||||
* The inherited class doesn't need to check work profile if android:forWork="true" is set in
|
||||
* preference xml.
|
||||
*/
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
String record = Settings.System.getString(
|
||||
mContext.getContentResolver(), Settings.System.LOCALE_PREFERENCES);
|
||||
String result = "";
|
||||
if (record != null) {
|
||||
result = LocalePreferences.getFirstDayOfWeek(Locale.forLanguageTag(record), false);
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
result = LocalePreferences.getFirstDayOfWeek(false);
|
||||
}
|
||||
return result.isEmpty()
|
||||
? mContext.getString(R.string.default_string_of_regional_preference) : result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
import android.icu.number.LocalizedNumberFormatter;
|
||||
import android.icu.number.NumberFormatter;
|
||||
import android.icu.text.DateFormat;
|
||||
import android.icu.text.DateTimePatternGenerator;
|
||||
import android.icu.util.MeasureUnit;
|
||||
import android.os.Build.VERSION;
|
||||
|
||||
import androidx.annotation.DoNotInline;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.OptIn;
|
||||
import androidx.annotation.RestrictTo;
|
||||
import androidx.annotation.StringDef;
|
||||
import androidx.core.os.BuildCompat;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Locale;
|
||||
import java.util.Locale.Category;
|
||||
|
||||
/**
|
||||
* TODO(b/263861083) This is a temp file and will replace it to Androidx version.
|
||||
* Provides friendly APIs to get the user's locale preferences. The data can refer to
|
||||
* external/cldr/common/main/en.xml.
|
||||
*/
|
||||
public final class LocalePreferences {
|
||||
private static final String TAG = LocalePreferences.class.getSimpleName();
|
||||
|
||||
/** APIs to get the user's preference of the hour cycle. */
|
||||
public static class HourCycle {
|
||||
private static final String U_EXTENSION_OF_HOUR_CYCLE = "hc";
|
||||
|
||||
/** 12 Hour System (0-11) */
|
||||
public static final String H11 = "h11";
|
||||
/** 12 Hour System (1-12) */
|
||||
public static final String H12 = "h12";
|
||||
/** 24 Hour System (0-23) */
|
||||
public static final String H23 = "h23";
|
||||
/** 24 Hour System (1-24) */
|
||||
public static final String H24 = "h24";
|
||||
/** Default hour cycle for the locale */
|
||||
public static final String DEFAULT = "";
|
||||
|
||||
/** @hide */
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
||||
@StringDef({
|
||||
H11,
|
||||
H12,
|
||||
H23,
|
||||
H24,
|
||||
DEFAULT
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface HourCycleTypes {
|
||||
}
|
||||
|
||||
private HourCycle() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the hour cycle which is from
|
||||
* {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and
|
||||
* bases on the {@code Locale#getDefault(Locale.Category)}. E.g. "h23"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@HourCycle.HourCycleTypes
|
||||
public static String getHourCycle() {
|
||||
return getHourCycle(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hour cycle setting of the inputted {@link Locale}. The returned result is resolved
|
||||
* and bases on the inputted {@code Locale}.
|
||||
* E.g. "h23"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@HourCycle.HourCycleTypes
|
||||
public static String getHourCycle(@NonNull Locale locale) {
|
||||
return getHourCycle(locale, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the hour cycle which is from
|
||||
* {@link Locale#getDefault(Locale.Category)}. E.g. "h23"
|
||||
*
|
||||
* @param resolved If the {@code Locale#getDefault(Locale.Category)} contains hour cycle subtag,
|
||||
* this argument is ignored. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag
|
||||
* and the resolved argument is true, this function tries to find the default
|
||||
* hour cycle for the {@code Locale#getDefault(Locale.Category)}. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain hour cycle subtag
|
||||
* and the resolved argument is false, this function returns empty string
|
||||
* i.e. HourCycle.Default.
|
||||
* @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified
|
||||
* in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string
|
||||
* i.e. HourCycle.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@HourCycle.HourCycleTypes
|
||||
public static String getHourCycle(
|
||||
boolean resolved) {
|
||||
return getHourCycle(Api33Impl.getDefaultLocale(), resolved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the hour cycle setting of the inputted {@link Locale}. E.g. "en-US-u-hc-h23".
|
||||
*
|
||||
* @param locale The {@code Locale} to get the hour cycle.
|
||||
* @param resolved If the given {@code Locale} contains hour cycle subtag, this argument is
|
||||
* ignored. If the given {@code Locale} doesn't contain hour cycle subtag and
|
||||
* the resolved argument is true, this function tries to find the default
|
||||
* hour cycle for the given {@code Locale}. If the given {@code Locale} doesn't
|
||||
* contain hour cycle subtag and the resolved argument is false, this function
|
||||
* return empty string i.e. HourCycle.Default.
|
||||
* @return {@link HourCycle.HourCycleTypes} If the malformed hour cycle format was specified
|
||||
* in the hour cycle subtag, e.g. en-US-u-hc-h32, this function returns empty string
|
||||
* i.e. HourCycle.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@HourCycle.HourCycleTypes
|
||||
public static String getHourCycle(@NonNull Locale locale, boolean resolved) {
|
||||
if (!BuildCompat.isAtLeastT()) {
|
||||
throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
|
||||
}
|
||||
return Api33Impl.getHourCycle(locale, resolved);
|
||||
}
|
||||
|
||||
/** APIs to get the user's preference of Calendar. */
|
||||
public static class CalendarType {
|
||||
private static final String U_EXTENSION_OF_CALENDAR = "ca";
|
||||
/** Chinese Calendar */
|
||||
public static final String CHINESE = "chinese";
|
||||
/** Dangi Calendar (Korea Calendar) */
|
||||
public static final String DANGI = "dangi";
|
||||
/** Gregorian Calendar */
|
||||
public static final String GREGORIAN = "gregorian";
|
||||
/** Hebrew Calendar */
|
||||
public static final String HEBREW = "hebrew";
|
||||
/** Indian National Calendar */
|
||||
public static final String INDIAN = "indian";
|
||||
/** Islamic Calendar */
|
||||
public static final String ISLAMIC = "islamic";
|
||||
/** Islamic Calendar (tabular, civil epoch) */
|
||||
public static final String ISLAMIC_CIVIL = "islamic-civil";
|
||||
/** Islamic Calendar (Saudi Arabia, sighting) */
|
||||
public static final String ISLAMIC_RGSA = "islamic-rgsa";
|
||||
/** Islamic Calendar (tabular, astronomical epoch) */
|
||||
public static final String ISLAMIC_TBLA = "islamic-tbla";
|
||||
/** Islamic Calendar (Umm al-Qura) */
|
||||
public static final String ISLAMIC_UMALQURA = "islamic-umalqura";
|
||||
/** Persian Calendar */
|
||||
public static final String PERSIAN = "persian";
|
||||
/** Default calendar for the locale */
|
||||
public static final String DEFAULT = "";
|
||||
|
||||
/** @hide */
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
||||
@StringDef({
|
||||
CHINESE,
|
||||
DANGI,
|
||||
GREGORIAN,
|
||||
HEBREW,
|
||||
INDIAN,
|
||||
ISLAMIC,
|
||||
ISLAMIC_CIVIL,
|
||||
ISLAMIC_RGSA,
|
||||
ISLAMIC_TBLA,
|
||||
ISLAMIC_UMALQURA,
|
||||
PERSIAN,
|
||||
DEFAULT
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface CalendarTypes {
|
||||
}
|
||||
|
||||
private CalendarType() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the calendar type which is from {@link
|
||||
* Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on
|
||||
* the {@code Locale#getDefault(Locale.Category)} settings. E.g. "chinese"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@CalendarType.CalendarTypes
|
||||
public static String getCalendarType() {
|
||||
return getCalendarType(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calendar type of the inputted {@link Locale}. The returned result is resolved and
|
||||
* bases on the inputted {@link Locale} settings.
|
||||
* E.g. "chinese"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@CalendarType.CalendarTypes
|
||||
public static String getCalendarType(@NonNull Locale locale) {
|
||||
return getCalendarType(locale, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the calendar type which is from {@link
|
||||
* Locale#getDefault(Locale.Category)}. E.g. "chinese"
|
||||
*
|
||||
* @param resolved If the {@code Locale#getDefault(Locale.Category)} contains calendar type
|
||||
* subtag, this argument is ignored. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type
|
||||
* subtag and the resolved argument is true, this function tries to find
|
||||
* the default calendar type for the
|
||||
* {@code Locale#getDefault(Locale.Category)}. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain calendar type
|
||||
* subtag and the resolved argument is false, this function returns empty string
|
||||
* i.e. CalendarTypes.Default.
|
||||
* @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was
|
||||
* specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns
|
||||
* empty string i.e. CalendarTypes.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@CalendarType.CalendarTypes
|
||||
public static String getCalendarType(boolean resolved) {
|
||||
return getCalendarType(Api33Impl.getDefaultLocale(), resolved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the calendar type of the inputted {@link Locale}. E.g. "chinese"
|
||||
*
|
||||
* @param locale The {@link Locale} to get the calendar type.
|
||||
* @param resolved If the given {@code Locale} contains calendar type subtag, this argument is
|
||||
* ignored. If the given {@code Locale} doesn't contain calendar type subtag and
|
||||
* the resolved argument is true, this function tries to find the default
|
||||
* calendar type for the given {@code Locale}. If the given {@code Locale}
|
||||
* doesn't contain calendar type subtag and the resolved argument is false, this
|
||||
* function return empty string i.e. CalendarTypes.Default.
|
||||
* @return {@link CalendarType.CalendarTypes} If the malformed calendar type format was
|
||||
* specified in the calendar type subtag, e.g. en-US-u-ca-calendar, this function returns
|
||||
* empty string i.e. CalendarTypes.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@CalendarType.CalendarTypes
|
||||
public static String getCalendarType(@NonNull Locale locale, boolean resolved) {
|
||||
if (!BuildCompat.isAtLeastT()) {
|
||||
throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
|
||||
}
|
||||
return Api33Impl.getCalendarType(locale, resolved);
|
||||
}
|
||||
|
||||
/** APIs to get the user's preference of temperature unit. */
|
||||
public static class TemperatureUnit {
|
||||
private static final String U_EXTENSION_OF_TEMPERATURE_UNIT = "mu";
|
||||
/** Celsius */
|
||||
public static final String CELSIUS = "celsius";
|
||||
/** Fahrenheit */
|
||||
public static final String FAHRENHEIT = "fahrenheit";
|
||||
/** Kelvin */
|
||||
public static final String KELVIN = "kelvin";
|
||||
/** Default Temperature for the locale */
|
||||
public static final String DEFAULT = "";
|
||||
|
||||
/** @hide */
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
||||
@StringDef({
|
||||
CELSIUS,
|
||||
FAHRENHEIT,
|
||||
KELVIN,
|
||||
DEFAULT
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface TemperatureUnits {
|
||||
}
|
||||
|
||||
private TemperatureUnit() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the temperature unit which is from {@link
|
||||
* Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the
|
||||
* {@code Locale#getDefault(Locale.Category)} settings. E.g. "fahrenheit"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@TemperatureUnit.TemperatureUnits
|
||||
public static String getTemperatureUnit() {
|
||||
return getTemperatureUnit(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the temperature unit of the inputted {@link Locale}. The returned result is resolved
|
||||
* and bases on the inputted {@code Locale} settings. E.g. "fahrenheit"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@TemperatureUnit.TemperatureUnits
|
||||
public static String getTemperatureUnit(
|
||||
@NonNull Locale locale) {
|
||||
return getTemperatureUnit(locale, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the temperature unit which is from {@link
|
||||
* Locale#getDefault(Locale.Category)}. E.g. "fahrenheit"
|
||||
*
|
||||
* @param resolved If the {@code Locale#getDefault(Locale.Category)} contains temperature unit
|
||||
* subtag, this argument is ignored. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit
|
||||
* subtag and the resolved argument is true, this function tries to find
|
||||
* the default temperature unit for the
|
||||
* {@code Locale#getDefault(Locale.Category)}. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain temperature unit
|
||||
* subtag and the resolved argument is false, this function returns empty string
|
||||
* i.e. TemperatureUnits.Default.
|
||||
* @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was
|
||||
* specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns
|
||||
* empty string i.e. TemperatureUnits.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@TemperatureUnit.TemperatureUnits
|
||||
public static String getTemperatureUnit(boolean resolved) {
|
||||
return getTemperatureUnit(Api33Impl.getDefaultLocale(), resolved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the temperature unit of the inputted {@link Locale}. E.g. "fahrenheit"
|
||||
*
|
||||
* @param locale The {@link Locale} to get the temperature unit.
|
||||
* @param resolved If the given {@code Locale} contains temperature unit subtag, this argument
|
||||
* is ignored. If the given {@code Locale} doesn't contain temperature unit
|
||||
* subtag and the resolved argument is true, this function tries to find
|
||||
* the default temperature unit for the given {@code Locale}. If the given
|
||||
* {@code Locale} doesn't contain temperature unit subtag and the resolved
|
||||
* argument is false, this function return empty string
|
||||
* i.e. TemperatureUnits.Default.
|
||||
* @return {@link TemperatureUnit.TemperatureUnits} If the malformed temperature unit format was
|
||||
* specified in the temperature unit subtag, e.g. en-US-u-mu-temperature, this function returns
|
||||
* empty string i.e. TemperatureUnits.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@TemperatureUnit.TemperatureUnits
|
||||
public static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) {
|
||||
if (!BuildCompat.isAtLeastT()) {
|
||||
throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
|
||||
}
|
||||
return Api33Impl.getTemperatureUnit(locale, resolved);
|
||||
}
|
||||
|
||||
/** APIs to get the user's preference of the first day of week. */
|
||||
public static class FirstDayOfWeek {
|
||||
private static final String U_EXTENSION_OF_FIRST_DAY_OF_WEEK = "fw";
|
||||
/** Sunday */
|
||||
public static final String SUNDAY = "sun";
|
||||
/** Monday */
|
||||
public static final String MONDAY = "mon";
|
||||
/** Tuesday */
|
||||
public static final String TUESDAY = "tue";
|
||||
/** Wednesday */
|
||||
public static final String WEDNESDAY = "wed";
|
||||
/** Thursday */
|
||||
public static final String THURSDAY = "thu";
|
||||
/** Friday */
|
||||
public static final String FRIDAY = "fri";
|
||||
/** Saturday */
|
||||
public static final String SATURDAY = "sat";
|
||||
/** Default first day of week for the locale */
|
||||
public static final String DEFAULT = "";
|
||||
|
||||
/** @hide */
|
||||
@RestrictTo(RestrictTo.Scope.LIBRARY)
|
||||
@StringDef({
|
||||
SUNDAY,
|
||||
MONDAY,
|
||||
TUESDAY,
|
||||
WEDNESDAY,
|
||||
THURSDAY,
|
||||
FRIDAY,
|
||||
SATURDAY,
|
||||
DEFAULT
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Days {
|
||||
}
|
||||
|
||||
private FirstDayOfWeek() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the first day of week which is from
|
||||
* {@link Locale#getDefault(Locale.Category)}. The returned result is resolved and bases on the
|
||||
* {@code Locale#getDefault(Locale.Category)} settings. E.g. "sun"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@FirstDayOfWeek.Days
|
||||
public static String getFirstDayOfWeek() {
|
||||
return getFirstDayOfWeek(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first day of week of the inputted {@link Locale}. The returned result is resolved
|
||||
* and bases on the inputted {@code Locale} settings.
|
||||
* E.g. "sun"
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
public static @FirstDayOfWeek.Days String getFirstDayOfWeek(@NonNull Locale locale) {
|
||||
return getFirstDayOfWeek(locale, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the user's preference of the first day of week which is from {@link
|
||||
* Locale#getDefault(Locale.Category)}. E.g. "sun"
|
||||
*
|
||||
* @param resolved If the {@code Locale#getDefault(Locale.Category)} contains first day of week
|
||||
* subtag, this argument is ignored. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week
|
||||
* subtag and the resolved argument is true, this function tries to find
|
||||
* the default first day of week for the
|
||||
* {@code Locale#getDefault(Locale.Category)}. If the
|
||||
* {@code Locale#getDefault(Locale.Category)} doesn't contain first day of week
|
||||
* subtag and the resolved argument is false, this function returns empty string
|
||||
* i.e. Days.Default.
|
||||
* @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was specified
|
||||
* in the first day of week subtag, e.g. en-US-u-fw-days, this function returns empty string
|
||||
* i.e. Days.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@FirstDayOfWeek.Days
|
||||
public static String getFirstDayOfWeek(boolean resolved) {
|
||||
return getFirstDayOfWeek(Api33Impl.getDefaultLocale(), resolved);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the first day of week of the inputted {@link Locale}. E.g. "sun"
|
||||
*
|
||||
* @param locale The {@link Locale} to get the first day of week.
|
||||
* @param resolved If the given {@code Locale} contains first day of week subtag, this argument
|
||||
* is ignored. If the given {@code Locale} doesn't contain first day of week
|
||||
* subtag and the resolved argument is true, this function tries to find
|
||||
* the default first day of week for the given {@code Locale}. If the given
|
||||
* {@code Locale} doesn't contain first day of week subtag and the resolved
|
||||
* argument is false, this function return empty string i.e. Days.Default.
|
||||
* @return {@link FirstDayOfWeek.Days} If the malformed first day of week format was
|
||||
* specified in the first day of week subtag, e.g. en-US-u-fw-days, this function returns
|
||||
* empty string i.e. Days.Default.
|
||||
*/
|
||||
@NonNull
|
||||
@OptIn(markerClass = BuildCompat.PrereleaseSdkCheck.class)
|
||||
@FirstDayOfWeek.Days
|
||||
public static String getFirstDayOfWeek(
|
||||
@NonNull Locale locale, boolean resolved) {
|
||||
if (!BuildCompat.isAtLeastT()) {
|
||||
throw new IllegalArgumentException("not a valid extension: " + VERSION.SDK_INT);
|
||||
}
|
||||
|
||||
return Api33Impl.getFirstDayOfWeek(locale, resolved);
|
||||
}
|
||||
|
||||
private static class Api33Impl {
|
||||
@DoNotInline
|
||||
@HourCycle.HourCycleTypes
|
||||
static String getHourCycle(@NonNull Locale locale,
|
||||
boolean resolved) {
|
||||
String hc = locale.getUnicodeLocaleType(HourCycle.U_EXTENSION_OF_HOUR_CYCLE);
|
||||
if (hc != null) {
|
||||
return hc;
|
||||
}
|
||||
if (!resolved) {
|
||||
return HourCycle.DEFAULT;
|
||||
}
|
||||
|
||||
return getHourCycleType(
|
||||
DateTimePatternGenerator.getInstance(locale).getDefaultHourCycle());
|
||||
|
||||
}
|
||||
|
||||
@DoNotInline
|
||||
@CalendarType.CalendarTypes
|
||||
static String getCalendarType(@NonNull Locale locale, boolean resolved) {
|
||||
String ca = locale.getUnicodeLocaleType(CalendarType.U_EXTENSION_OF_CALENDAR);
|
||||
if (ca != null) {
|
||||
return ca;
|
||||
}
|
||||
if (!resolved) {
|
||||
return CalendarType.DEFAULT;
|
||||
}
|
||||
|
||||
return android.icu.util.Calendar.getInstance(locale).getType();
|
||||
}
|
||||
|
||||
@DoNotInline
|
||||
@TemperatureUnit.TemperatureUnits
|
||||
static String getTemperatureUnit(@NonNull Locale locale, boolean resolved) {
|
||||
String mu =
|
||||
locale.getUnicodeLocaleType(TemperatureUnit.U_EXTENSION_OF_TEMPERATURE_UNIT);
|
||||
if (mu != null) {
|
||||
if (mu.contains("fahrenhe")) {
|
||||
mu = TemperatureUnit.FAHRENHEIT;
|
||||
}
|
||||
return mu;
|
||||
}
|
||||
if (!resolved) {
|
||||
return TemperatureUnit.DEFAULT;
|
||||
}
|
||||
|
||||
return getResolvedTemperatureUnit(locale);
|
||||
}
|
||||
|
||||
@DoNotInline
|
||||
@FirstDayOfWeek.Days
|
||||
static String getFirstDayOfWeek(@NonNull Locale locale, boolean resolved) {
|
||||
String mu =
|
||||
locale.getUnicodeLocaleType(FirstDayOfWeek.U_EXTENSION_OF_FIRST_DAY_OF_WEEK);
|
||||
if (mu != null) {
|
||||
return mu;
|
||||
}
|
||||
if (!resolved) {
|
||||
return FirstDayOfWeek.DEFAULT;
|
||||
}
|
||||
// TODO(b/262294472) Use {@code android.icu.util.Calendar} instead of
|
||||
// {@code java.util.Calendar}.
|
||||
return getStringOfFirstDayOfWeek(
|
||||
java.util.Calendar.getInstance(locale).getFirstDayOfWeek());
|
||||
}
|
||||
|
||||
@DoNotInline
|
||||
static Locale getDefaultLocale() {
|
||||
return Locale.getDefault(Category.FORMAT);
|
||||
}
|
||||
|
||||
private static String getStringOfFirstDayOfWeek(int fw) {
|
||||
String[] arrDays = {
|
||||
FirstDayOfWeek.SUNDAY,
|
||||
FirstDayOfWeek.MONDAY,
|
||||
FirstDayOfWeek.TUESDAY,
|
||||
FirstDayOfWeek.WEDNESDAY,
|
||||
FirstDayOfWeek.THURSDAY,
|
||||
FirstDayOfWeek.FRIDAY,
|
||||
FirstDayOfWeek.SATURDAY};
|
||||
|
||||
return fw >= 1 && fw <= 7 ? arrDays[fw - 1] : FirstDayOfWeek.DEFAULT;
|
||||
}
|
||||
|
||||
@HourCycle.HourCycleTypes
|
||||
private static String getHourCycleType(
|
||||
DateFormat.HourCycle hourCycle) {
|
||||
switch (hourCycle) {
|
||||
case HOUR_CYCLE_11:
|
||||
return HourCycle.H11;
|
||||
case HOUR_CYCLE_12:
|
||||
return HourCycle.H12;
|
||||
case HOUR_CYCLE_23:
|
||||
return HourCycle.H23;
|
||||
case HOUR_CYCLE_24:
|
||||
return HourCycle.H24;
|
||||
default:
|
||||
return HourCycle.DEFAULT;
|
||||
}
|
||||
}
|
||||
|
||||
@TemperatureUnit.TemperatureUnits
|
||||
private static String getResolvedTemperatureUnit(@NonNull Locale locale) {
|
||||
LocalizedNumberFormatter nf = NumberFormatter.with()
|
||||
.usage("temperature")
|
||||
.unit(MeasureUnit.CELSIUS)
|
||||
.locale(locale);
|
||||
return nf.format(1).getOutputUnit().getIdentifier();
|
||||
}
|
||||
|
||||
private Api33Impl() {
|
||||
}
|
||||
}
|
||||
|
||||
private LocalePreferences() {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.icu.text.NumberingSystem;
|
||||
import android.provider.Settings;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/** A controller for the entry of Numbering System's page */
|
||||
public class NumberingSystemController extends BasePreferenceController {
|
||||
private static final String UNICODE_EXTENSION_NUMBERING_SYSTEM = "nu";
|
||||
|
||||
public NumberingSystemController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link AvailabilityStatus} for the Setting. This status is used to determine if the
|
||||
* Setting should be shown or disabled in Settings. Further, it can be used to produce
|
||||
* appropriate error / warning Slice in the case of unavailability.
|
||||
* </p>
|
||||
* The status is used for the convenience methods: {@link #isAvailable()}, {@link
|
||||
* #isSupported()}
|
||||
* </p>
|
||||
* The inherited class doesn't need to check work profile if android:forWork="true" is set in
|
||||
* preference xml.
|
||||
*/
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
String record = Settings.System.getString(
|
||||
mContext.getContentResolver(), Settings.System.LOCALE_PREFERENCES);
|
||||
String result = "";
|
||||
if (!TextUtils.isEmpty(record)) {
|
||||
result = Locale.forLanguageTag(record)
|
||||
.getUnicodeLocaleType(UNICODE_EXTENSION_NUMBERING_SYSTEM);
|
||||
}
|
||||
|
||||
if (TextUtils.isEmpty(result)) {
|
||||
result = Locale.getDefault(Locale.Category.FORMAT)
|
||||
.getUnicodeLocaleType(UNICODE_EXTENSION_NUMBERING_SYSTEM);
|
||||
if (TextUtils.isEmpty(result)) {
|
||||
return mContext.getString(R.string.default_string_of_regional_preference);
|
||||
}
|
||||
}
|
||||
|
||||
Locale locale = new Locale.Builder()
|
||||
.setUnicodeLocaleKeyword(UNICODE_EXTENSION_NUMBERING_SYSTEM, result)
|
||||
.build();
|
||||
return NumberingSystem.getInstance(locale).getName();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
/** A controller for the entry of Regional preferences */
|
||||
public class RegionalPreferencesController extends BasePreferenceController {
|
||||
// This is a feature flag and will be removed after feature completed.
|
||||
static final String FEATURE_PROPERTY = "i18n-feature-locale-preference";
|
||||
public RegionalPreferencesController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link AvailabilityStatus} for the Setting. This status is used to determine if the
|
||||
* Setting should be shown or disabled in Settings. Further, it can be used to produce
|
||||
* appropriate error / warning Slice in the case of unavailability.
|
||||
* </p>
|
||||
* The status is used for the convenience methods: {@link #isAvailable()}, {@link
|
||||
* #isSupported()}
|
||||
* </p>
|
||||
* The inherited class doesn't need to check work profile if android:forWork="true" is set in
|
||||
* preference xml.
|
||||
*/
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return SystemProperties.getBoolean(FEATURE_PROPERTY, false)
|
||||
? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.dashboard.DashboardFragment;
|
||||
import com.android.settings.search.BaseSearchIndexProvider;
|
||||
import com.android.settingslib.search.SearchIndexable;
|
||||
|
||||
/** Provides entries of each regional preferences */
|
||||
@SearchIndexable
|
||||
public class RegionalPreferencesEntriesFragment extends DashboardFragment {
|
||||
private static final String TAG = RegionalPreferencesEntriesFragment.class.getSimpleName();
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
getActivity().setTitle(R.string.regional_preferences_title);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMetricsCategory() {
|
||||
return SettingsEnums.REGIONAL_PREFERENCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getPreferenceScreenResId() {
|
||||
return R.xml.regional_preference_main_page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the tag string for logging.
|
||||
*/
|
||||
@Override
|
||||
protected String getLogTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
||||
new BaseSearchIndexProvider(R.xml.regional_preference_main_page);
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.core.BasePreferenceController;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
/** A controller for the entry of Temperature units' page */
|
||||
public class TemperatureUnitController extends BasePreferenceController {
|
||||
public TemperatureUnitController(Context context, String preferenceKey) {
|
||||
super(context, preferenceKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@link AvailabilityStatus} for the Setting. This status is used to determine if the
|
||||
* Setting should be shown or disabled in Settings. Further, it can be used to produce
|
||||
* appropriate error / warning Slice in the case of unavailability.
|
||||
* </p>
|
||||
* The status is used for the convenience methods: {@link #isAvailable()}, {@link
|
||||
* #isSupported()}
|
||||
* </p>
|
||||
* The inherited class doesn't need to check work profile if android:forWork="true" is set in
|
||||
* preference xml.
|
||||
*/
|
||||
@Override
|
||||
public int getAvailabilityStatus() {
|
||||
return AVAILABLE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence getSummary() {
|
||||
String record = Settings.System.getString(
|
||||
mContext.getContentResolver(), Settings.System.LOCALE_PREFERENCES);
|
||||
String result = "";
|
||||
if (record != null) {
|
||||
result = LocalePreferences.getTemperatureUnit(Locale.forLanguageTag(record), false);
|
||||
}
|
||||
|
||||
if (result.isEmpty()) {
|
||||
result = LocalePreferences.getTemperatureUnit(false);
|
||||
}
|
||||
return result.isEmpty()
|
||||
? mContext.getString(R.string.default_string_of_regional_preference) : result;
|
||||
}
|
||||
}
|
||||
@@ -34,6 +34,7 @@ import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -193,8 +194,8 @@ public class CredentialManagementAppAdapter extends RecyclerView.Adapter<Recycle
|
||||
}
|
||||
|
||||
private String getNumberOfUrlsText(Map<Uri, String> urisToAliases) {
|
||||
return mContext.getResources().getQuantityString(R.plurals.number_of_urls,
|
||||
urisToAliases.size(), urisToAliases.size());
|
||||
return StringUtil.getIcuPluralsString(mContext, urisToAliases.size(),
|
||||
R.string.number_of_urls);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -177,12 +177,14 @@ class AppNotificationRepository(
|
||||
fun calculateFrequencySummary(sentCount: Int): String {
|
||||
val dailyFrequency = (sentCount.toFloat() / DAYS_TO_CHECK).roundToInt()
|
||||
return if (dailyFrequency > 0) {
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.notifications_sent_daily, dailyFrequency, dailyFrequency
|
||||
context.formatString(
|
||||
R.string.notifications_sent_daily,
|
||||
"count" to dailyFrequency,
|
||||
)
|
||||
} else {
|
||||
context.resources.getQuantityString(
|
||||
R.plurals.notifications_sent_weekly, sentCount, sentCount
|
||||
context.formatString(
|
||||
R.string.notifications_sent_weekly,
|
||||
"count" to sentCount,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +82,6 @@ public class WifiEntryPreference extends RestrictedPreference implements
|
||||
super(context);
|
||||
|
||||
setLayoutResource(R.layout.preference_access_point);
|
||||
setWidgetLayoutResource(R.layout.access_point_friction_widget);
|
||||
mFrictionSld = getFrictionStateListDrawable();
|
||||
mWifiEntry = wifiEntry;
|
||||
mWifiEntry.setListener(this);
|
||||
@@ -280,6 +279,11 @@ public class WifiEntryPreference extends RestrictedPreference implements
|
||||
notifyChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSecondTargetResId() {
|
||||
return R.layout.access_point_friction_widget;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View view) {
|
||||
if (view.getId() == R.id.icon_button) {
|
||||
|
||||
@@ -72,8 +72,8 @@ public class AutoclickPreferenceControllerTest {
|
||||
|
||||
assertThat(mController.getSummary().toString())
|
||||
.isEqualTo(AutoclickUtils.getAutoclickDelaySummary(
|
||||
mContext.getResources(),
|
||||
R.plurals.accessibilty_autoclick_preference_subtitle_medium_delay,
|
||||
mContext,
|
||||
R.string.accessibilty_autoclick_preference_subtitle_medium_delay,
|
||||
AUTOCLICK_DELAY_DEFAULT).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public final class AutoclickUtilsTest {
|
||||
@Test
|
||||
public void getAutoclickDelaySummary_minDelay_shouldReturnOnSummary() {
|
||||
final CharSequence summary = AutoclickUtils.getAutoclickDelaySummary(
|
||||
mContext.getResources(), R.plurals.accessibilty_autoclick_delay_unit_second,
|
||||
mContext, R.string.accessibilty_autoclick_delay_unit_second,
|
||||
MIN_AUTOCLICK_DELAY_MS);
|
||||
assertThat(summary.toString()).isEqualTo("0.2 seconds");
|
||||
}
|
||||
@@ -48,7 +48,7 @@ public final class AutoclickUtilsTest {
|
||||
@Test
|
||||
public void getAutoclickDelaySummary_maxDelay_shouldReturnOnSummary() {
|
||||
final CharSequence summary = AutoclickUtils.getAutoclickDelaySummary(
|
||||
mContext.getResources(), R.plurals.accessibilty_autoclick_delay_unit_second,
|
||||
mContext, R.string.accessibilty_autoclick_delay_unit_second,
|
||||
MAX_AUTOCLICK_DELAY_MS);
|
||||
assertThat(summary.toString()).isEqualTo("1 second");
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ import com.android.settings.testutils.FakeFeatureFactory;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
@@ -140,8 +141,8 @@ public class FingerprintStatusPreferenceControllerTest {
|
||||
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.getSummary()).isEqualTo(mContext.getResources().getQuantityString(
|
||||
R.plurals.security_settings_fingerprint_preference_summary, 1, 1));
|
||||
assertThat(mPreference.getSummary()).isEqualTo(StringUtil.getIcuPluralsString(mContext, 1,
|
||||
R.string.security_settings_fingerprint_preference_summary));
|
||||
assertThat(mPreference.isVisible()).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@@ -159,7 +159,9 @@ public class BluetoothDeviceDetailsFragmentTest {
|
||||
public void getTitle_inputDeviceTitle() {
|
||||
FeatureFlagUtils.setEnabled(mContext, FeatureFlagUtils.SETTINGS_SHOW_STYLUS_PREFERENCES,
|
||||
true);
|
||||
doReturn(mock(InputDevice.class)).when(mFragment).getInputDevice(mContext);
|
||||
InputDevice inputDevice = mock(InputDevice.class);
|
||||
doReturn(true).when(inputDevice).supportsSource(InputDevice.SOURCE_STYLUS);
|
||||
doReturn(inputDevice).when(mFragment).getInputDevice(mContext);
|
||||
mFragment.onAttach(mContext);
|
||||
|
||||
mFragment.setTitleForInputDevice();
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.android.internal.logging.nano.MetricsProto;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.fuelgauge.batterytip.AppInfo;
|
||||
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -148,8 +149,8 @@ public class RestrictAppTipTest {
|
||||
@Test
|
||||
public void getSummary_oneAppHandled_showHandledSummary() {
|
||||
assertThat(mHandledBatteryTip.getSummary(mContext).toString())
|
||||
.isEqualTo(mContext.getResources().getQuantityString(
|
||||
R.plurals.battery_tip_restrict_handled_summary, 1));
|
||||
.isEqualTo(StringUtil.getIcuPluralsString(mContext, 1,
|
||||
R.string.battery_tip_restrict_handled_summary));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -157,8 +158,8 @@ public class RestrictAppTipTest {
|
||||
mUsageAppList.add(new AppInfo.Builder().build());
|
||||
mHandledBatteryTip = new RestrictAppTip(BatteryTip.StateType.HANDLED, mUsageAppList);
|
||||
assertThat(mHandledBatteryTip.getSummary(mContext))
|
||||
.isEqualTo(mContext.getResources().getQuantityString(
|
||||
R.plurals.battery_tip_restrict_handled_summary, 2));
|
||||
.isEqualTo(StringUtil.getIcuPluralsString(mContext, 2,
|
||||
R.string.battery_tip_restrict_handled_summary));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -22,6 +22,7 @@ import android.content.Context;
|
||||
import android.location.LocationManager;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -67,9 +68,8 @@ public class TopLevelLocationPreferenceControllerTest {
|
||||
// Turn on location again and check if the previous summary text is still cached.
|
||||
mLocationManager.setLocationEnabledForUser(true, android.os.Process.myUserHandle());
|
||||
assertThat(mController.getSummary()).isEqualTo(
|
||||
mContext.getResources().getQuantityString(
|
||||
R.plurals.location_settings_summary_location_on, locationAppCount,
|
||||
locationAppCount));
|
||||
StringUtil.getIcuPluralsString(mContext, locationAppCount,
|
||||
R.string.location_settings_summary_location_on));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -78,9 +78,8 @@ public class TopLevelLocationPreferenceControllerTest {
|
||||
mLocationManager.setLocationEnabledForUser(true, android.os.Process.myUserHandle());
|
||||
mController.setLocationAppCount(locationAppCount);
|
||||
assertThat(mController.getSummary()).isEqualTo(
|
||||
mContext.getResources().getQuantityString(
|
||||
R.plurals.location_settings_summary_location_on,
|
||||
locationAppCount, locationAppCount));
|
||||
StringUtil.getIcuPluralsString(mContext, locationAppCount,
|
||||
R.string.location_settings_summary_location_on));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -89,8 +88,7 @@ public class TopLevelLocationPreferenceControllerTest {
|
||||
mLocationManager.setLocationEnabledForUser(true, android.os.Process.myUserHandle());
|
||||
mController.setLocationAppCount(locationAppCount);
|
||||
assertThat(mController.getSummary()).isEqualTo(
|
||||
mContext.getResources().getQuantityString(
|
||||
R.plurals.location_settings_summary_location_on,
|
||||
locationAppCount, locationAppCount));
|
||||
StringUtil.getIcuPluralsString(mContext, locationAppCount,
|
||||
R.string.location_settings_summary_location_on));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.tether;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.TetheringManager;
|
||||
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.lifecycle.LifecycleOwner;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Spy;
|
||||
import org.mockito.junit.MockitoJUnit;
|
||||
import org.mockito.junit.MockitoRule;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TetheringHelperTest {
|
||||
@Rule
|
||||
public final MockitoRule mMockitoRule = MockitoJUnit.rule();
|
||||
@Spy
|
||||
Context mContext = ApplicationProvider.getApplicationContext();
|
||||
@Mock
|
||||
Lifecycle mLifecycle;
|
||||
@Mock
|
||||
LifecycleOwner mLifecycleOwner;
|
||||
@Mock
|
||||
TetheringManager mTetheringManager;
|
||||
@Mock
|
||||
TetheringManager.TetheringEventCallback mTetheringEventCallback;
|
||||
@Mock
|
||||
List<String> mInterfaces;
|
||||
|
||||
TetheringHelper mHelper;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mHelper = TetheringHelper.getInstance(mContext, mTetheringEventCallback, mLifecycle);
|
||||
mHelper.sTetheringManager = mTetheringManager;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void constructor_propertiesShouldBeReady() {
|
||||
assertThat(mHelper.sAppContext).isNotNull();
|
||||
assertThat(mHelper.sTetheringManager).isNotNull();
|
||||
assertThat(mHelper.mCallback).isNotNull();
|
||||
verify(mLifecycle).addObserver(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getTetheringManager_isNotNull() {
|
||||
assertThat(mHelper.getTetheringManager()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_eventCallbacksClear_addAndRegisterCallback() {
|
||||
mHelper.sEventCallbacks.clear();
|
||||
|
||||
mHelper.onStart(mLifecycleOwner);
|
||||
|
||||
assertThat(mHelper.sEventCallbacks.contains(mTetheringEventCallback)).isTrue();
|
||||
assertThat(mHelper.sEventCallbacks.size()).isEqualTo(1);
|
||||
verify(mTetheringManager).registerTetheringEventCallback(any(Executor.class),
|
||||
eq(TetheringHelper.sTetheringEventCallback));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStart_eventCallbacksContains_doNotRegisterCallback() {
|
||||
mHelper.sEventCallbacks.clear();
|
||||
mHelper.sEventCallbacks.add(mTetheringEventCallback);
|
||||
|
||||
mHelper.onStart(mLifecycleOwner);
|
||||
|
||||
verify(mTetheringManager, never()).registerTetheringEventCallback(any(Executor.class),
|
||||
eq(TetheringHelper.sTetheringEventCallback));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_eventCallbacksContains_removeAndUnregisterCallback() {
|
||||
mHelper.sEventCallbacks.clear();
|
||||
mHelper.sEventCallbacks.add(mTetheringEventCallback);
|
||||
|
||||
mHelper.onStop(mLifecycleOwner);
|
||||
|
||||
assertThat(mHelper.sEventCallbacks.contains(mTetheringEventCallback)).isFalse();
|
||||
assertThat(mHelper.sEventCallbacks.size()).isEqualTo(0);
|
||||
verify(mTetheringManager).unregisterTetheringEventCallback(
|
||||
eq(TetheringHelper.sTetheringEventCallback));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onStop_eventCallbacksClear_doNotUnregisterCallback() {
|
||||
mHelper.sEventCallbacks.clear();
|
||||
|
||||
mHelper.onStop(mLifecycleOwner);
|
||||
|
||||
assertThat(mHelper.sEventCallbacks.contains(mTetheringEventCallback)).isFalse();
|
||||
assertThat(mHelper.sEventCallbacks.size()).isEqualTo(0);
|
||||
verify(mTetheringManager, never()).unregisterTetheringEventCallback(
|
||||
eq(TetheringHelper.sTetheringEventCallback));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTetheredInterfacesChanged_eventCallbacksContains_doCallback() {
|
||||
mHelper.sEventCallbacks.clear();
|
||||
mHelper.sEventCallbacks.add(mTetheringEventCallback);
|
||||
|
||||
mHelper.sTetheringEventCallback.onTetheredInterfacesChanged(mInterfaces);
|
||||
|
||||
verify(mTetheringEventCallback).onTetheredInterfacesChanged(eq(mInterfaces));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void onTetheredInterfacesChanged_eventCallbacksClear_doNotCallback() {
|
||||
mHelper.sEventCallbacks.clear();
|
||||
|
||||
mHelper.sTetheringEventCallback.onTetheredInterfacesChanged(mInterfaces);
|
||||
|
||||
verify(mTetheringEventCallback, never()).onTetheredInterfacesChanged(eq(mInterfaces));
|
||||
}
|
||||
}
|
||||
@@ -43,6 +43,7 @@ import androidx.lifecycle.LifecycleOwner;
|
||||
import com.android.settings.R;
|
||||
import com.android.settingslib.RestrictedPreference;
|
||||
import com.android.settingslib.core.lifecycle.Lifecycle;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -119,8 +120,8 @@ public class PrintSettingsPreferenceControllerTest {
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.getSummary())
|
||||
.isEqualTo(mContext.getResources()
|
||||
.getQuantityString(R.plurals.print_jobs_summary, 1, 1));
|
||||
.isEqualTo(StringUtil.getIcuPluralsString(mContext, 1,
|
||||
R.string.print_jobs_summary));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -135,8 +136,8 @@ public class PrintSettingsPreferenceControllerTest {
|
||||
mController.updateState(mPreference);
|
||||
|
||||
assertThat(mPreference.getSummary())
|
||||
.isEqualTo(mContext.getResources()
|
||||
.getQuantityString(R.plurals.print_settings_summary, 2, 2));
|
||||
.isEqualTo(StringUtil.getIcuPluralsString(mContext, 2,
|
||||
R.string.print_settings_summary));
|
||||
|
||||
// No service
|
||||
when(mPrintManager.getPrintServices(PrintManager.ENABLED_SERVICES)).thenReturn(null);
|
||||
|
||||
@@ -80,6 +80,8 @@ public class WifiEntryPreferenceTest {
|
||||
private static final String MOCK_SUMMARY = "summary";
|
||||
private static final String FAKE_URI_STRING = "fakeuri";
|
||||
|
||||
WifiEntryPreference mPref;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mContext = RuntimeEnvironment.application;
|
||||
@@ -105,6 +107,8 @@ public class WifiEntryPreferenceTest {
|
||||
.thenReturn(mMockShowXDrawable3);
|
||||
when(mMockIconInjector.getIcon(true /* showX */, 4))
|
||||
.thenReturn(mMockShowXDrawable4);
|
||||
|
||||
mPref = new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -128,52 +132,46 @@ public class WifiEntryPreferenceTest {
|
||||
|
||||
@Test
|
||||
public void titleChanged_refresh_shouldUpdateTitle() {
|
||||
final WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
final String updatedTitle = "updated title";
|
||||
when(mMockWifiEntry.getTitle()).thenReturn(updatedTitle);
|
||||
|
||||
pref.refresh();
|
||||
mPref.refresh();
|
||||
|
||||
assertThat(pref.getTitle()).isEqualTo(updatedTitle);
|
||||
assertThat(mPref.getTitle().toString()).isEqualTo(updatedTitle);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void summaryChanged_refresh_shouldUpdateSummary() {
|
||||
final WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
final String updatedSummary = "updated summary";
|
||||
when(mMockWifiEntry.getSummary(false /* concise */)).thenReturn(updatedSummary);
|
||||
|
||||
pref.refresh();
|
||||
mPref.refresh();
|
||||
|
||||
assertThat(pref.getSummary()).isEqualTo(updatedSummary);
|
||||
assertThat(mPref.getSummary().toString()).isEqualTo(updatedSummary);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void levelChanged_refresh_shouldUpdateLevelIcon() {
|
||||
final List<Drawable> iconList = new ArrayList<>();
|
||||
final WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(0);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(1);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(2);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(3);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(4);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(-1);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
|
||||
assertThat(iconList).containsExactly(mMockDrawable0, mMockDrawable1,
|
||||
mMockDrawable2, mMockDrawable3, mMockDrawable4, null);
|
||||
@@ -183,27 +181,25 @@ public class WifiEntryPreferenceTest {
|
||||
public void levelChanged_showXWifiRefresh_shouldUpdateLevelIcon() {
|
||||
final List<Drawable> iconList = new ArrayList<>();
|
||||
when(mMockWifiEntry.shouldShowXLevelIcon()).thenReturn(true);
|
||||
final WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(0);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(1);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(2);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(3);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(4);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
when(mMockWifiEntry.getLevel()).thenReturn(-1);
|
||||
pref.refresh();
|
||||
iconList.add(pref.getIcon());
|
||||
mPref.refresh();
|
||||
iconList.add(mPref.getIcon());
|
||||
|
||||
assertThat(iconList).containsExactly(mMockShowXDrawable0, mMockShowXDrawable1,
|
||||
mMockShowXDrawable2, mMockShowXDrawable3, mMockShowXDrawable4, null);
|
||||
@@ -212,14 +208,12 @@ public class WifiEntryPreferenceTest {
|
||||
@Test
|
||||
public void notNull_whenGetHelpUriString_shouldSetImageButtonVisible() {
|
||||
when(mMockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
|
||||
final WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final View view = inflater.inflate(pref.getLayoutResource(), new LinearLayout(mContext),
|
||||
final View view = inflater.inflate(mPref.getLayoutResource(), new LinearLayout(mContext),
|
||||
false);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
|
||||
pref.onBindViewHolder(holder);
|
||||
mPref.onBindViewHolder(holder);
|
||||
|
||||
assertThat(view.findViewById(R.id.icon_button).getVisibility()).isEqualTo(View.VISIBLE);
|
||||
}
|
||||
@@ -227,14 +221,12 @@ public class WifiEntryPreferenceTest {
|
||||
@Test
|
||||
public void helpButton_whenGetHelpUriStringNotNull_shouldSetCorrectContentDescription() {
|
||||
when(mMockWifiEntry.getHelpUriString()).thenReturn(FAKE_URI_STRING);
|
||||
final WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final View view = inflater.inflate(pref.getLayoutResource(), new LinearLayout(mContext),
|
||||
final View view = inflater.inflate(mPref.getLayoutResource(), new LinearLayout(mContext),
|
||||
false);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
|
||||
pref.onBindViewHolder(holder);
|
||||
mPref.onBindViewHolder(holder);
|
||||
|
||||
assertThat(view.findViewById(R.id.icon_button).getContentDescription()).isEqualTo(
|
||||
mContext.getString(R.string.help_label));
|
||||
@@ -243,25 +235,25 @@ public class WifiEntryPreferenceTest {
|
||||
@Test
|
||||
public void subscriptionEntry_shouldSetImageButtonGone() {
|
||||
when(mMockWifiEntry.isSubscription()).thenReturn(true);
|
||||
final WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
final LayoutInflater inflater = LayoutInflater.from(mContext);
|
||||
final View view = inflater.inflate(pref.getLayoutResource(), new LinearLayout(mContext),
|
||||
final View view = inflater.inflate(mPref.getLayoutResource(), new LinearLayout(mContext),
|
||||
false);
|
||||
final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(view);
|
||||
|
||||
pref.onBindViewHolder(holder);
|
||||
mPref.onBindViewHolder(holder);
|
||||
|
||||
assertThat(view.findViewById(R.id.icon_button).getVisibility()).isEqualTo(View.GONE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void updateIcon_ShouldSetTintListForDrawable() {
|
||||
WifiEntryPreference pref =
|
||||
new WifiEntryPreference(mContext, mMockWifiEntry, mMockIconInjector);
|
||||
|
||||
pref.updateIcon(false /* showX */, 4 /* level */);
|
||||
public void updateIcon_shouldSetTintListForDrawable() {
|
||||
mPref.updateIcon(false /* showX */, 4 /* level */);
|
||||
|
||||
verify(mMockDrawable4).setTintList(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSecondTargetResId_shouldNotReturnZero() {
|
||||
assertThat(mPref.getSecondTargetResId()).isNotEqualTo(0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import com.android.settings.Settings;
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -244,11 +245,10 @@ public class CombinedBiometricStatusUtilsTest {
|
||||
public void getSummary_whenNoFaceEnrolled_whenMultipleFingerprints_returnsFingerprints() {
|
||||
final int enrolledFingerprintsCount = 2;
|
||||
final int stringResId = ResourcesUtils.getResourcesId(
|
||||
ApplicationProvider.getApplicationContext(), "plurals",
|
||||
ApplicationProvider.getApplicationContext(), "string",
|
||||
"security_settings_fingerprint_preference_summary");
|
||||
final String summary = mApplicationContext.getResources().getQuantityString(
|
||||
stringResId, enrolledFingerprintsCount /* quantity */,
|
||||
enrolledFingerprintsCount /* formatArgs */);
|
||||
final String summary = StringUtil.getIcuPluralsString(mApplicationContext,
|
||||
enrolledFingerprintsCount, stringResId);
|
||||
|
||||
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
|
||||
when(mFingerprintManager.getEnrolledFingerprints(anyInt()))
|
||||
@@ -261,11 +261,10 @@ public class CombinedBiometricStatusUtilsTest {
|
||||
public void getSummary_whenNoFaceEnrolled_whenSingleFingerprints_returnsFingerprints() {
|
||||
final int enrolledFingerprintsCount = 1;
|
||||
final int stringResId = ResourcesUtils.getResourcesId(
|
||||
ApplicationProvider.getApplicationContext(), "plurals",
|
||||
ApplicationProvider.getApplicationContext(), "string",
|
||||
"security_settings_fingerprint_preference_summary");
|
||||
final String summary = mApplicationContext.getResources().getQuantityString(
|
||||
stringResId, enrolledFingerprintsCount /* quantity */,
|
||||
enrolledFingerprintsCount /* formatArgs */);
|
||||
final String summary = StringUtil.getIcuPluralsString(mApplicationContext,
|
||||
enrolledFingerprintsCount, stringResId);
|
||||
|
||||
when(mFaceManager.hasEnrolledTemplates(anyInt())).thenReturn(false);
|
||||
when(mFingerprintManager.getEnrolledFingerprints(anyInt()))
|
||||
|
||||
@@ -37,6 +37,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
import com.android.settingslib.RestrictedLockUtils;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -165,11 +166,10 @@ public class FingerprintStatusUtilsTest {
|
||||
public void getSummary_whenEnrolled_returnsSummary() {
|
||||
final int enrolledFingerprintsCount = 2;
|
||||
final int stringResId = ResourcesUtils.getResourcesId(
|
||||
ApplicationProvider.getApplicationContext(), "plurals",
|
||||
ApplicationProvider.getApplicationContext(), "string",
|
||||
"security_settings_fingerprint_preference_summary");
|
||||
final String summary = mApplicationContext.getResources().getQuantityString(
|
||||
stringResId, enrolledFingerprintsCount /* quantity */,
|
||||
enrolledFingerprintsCount /* formatArgs */);
|
||||
final String summary = StringUtil.getIcuPluralsString(mApplicationContext,
|
||||
enrolledFingerprintsCount, stringResId);
|
||||
|
||||
when(mFingerprintManager.hasEnrolledFingerprints(anyInt())).thenReturn(true);
|
||||
when(mFingerprintManager.getEnrolledFingerprints(anyInt())).thenReturn(
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class CalendarTypeControllerTest {
|
||||
private Context mApplicationContext;
|
||||
private CalendarTypeController mController;
|
||||
private String mCacheProviderContent = "";
|
||||
private Locale mCacheLocale;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mApplicationContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new CalendarTypeController(mApplicationContext, "key");
|
||||
mCacheProviderContent = Settings.System.getString(
|
||||
mApplicationContext.getContentResolver(), Settings.System.LOCALE_PREFERENCES);
|
||||
mCacheLocale = Locale.getDefault(Locale.Category.FORMAT);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(
|
||||
mApplicationContext, mCacheProviderContent);
|
||||
Locale.setDefault(mCacheLocale);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_hasProviderValue_resultIsChinese() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(
|
||||
mApplicationContext, "und-u-ca-chinese");
|
||||
|
||||
CharSequence type = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.CalendarType.CHINESE, type.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_hasProviderValue_resultIsDangi() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(
|
||||
mApplicationContext, "und-u-ca-dangi");
|
||||
|
||||
CharSequence type = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.CalendarType.DANGI, type.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_noProviderValueButHasDefaultLocaleWithSubtag_resultIsSat() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "");
|
||||
Locale.setDefault(Locale.forLanguageTag("en-US-u-ca-chinese"));
|
||||
|
||||
CharSequence type = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.CalendarType.CHINESE, type.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_noProviderValueAndDefaultLocaleWithoutSubtag_resultIsEmpty() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "");
|
||||
Locale.setDefault(Locale.forLanguageTag("en-US"));
|
||||
|
||||
CharSequence type = mController.getSummary();
|
||||
|
||||
assertEquals(ResourcesUtils.getResourcesString(
|
||||
mApplicationContext, "default_string_of_regional_preference"), type.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class FirstDayOfWeekControllerTest {
|
||||
private Context mApplicationContext;
|
||||
private FirstDayOfWeekController mController;
|
||||
private String mCacheProviderContent = "";
|
||||
private Locale mCacheLocale;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mApplicationContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new FirstDayOfWeekController(mApplicationContext, "key");
|
||||
mCacheProviderContent = Settings.System.getString(
|
||||
mApplicationContext.getContentResolver(), Settings.System.LOCALE_PREFERENCES);
|
||||
mCacheLocale = Locale.getDefault(Locale.Category.FORMAT);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(
|
||||
mApplicationContext, mCacheProviderContent);
|
||||
Locale.setDefault(mCacheLocale);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_hasProviderValue_resultIsWed() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "und-u-fw-wed");
|
||||
|
||||
CharSequence day = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.FirstDayOfWeek.WEDNESDAY, day.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_hasProviderValue_resultIsSat() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "und-u-fw-sat");
|
||||
|
||||
CharSequence day = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.FirstDayOfWeek.SATURDAY, day.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_noProviderValueButHasDefaultLocaleWithSubtag_resultIsSat() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "");
|
||||
Locale.setDefault(Locale.forLanguageTag("en-US-u-fw-sat"));
|
||||
|
||||
CharSequence day = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.FirstDayOfWeek.SATURDAY, day.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_noProviderValueAndDefaultLocaleWithoutSubtag_resultIsEmpty() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "");
|
||||
Locale.setDefault(Locale.forLanguageTag("en-US"));
|
||||
|
||||
CharSequence day = mController.getSummary();
|
||||
|
||||
assertEquals(ResourcesUtils.getResourcesString(
|
||||
mApplicationContext, "default_string_of_regional_preference"), day.toString());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
/** Utils for each regional preference unit test. */
|
||||
public final class RegionalPreferenceUtils {
|
||||
/** Set language tag to Settings Provider */
|
||||
public static void setSettingsProviderContent(Context context, String languageTag) {
|
||||
Settings.System.putString(context.getContentResolver(),
|
||||
Settings.System.LOCALE_PREFERENCES, languageTag);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||
import static com.android.settings.core.BasePreferenceController.CONDITIONALLY_UNAVAILABLE;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.app.UiAutomation;
|
||||
import android.content.Context;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import androidx.test.InstrumentationRegistry;
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RegionalPreferencesControllerTest {
|
||||
private boolean mCacheProperty = false;
|
||||
private Context mApplicationContext;
|
||||
private RegionalPreferencesController mController;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mApplicationContext = ApplicationProvider.getApplicationContext();
|
||||
mCacheProperty =
|
||||
SystemProperties.getBoolean(RegionalPreferencesController.FEATURE_PROPERTY, false);
|
||||
mController = new RegionalPreferencesController(mApplicationContext, "key");
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
setProp(mCacheProperty);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_systemPropertyIstrue_available() throws Exception {
|
||||
setProp(true);
|
||||
|
||||
int result = mController.getAvailabilityStatus();
|
||||
|
||||
assertEquals(AVAILABLE, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getAvailabilityStatus_systemPropertyIstrue_unavailable() throws Exception {
|
||||
setProp(false);
|
||||
|
||||
int result = mController.getAvailabilityStatus();
|
||||
|
||||
assertEquals(CONDITIONALLY_UNAVAILABLE, result);
|
||||
}
|
||||
|
||||
private static void setProp(boolean isEnabled) throws Exception {
|
||||
UiAutomation uiAutomation = InstrumentationRegistry.getInstrumentation().getUiAutomation();
|
||||
uiAutomation.executeShellCommand(
|
||||
"setprop " + RegionalPreferencesController.FEATURE_PROPERTY + " " + isEnabled);
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
Thread.sleep(500);
|
||||
if (SystemProperties.getBoolean(
|
||||
RegionalPreferencesController.FEATURE_PROPERTY, false) == isEnabled) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.app.settings.SettingsEnums;
|
||||
import android.os.Looper;
|
||||
|
||||
import androidx.test.annotation.UiThreadTest;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class RegionalPreferencesEntriesFragmentTest {
|
||||
private RegionalPreferencesEntriesFragment mFragment;
|
||||
|
||||
@Before
|
||||
@UiThreadTest
|
||||
public void setUp() throws Exception {
|
||||
if (Looper.myLooper() == null) {
|
||||
Looper.prepare();
|
||||
}
|
||||
mFragment = new RegionalPreferencesEntriesFragment();
|
||||
}
|
||||
|
||||
@Test
|
||||
@UiThreadTest
|
||||
public void getMetricsCategory_returnRegionalPreference() {
|
||||
assertEquals(SettingsEnums.REGIONAL_PREFERENCE, mFragment.getMetricsCategory());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2022 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.regionalpreferences;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.Settings;
|
||||
|
||||
import androidx.test.core.app.ApplicationProvider;
|
||||
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
public class TemperatureUnitControllerTest {
|
||||
private Context mApplicationContext;
|
||||
private TemperatureUnitController mController;
|
||||
private String mCacheProviderContent = "";
|
||||
private Locale mCacheLocale;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
mApplicationContext = ApplicationProvider.getApplicationContext();
|
||||
mController = new TemperatureUnitController(mApplicationContext, "key");
|
||||
mCacheProviderContent = Settings.System.getString(
|
||||
mApplicationContext.getContentResolver(), Settings.System.LOCALE_PREFERENCES);
|
||||
mCacheLocale = Locale.getDefault(Locale.Category.FORMAT);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(
|
||||
mApplicationContext, mCacheProviderContent);
|
||||
Locale.setDefault(mCacheLocale);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_hasProviderValue_resultIsCelsius() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(
|
||||
mApplicationContext, "und-u-mu-celsius");
|
||||
|
||||
CharSequence unit = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.TemperatureUnit.CELSIUS, unit.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_hasProviderValue_resultIsFahrenheit() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(
|
||||
mApplicationContext, "und-u-mu-fahrenhe");
|
||||
|
||||
CharSequence unit = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.TemperatureUnit.FAHRENHEIT, unit.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_noProviderValueButHasDefaultLocaleWithSubtag_resultIsFahrenheit() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "");
|
||||
Locale.setDefault(Locale.forLanguageTag("en-US-u-mu-fahrenhe"));
|
||||
|
||||
CharSequence unit = mController.getSummary();
|
||||
|
||||
assertEquals(LocalePreferences.TemperatureUnit.FAHRENHEIT, unit.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getSummary_noProviderValueAndDefaultLocaleWithoutSubtag_resultIsEmpty() {
|
||||
RegionalPreferenceUtils.setSettingsProviderContent(mApplicationContext, "");
|
||||
Locale.setDefault(Locale.forLanguageTag("en-US"));
|
||||
|
||||
CharSequence unit = mController.getSummary();
|
||||
|
||||
assertEquals(ResourcesUtils.getResourcesString(
|
||||
mApplicationContext, "default_string_of_regional_preference"), unit.toString());
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,7 @@ import com.android.settings.Settings;
|
||||
import com.android.settings.biometrics.face.FaceEnrollIntroductionInternal;
|
||||
import com.android.settings.biometrics.fingerprint.FingerprintSettings;
|
||||
import com.android.settings.testutils.ResourcesUtils;
|
||||
import com.android.settingslib.utils.StringUtil;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
@@ -568,13 +569,12 @@ public class BiometricsSafetySourceTest {
|
||||
private void assertSafetySourceDisabledDataSetWithPluralSummary(String expectedTitleResName,
|
||||
String expectedSummaryResName, int expectedSummaryQuantity) {
|
||||
final int stringResId = ResourcesUtils.getResourcesId(
|
||||
ApplicationProvider.getApplicationContext(), "plurals",
|
||||
ApplicationProvider.getApplicationContext(), "string",
|
||||
expectedSummaryResName);
|
||||
assertSafetySourceDisabledDataSet(
|
||||
ResourcesUtils.getResourcesString(mApplicationContext, expectedTitleResName),
|
||||
mApplicationContext.getResources().getQuantityString(stringResId,
|
||||
expectedSummaryQuantity /* quantity */,
|
||||
expectedSummaryQuantity /* formatArgs */)
|
||||
StringUtil.getIcuPluralsString(mApplicationContext,
|
||||
expectedSummaryQuantity, stringResId)
|
||||
);
|
||||
}
|
||||
|
||||
@@ -582,13 +582,12 @@ public class BiometricsSafetySourceTest {
|
||||
String expectedSummaryResName, int expectedSummaryQuantity,
|
||||
String expectedSettingsClassName) {
|
||||
final int stringResId = ResourcesUtils.getResourcesId(
|
||||
ApplicationProvider.getApplicationContext(), "plurals",
|
||||
ApplicationProvider.getApplicationContext(), "string",
|
||||
expectedSummaryResName);
|
||||
assertSafetySourceEnabledDataSet(
|
||||
ResourcesUtils.getResourcesString(mApplicationContext, expectedTitleResName),
|
||||
mApplicationContext.getResources().getQuantityString(stringResId,
|
||||
expectedSummaryQuantity /* quantity */,
|
||||
expectedSummaryQuantity /* formatArgs */),
|
||||
StringUtil.getIcuPluralsString(mApplicationContext,
|
||||
expectedSummaryQuantity, stringResId),
|
||||
expectedSettingsClassName
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user