| /* |
| * Copyright (C) 2023 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 android.content.Context; |
| import android.icu.text.NumberingSystem; |
| import android.icu.util.ULocale; |
| import android.os.Bundle; |
| import android.os.LocaleList; |
| import android.text.TextUtils; |
| import android.util.Log; |
| |
| import androidx.preference.Preference; |
| import androidx.preference.PreferenceScreen; |
| |
| import com.android.internal.app.LocaleHelper; |
| import com.android.internal.app.LocalePicker; |
| import com.android.internal.app.LocaleStore; |
| import com.android.settings.core.BasePreferenceController; |
| import com.android.settings.core.SubSettingLauncher; |
| import com.android.settings.dashboard.DashboardFragment; |
| import com.android.settings.overlay.FeatureFactory; |
| import com.android.settings.widget.TickButtonPreference; |
| import com.android.settingslib.core.instrumentation.MetricsFeatureProvider; |
| |
| import java.util.Locale; |
| |
| /** Uses to control the preference UI of numbering system page. */ |
| public class NumberingSystemItemController extends BasePreferenceController { |
| private static final String TAG = NumberingSystemItemController.class.getSimpleName(); |
| private static final String DISPLAY_KEYWORD_NUMBERING_SYSTEM = "numbers"; |
| |
| static final String ARG_VALUE_NUMBERING_SYSTEM_SELECT = "arg_value_numbering_system_select"; |
| static final String ARG_VALUE_LANGUAGE_SELECT = "arg_value_language_select"; |
| static final String KEY_SELECTED_LANGUAGE = "key_selected_language"; |
| |
| private final MetricsFeatureProvider mMetricsFeatureProvider; |
| |
| private String mOption = ""; |
| private String mSelectedLanguage = ""; |
| private DashboardFragment mParentFragment; |
| private PreferenceScreen mPreferenceScreen; |
| |
| public NumberingSystemItemController(Context context, Bundle argument) { |
| super(context, "no_key"); |
| // Initialize the supported languages to LocaleInfos |
| LocaleStore.fillCache(context); |
| mOption = argument.getString( |
| RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE, ""); |
| mSelectedLanguage = argument.getString( |
| NumberingSystemItemController.KEY_SELECTED_LANGUAGE, ""); |
| mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider(); |
| } |
| |
| /** |
| * Displays preference in this controller. |
| */ |
| @Override |
| public void displayPreference(PreferenceScreen screen) { |
| super.displayPreference(screen); |
| mPreferenceScreen = screen; |
| if (mOption.equals(ARG_VALUE_LANGUAGE_SELECT)) { |
| initLanguageOptionsUi(screen); |
| } else if (mOption.equals(ARG_VALUE_NUMBERING_SYSTEM_SELECT)) { |
| initNumberingSystemOptionsUi(screen, Locale.forLanguageTag(mSelectedLanguage)); |
| } |
| } |
| |
| /** |
| * Sets the parent fragment and attaches this controller to the settings lifecycle. |
| * |
| * @param fragment the fragment to use as the parent |
| */ |
| public void setParentFragment(DashboardFragment fragment) { |
| mParentFragment = fragment; |
| } |
| |
| /** |
| * @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 boolean handlePreferenceTreeClick(Preference preference) { |
| if (mOption.equals(ARG_VALUE_LANGUAGE_SELECT)) { |
| handleLanguageSelect(preference); |
| } else if (mOption.equals(ARG_VALUE_NUMBERING_SYSTEM_SELECT)) { |
| handleNumberSystemSelect(preference); |
| } |
| return true; |
| } |
| |
| private void initLanguageOptionsUi(PreferenceScreen screen) { |
| // Get current system language list to show on screen. |
| LocaleList localeList = LocaleList.getDefault(); |
| for (int i = 0; i < localeList.size(); i++) { |
| Locale locale = localeList.get(i); |
| LocaleStore.LocaleInfo localeInfo = LocaleStore.getLocaleInfo(locale); |
| if (!localeInfo.hasNumberingSystems()) { |
| continue; |
| } |
| Preference pref = new Preference(mContext); |
| pref.setTitle(LocaleHelper.getDisplayName(locale.stripExtensions(), locale, true)); |
| pref.setKey(locale.toLanguageTag()); |
| pref.setSummary(getNumberingSystem(locale)); |
| screen.addPreference(pref); |
| } |
| } |
| |
| private void initNumberingSystemOptionsUi(PreferenceScreen screen, Locale targetLocale) { |
| String[] locales = LocalePicker.getSupportedLocales(mContext); |
| for (String localeTag : locales) { |
| Locale supportedLocale = Locale.forLanguageTag(localeTag); |
| if (isSameBaseLocale(targetLocale, supportedLocale)) { |
| TickButtonPreference pref = new TickButtonPreference(mContext); |
| String numberingName = getNumberingSystem(supportedLocale); |
| pref.setTitle(numberingName); |
| String key = supportedLocale.getUnicodeLocaleType( |
| ExtensionTypes.NUMBERING_SYSTEM); |
| pref.setKey(key == null ? RegionalPreferencesDataUtils.DEFAULT_VALUE : key); |
| pref.setSelected(isSameNumberingSystem(targetLocale, supportedLocale)); |
| screen.addPreference(pref); |
| } |
| } |
| } |
| |
| private void handleLanguageSelect(Preference preference) { |
| String selectedLanguage = preference.getKey(); |
| mMetricsFeatureProvider.action(mContext, |
| SettingsEnums.ACTION_CHOOSE_LANGUAGE_FOR_NUMBERS_PREFERENCES); |
| final Bundle extra = new Bundle(); |
| extra.putString(RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE, |
| ARG_VALUE_NUMBERING_SYSTEM_SELECT); |
| extra.putString(KEY_SELECTED_LANGUAGE, selectedLanguage); |
| new SubSettingLauncher(preference.getContext()) |
| .setDestination(NumberingPreferencesFragment.class.getName()) |
| .setSourceMetricsCategory( |
| SettingsEnums.NUMBERING_SYSTEM_LANGUAGE_SELECTION_PREFERENCE) |
| .setArguments(extra) |
| .launch(); |
| } |
| |
| private void handleNumberSystemSelect(Preference preference) { |
| for (int i = 0; i < mPreferenceScreen.getPreferenceCount(); i++) { |
| TickButtonPreference pref = (TickButtonPreference) mPreferenceScreen.getPreference(i); |
| Log.i(TAG, "[onPreferenceClick] key is " + pref.getKey()); |
| if (pref.getKey().equals(preference.getKey())) { |
| String numberingSystem = pref.getKey(); |
| pref.setSelected(true); |
| Locale updatedLocale = |
| saveNumberingSystemToLocale(Locale.forLanguageTag(mSelectedLanguage), |
| numberingSystem); |
| mMetricsFeatureProvider.action(mContext, |
| SettingsEnums.ACTION_SET_NUMBERS_PREFERENCES); |
| // After updated locale to framework, this fragment will recreate, |
| // so it needs to update the argument of selected language. |
| Bundle bundle = new Bundle(); |
| bundle.putString(RegionalPreferencesEntriesFragment.ARG_KEY_REGIONAL_PREFERENCE, |
| ARG_VALUE_NUMBERING_SYSTEM_SELECT); |
| bundle.putString(KEY_SELECTED_LANGUAGE, |
| updatedLocale != null ? updatedLocale.toLanguageTag() : ""); |
| mParentFragment.setArguments(bundle); |
| continue; |
| } |
| pref.setSelected(false); |
| } |
| } |
| |
| private Locale saveNumberingSystemToLocale(Locale targetLocale, String value) { |
| LocaleList localeList = LocalePicker.getLocales(); |
| Locale[] locales = new Locale[localeList.size()]; |
| Locale updatedLocale = null; |
| for (int i = 0; i < localeList.size(); i++) { |
| Locale locale = localeList.get(i); |
| if (targetLocale.equals(locale)) { |
| if (RegionalPreferencesDataUtils.DEFAULT_VALUE.equals(value)) { |
| value = null; |
| } |
| updatedLocale = new Locale.Builder() |
| .setLocale(locale) |
| .setUnicodeLocaleKeyword(ExtensionTypes.NUMBERING_SYSTEM, value) |
| .build(); |
| locales[i] = updatedLocale; |
| continue; |
| } |
| locales[i] = localeList.get(i); |
| } |
| LocalePicker.updateLocales(new LocaleList(locales)); |
| return updatedLocale; |
| } |
| |
| private static String getNumberingSystem(Locale locale) { |
| ULocale uLocale = new ULocale.Builder() |
| .setUnicodeLocaleKeyword(ExtensionTypes.NUMBERING_SYSTEM, |
| NumberingSystem.getInstance(locale).getName()) |
| .build(); |
| return uLocale.getDisplayKeywordValue(DISPLAY_KEYWORD_NUMBERING_SYSTEM, |
| ULocale.forLocale(locale)); |
| } |
| |
| private static boolean isSameNumberingSystem(Locale locale1, Locale locale2) { |
| String name1 = NumberingSystem.getInstance(locale1).getName(); |
| String name2 = NumberingSystem.getInstance(locale2).getName(); |
| return TextUtils.equals(name1, name2); |
| } |
| |
| private static boolean isSameBaseLocale(Locale locale1, Locale locale2) { |
| return locale1.stripExtensions().equals(locale2.stripExtensions()); |
| } |
| } |