diff options
| -rw-r--r-- | packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java | 77 | ||||
| -rw-r--r-- | packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java | 32 |
2 files changed, 103 insertions, 6 deletions
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java index 6d375ac215a4..48259e165670 100644 --- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java +++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java @@ -46,12 +46,16 @@ import com.android.settingslib.devicestate.DeviceStateRotationLockSettingsManage import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; +import java.util.Set; public class SettingsHelper { private static final String TAG = "SettingsHelper"; private static final String SILENT_RINGTONE = "_silent"; private static final String SETTINGS_REPLACED_KEY = "backup_skip_user_facing_data"; private static final String SETTING_ORIGINAL_KEY_SUFFIX = "_original"; + private static final String UNICODE_LOCALE_EXTENSION_FW = "fw"; + private static final String UNICODE_LOCALE_EXTENSION_MU = "mu"; + private static final String UNICODE_LOCALE_EXTENSION_NU = "nu"; private static final float FLOAT_TOLERANCE = 0.01f; /** See frameworks/base/core/res/res/values/config.xml#config_longPressOnPowerBehavior **/ @@ -97,6 +101,25 @@ public class SettingsHelper { sBroadcastOnRestoreSystemUI.add(Settings.Secure.QS_AUTO_ADDED_TILES); } + private static final ArraySet<String> UNICODE_LOCALE_SUPPORTED_EXTENSIONS = new ArraySet<>(); + + /** + * Current supported extensions are fw (first day of week) and mu (temperature unit) extension. + * User can set these extensions in Settings app, and it will be appended to the locale, + * for example: zh-Hant-TW-u-fw-mon-mu-celsius. So after the factory reset, these extensions + * should be restored as well because they are set by users. + * We do not put the nu (numbering system) extension here because it is an Android supported + * extension and defined in some particular locales, for example: + * ar-Arab-MA-u-nu-arab and ar-Arab-YE-u-nu-latn. See + * <code>frameworks/base/core/res/res/values/locale_config.xml</code> + * The nu extension should not be appended to the current/restored locale after factory reset + * if the current/restored locale does not have it. + */ + static { + UNICODE_LOCALE_SUPPORTED_EXTENSIONS.add(UNICODE_LOCALE_EXTENSION_FW); + UNICODE_LOCALE_SUPPORTED_EXTENSIONS.add(UNICODE_LOCALE_EXTENSION_MU); + } + private interface SettingsLookup { public String lookup(ContentResolver resolver, String name, int userHandle); } @@ -500,20 +523,25 @@ public class SettingsHelper { allLocales.put(toFullLocale(locale), locale); } + // After restoring to reset locales, need to get extensions from restored locale. Get the + // first restored locale to check its extension. + final Locale restoredLocale = restore.isEmpty() + ? Locale.ROOT + : restore.get(0); final ArrayList<Locale> filtered = new ArrayList<>(current.size()); for (int i = 0; i < current.size(); i++) { - final Locale locale = current.get(i); + Locale locale = copyExtensionToTargetLocale(restoredLocale, current.get(i)); allLocales.remove(toFullLocale(locale)); filtered.add(locale); } for (int i = 0; i < restore.size(); i++) { - final Locale locale = allLocales.remove(toFullLocale(restore.get(i))); - if (locale != null) { - filtered.add(locale); + final Locale restoredLocaleWithExtension = copyExtensionToTargetLocale(restoredLocale, + getFilteredLocale(restore.get(i), allLocales)); + if (restoredLocaleWithExtension != null) { + filtered.add(restoredLocaleWithExtension); } } - if (filtered.size() == current.size()) { return current; // Nothing added to current locale list. } @@ -521,6 +549,45 @@ public class SettingsHelper { return new LocaleList(filtered.toArray(new Locale[filtered.size()])); } + private static Locale copyExtensionToTargetLocale(Locale restoredLocale, + Locale targetLocale) { + if (!restoredLocale.hasExtensions()) { + return targetLocale; + } + + if (targetLocale == null) { + return null; + } + + Locale.Builder builder = new Locale.Builder() + .setLocale(targetLocale); + Set<String> unicodeLocaleKeys = restoredLocale.getUnicodeLocaleKeys(); + unicodeLocaleKeys.stream().forEach(key -> { + // Copy all supported extensions from restored locales except "nu" extension. The "nu" + // extension has been added in #getFilteredLocale(Locale, HashMap<Locale, Locale>) + // already, we don't need to add it again. + if (UNICODE_LOCALE_SUPPORTED_EXTENSIONS.contains(key)) { + builder.setUnicodeLocaleKeyword(key, restoredLocale.getUnicodeLocaleType(key)); + } + }); + return builder.build(); + } + + private static Locale getFilteredLocale(Locale restoreLocale, + HashMap<Locale, Locale> allLocales) { + Locale locale = allLocales.remove(toFullLocale(restoreLocale)); + if (locale != null) { + return locale; + } + + Locale filteredLocale = new Locale.Builder() + .setLocale(restoreLocale.stripExtensions()) + .setUnicodeLocaleKeyword(UNICODE_LOCALE_EXTENSION_NU, + restoreLocale.getUnicodeLocaleType(UNICODE_LOCALE_EXTENSION_NU)) + .build(); + return allLocales.remove(toFullLocale(filteredLocale)); + } + /** * Sets the locale specified. Input data is the byte representation of comma separated * multiple BCP-47 language tags. For backwards compatibility, strings of the form diff --git a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java index ee76dbf8ce70..bc81c4441af5 100644 --- a/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java +++ b/packages/SettingsProvider/test/src/com/android/providers/settings/SettingsHelperTest.java @@ -299,12 +299,42 @@ public class SettingsHelperTest { LocaleList.forLanguageTags("en-US"), // current new String[] { "en-US", "zh-Hans-CN" })); // supported - // Old langauge code should be updated. + // Old language code should be updated. assertEquals(LocaleList.forLanguageTags("en-US,he-IL,id-ID,yi"), SettingsHelper.resolveLocales( LocaleList.forLanguageTags("iw-IL,in-ID,ji"), // restore LocaleList.forLanguageTags("en-US"), // current new String[] { "he-IL", "id-ID", "yi" })); // supported + + // No matter the current locale has "nu" extension or not, if the restored locale has fw + // (first day of week) or mu(temperature unit) extension, we should restore fw or mu + // extensions as well and append these to restore and current locales. + assertEquals(LocaleList.forLanguageTags( + "en-US-u-fw-mon-mu-celsius,zh-Hant-TW-u-fw-mon-mu-celsius"), + SettingsHelper.resolveLocales( + LocaleList.forLanguageTags("zh-Hant-TW-u-fw-mon-mu-celsius"), // restore + LocaleList.forLanguageTags("en-US"), // current + new String[] { "en-US", "zh-Hant-TW" })); // supported + + // No matter the current locale has "nu" extension or not, if the restored locale has fw + // (first day of week) or mu(temperature unit) extension, we should restore fw or mu + // extensions as well and append these to restore and current locales. + assertEquals(LocaleList.forLanguageTags( + "fa-Arab-AF-u-nu-latn-fw-mon-mu-celsius,zh-Hant-TW-u-fw-mon-mu-celsius"), + SettingsHelper.resolveLocales( + LocaleList.forLanguageTags("zh-Hant-TW-u-fw-mon-mu-celsius"), // restore + LocaleList.forLanguageTags("fa-Arab-AF-u-nu-latn"), // current + new String[] { "fa-Arab-AF-u-nu-latn", "zh-Hant-TW" })); // supported + + // If the restored locale only has nu extension, we should not restore the nu extensions to + // current locales. + assertEquals(LocaleList.forLanguageTags("zh-Hant-TW,fa-Arab-AF-u-nu-latn"), + SettingsHelper.resolveLocales( + LocaleList.forLanguageTags("fa-Arab-AF-u-nu-latn"), // restore + LocaleList.forLanguageTags("zh-Hant-TW"), // current + new String[] { "fa-Arab-AF-u-nu-latn", "zh-Hant-TW" })); // supported + + } @Test |