[Regional Preference] Add each option entry

- Add a entry in langauge and input page
 - Add new page for the options of Temperature unit, calendar type,
   first day of week, and numbering system.

Bug: b/246929960
Test: atest pass
Test: Manual test pass
Change-Id: I69377fe9cd6dcd7a27c933a8dc98483df3da7665
This commit is contained in:
tom hsu
2022-12-19 20:05:44 +08:00
parent 58c3318e19
commit 504a5dda43
16 changed files with 1500 additions and 0 deletions

View File

@@ -354,6 +354,24 @@
<!-- Description for introduction of the locale selection supported of app list [CHAR LIMIT=NONE]--> <!-- 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> <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] --> <!-- 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, <string name="dlg_remove_locales_title">{count, plural,
=1 {Remove selected language?} =1 {Remove selected language?}

View File

@@ -38,6 +38,15 @@
android:name="classname" android:name="classname"
android:value="com.android.settings.applications.appinfo.AppLocaleDetails" /> android:value="com.android.settings.applications.appinfo.AppLocaleDetails" />
</Preference> </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>
<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

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

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