Snap for 9446745 from 2451afc0df to udc-release

Change-Id: Ib1306a9668829d0d306962b8282576fbc4b5e2f7
This commit is contained in:
Android Build Coastguard Worker
2022-12-31 06:38:02 +00:00
53 changed files with 2105 additions and 305 deletions

View File

@@ -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>

View File

@@ -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

View 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>

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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(){}

View File

@@ -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);
}
}

View File

@@ -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 "";
}

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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.

View File

@@ -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));
}
}
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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) {

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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);

View 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);
}
}
}
}

View File

@@ -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) {

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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() {
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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,
)
}
}

View File

@@ -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) {

View File

@@ -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());
}
}

View File

@@ -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");
}

View File

@@ -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();
}

View File

@@ -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();

View File

@@ -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

View File

@@ -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));
}
}

View File

@@ -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));
}
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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()))

View File

@@ -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(

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}
}
}

View File

@@ -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());
}
}

View File

@@ -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());
}
}

View File

@@ -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
);
}