diff options
| author | 2018-09-11 21:19:48 +0000 | |
|---|---|---|
| committer | 2018-09-11 21:19:48 +0000 | |
| commit | 5789fa6b7308fc3860f638c50c52821bf28c46c5 (patch) | |
| tree | 2488137b35b041b96c9f7ff3640a2ee83308b05f | |
| parent | 48c882b4856df50697f6619b106f07d24ee93eca (diff) | |
| parent | 16703c4b4770648ac07d7efdc133a9de954480c1 (diff) | |
Merge "Prepare to make InputMethodUtils package-private"
7 files changed, 285 insertions, 282 deletions
diff --git a/core/java/android/view/inputmethod/InputMethodSubtype.java b/core/java/android/view/inputmethod/InputMethodSubtype.java index a7d7a8d67f64..61a697282dcb 100644 --- a/core/java/android/view/inputmethod/InputMethodSubtype.java +++ b/core/java/android/view/inputmethod/InputMethodSubtype.java @@ -28,7 +28,7 @@ import android.os.Parcelable; import android.text.TextUtils; import android.util.Slog; -import com.android.internal.inputmethod.InputMethodUtils; +import com.android.internal.inputmethod.LocaleUtils; import java.util.ArrayList; import java.util.Arrays; @@ -384,7 +384,7 @@ public final class InputMethodSubtype implements Parcelable { if (!TextUtils.isEmpty(mSubtypeLanguageTag)) { mCachedLocaleObj = Locale.forLanguageTag(mSubtypeLanguageTag); } else { - mCachedLocaleObj = InputMethodUtils.constructLocaleFromString(mSubtypeLocale); + mCachedLocaleObj = LocaleUtils.constructLocaleFromString(mSubtypeLocale); } return mCachedLocaleObj; } diff --git a/core/java/android/view/textservice/SpellCheckerSubtype.java b/core/java/android/view/textservice/SpellCheckerSubtype.java index 026610ecb6f9..41b70b61fd4a 100644 --- a/core/java/android/view/textservice/SpellCheckerSubtype.java +++ b/core/java/android/view/textservice/SpellCheckerSubtype.java @@ -25,7 +25,7 @@ import android.os.Parcelable; import android.text.TextUtils; import android.util.Slog; -import com.android.internal.inputmethod.InputMethodUtils; +import com.android.internal.inputmethod.LocaleUtils; import java.util.ArrayList; import java.util.Arrays; @@ -228,7 +228,7 @@ public final class SpellCheckerSubtype implements Parcelable { if (!TextUtils.isEmpty(mSubtypeLanguageTag)) { return Locale.forLanguageTag(mSubtypeLanguageTag); } - return InputMethodUtils.constructLocaleFromString(mSubtypeLocale); + return LocaleUtils.constructLocaleFromString(mSubtypeLocale); } /** diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java index 1e5b5c80f31b..1410ff9a0813 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java +++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java @@ -334,32 +334,6 @@ public class InputMethodUtils { return getDefaultEnabledImes(context, imis, false /* onlyMinimum */); } - public static Locale constructLocaleFromString(String localeStr) { - if (TextUtils.isEmpty(localeStr)) { - return null; - } - // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}. - String[] localeParams = localeStr.split("_", 3); - if (localeParams.length >= 1 && "tl".equals(localeParams[0])) { - // Convert a locale whose language is "tl" to one whose language is "fil". - // For example, "tl_PH" will get converted to "fil_PH". - // Versions of Android earlier than Lollipop did not support three letter language - // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino). - // On Lollipop and above, the current three letter version must be used. - localeParams[0] = "fil"; - } - // The length of localeStr is guaranteed to always return a 1 <= value <= 3 - // because localeStr is not empty. - if (localeParams.length == 1) { - return new Locale(localeParams[0]); - } else if (localeParams.length == 2) { - return new Locale(localeParams[0], localeParams[1]); - } else if (localeParams.length == 3) { - return new Locale(localeParams[0], localeParams[1], localeParams[2]); - } - return null; - } - public static boolean containsSubtypeOf(final InputMethodInfo imi, @Nullable final Locale locale, final boolean checkCountry, final String mode) { if (locale == null) { @@ -1320,133 +1294,7 @@ public class InputMethodUtils { } } - // For spell checker service manager. - // TODO: Should we have TextServicesUtils.java? - private static final Locale LOCALE_EN_US = new Locale("en", "US"); - private static final Locale LOCALE_EN_GB = new Locale("en", "GB"); - - /** - * Returns a list of {@link Locale} in the order of appropriateness for the default spell - * checker service. - * - * <p>If the system language is English, and the region is also explicitly specified in the - * system locale, the following fallback order will be applied.</p> - * <ul> - * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> - * <li>(system-locale-language, system-locale-region)</li> - * <li>("en", "US")</li> - * <li>("en", "GB")</li> - * <li>("en")</li> - * </ul> - * - * <p>If the system language is English, but no region is specified in the system locale, - * the following fallback order will be applied.</p> - * <ul> - * <li>("en")</li> - * <li>("en", "US")</li> - * <li>("en", "GB")</li> - * </ul> - * - * <p>If the system language is not English, the following fallback order will be applied.</p> - * <ul> - * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> - * <li>(system-locale-language, system-locale-region) (if exists)</li> - * <li>(system-locale-language) (if exists)</li> - * <li>("en", "US")</li> - * <li>("en", "GB")</li> - * <li>("en")</li> - * </ul> - * - * @param systemLocale the current system locale to be taken into consideration. - * @return a list of {@link Locale}. The first one is considered to be most appropriate. - */ @VisibleForTesting - public static ArrayList<Locale> getSuitableLocalesForSpellChecker( - @Nullable final Locale systemLocale) { - final Locale systemLocaleLanguageCountryVariant; - final Locale systemLocaleLanguageCountry; - final Locale systemLocaleLanguage; - if (systemLocale != null) { - final String language = systemLocale.getLanguage(); - final boolean hasLanguage = !TextUtils.isEmpty(language); - final String country = systemLocale.getCountry(); - final boolean hasCountry = !TextUtils.isEmpty(country); - final String variant = systemLocale.getVariant(); - final boolean hasVariant = !TextUtils.isEmpty(variant); - if (hasLanguage && hasCountry && hasVariant) { - systemLocaleLanguageCountryVariant = new Locale(language, country, variant); - } else { - systemLocaleLanguageCountryVariant = null; - } - if (hasLanguage && hasCountry) { - systemLocaleLanguageCountry = new Locale(language, country); - } else { - systemLocaleLanguageCountry = null; - } - if (hasLanguage) { - systemLocaleLanguage = new Locale(language); - } else { - systemLocaleLanguage = null; - } - } else { - systemLocaleLanguageCountryVariant = null; - systemLocaleLanguageCountry = null; - systemLocaleLanguage = null; - } - - final ArrayList<Locale> locales = new ArrayList<>(); - if (systemLocaleLanguageCountryVariant != null) { - locales.add(systemLocaleLanguageCountryVariant); - } - - if (Locale.ENGLISH.equals(systemLocaleLanguage)) { - if (systemLocaleLanguageCountry != null) { - // If the system language is English, and the region is also explicitly specified, - // following fallback order will be applied. - // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null] - // - en_US [if systemLocaleLanguageCountry is non-null and not en_US] - // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB] - // - en - if (systemLocaleLanguageCountry != null) { - locales.add(systemLocaleLanguageCountry); - } - if (!LOCALE_EN_US.equals(systemLocaleLanguageCountry)) { - locales.add(LOCALE_EN_US); - } - if (!LOCALE_EN_GB.equals(systemLocaleLanguageCountry)) { - locales.add(LOCALE_EN_GB); - } - locales.add(Locale.ENGLISH); - } else { - // If the system language is English, but no region is specified, following - // fallback order will be applied. - // - en - // - en_US - // - en_GB - locales.add(Locale.ENGLISH); - locales.add(LOCALE_EN_US); - locales.add(LOCALE_EN_GB); - } - } else { - // If the system language is not English, the fallback order will be - // - systemLocaleLanguageCountry [if non-null] - // - systemLocaleLanguage [if non-null] - // - en_US - // - en_GB - // - en - if (systemLocaleLanguageCountry != null) { - locales.add(systemLocaleLanguageCountry); - } - if (systemLocaleLanguage != null) { - locales.add(systemLocaleLanguage); - } - locales.add(LOCALE_EN_US); - locales.add(LOCALE_EN_GB); - locales.add(Locale.ENGLISH); - } - return locales; - } - public static boolean isSoftInputModeStateVisibleAllowed( int targetSdkVersion, int controlFlags) { if (targetSdkVersion < Build.VERSION_CODES.P) { @@ -1461,5 +1309,4 @@ public class InputMethodUtils { } return true; } - } diff --git a/core/java/com/android/internal/inputmethod/LocaleUtils.java b/core/java/com/android/internal/inputmethod/LocaleUtils.java index eeb3854bcc55..f7360eb0fe13 100644 --- a/core/java/com/android/internal/inputmethod/LocaleUtils.java +++ b/core/java/com/android/internal/inputmethod/LocaleUtils.java @@ -16,8 +16,6 @@ package com.android.internal.inputmethod; -import com.android.internal.annotations.VisibleForTesting; - import android.annotation.IntRange; import android.annotation.NonNull; import android.annotation.Nullable; @@ -25,6 +23,8 @@ import android.icu.util.ULocale; import android.os.LocaleList; import android.text.TextUtils; +import com.android.internal.annotations.VisibleForTesting; + import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -208,4 +208,151 @@ public final class LocaleUtils { dest.add(sources.get(entry.mIndex)); } } + + public static Locale constructLocaleFromString(String localeStr) { + if (TextUtils.isEmpty(localeStr)) { + return null; + } + // TODO: Use {@link Locale#toLanguageTag()} and {@link Locale#forLanguageTag(languageTag)}. + String[] localeParams = localeStr.split("_", 3); + if (localeParams.length >= 1 && "tl".equals(localeParams[0])) { + // Convert a locale whose language is "tl" to one whose language is "fil". + // For example, "tl_PH" will get converted to "fil_PH". + // Versions of Android earlier than Lollipop did not support three letter language + // codes, and used "tl" (Tagalog) as the language string for "fil" (Filipino). + // On Lollipop and above, the current three letter version must be used. + localeParams[0] = "fil"; + } + // The length of localeStr is guaranteed to always return a 1 <= value <= 3 + // because localeStr is not empty. + if (localeParams.length == 1) { + return new Locale(localeParams[0]); + } else if (localeParams.length == 2) { + return new Locale(localeParams[0], localeParams[1]); + } else if (localeParams.length == 3) { + return new Locale(localeParams[0], localeParams[1], localeParams[2]); + } + return null; + } + + /** + * Returns a list of {@link Locale} in the order of appropriateness for the default spell + * checker service. + * + * <p>If the system language is English, and the region is also explicitly specified in the + * system locale, the following fallback order will be applied.</p> + * <ul> + * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> + * <li>(system-locale-language, system-locale-region)</li> + * <li>("en", "US")</li> + * <li>("en", "GB")</li> + * <li>("en")</li> + * </ul> + * + * <p>If the system language is English, but no region is specified in the system locale, + * the following fallback order will be applied.</p> + * <ul> + * <li>("en")</li> + * <li>("en", "US")</li> + * <li>("en", "GB")</li> + * </ul> + * + * <p>If the system language is not English, the following fallback order will be applied.</p> + * <ul> + * <li>(system-locale-language, system-locale-region, system-locale-variant) (if exists)</li> + * <li>(system-locale-language, system-locale-region) (if exists)</li> + * <li>(system-locale-language) (if exists)</li> + * <li>("en", "US")</li> + * <li>("en", "GB")</li> + * <li>("en")</li> + * </ul> + * + * @param systemLocale the current system locale to be taken into consideration. + * @return a list of {@link Locale}. The first one is considered to be most appropriate. + */ + public static ArrayList<Locale> getSuitableLocalesForSpellChecker( + @Nullable final Locale systemLocale) { + final Locale systemLocaleLanguageCountryVariant; + final Locale systemLocaleLanguageCountry; + final Locale systemLocaleLanguage; + if (systemLocale != null) { + final String language = systemLocale.getLanguage(); + final boolean hasLanguage = !TextUtils.isEmpty(language); + final String country = systemLocale.getCountry(); + final boolean hasCountry = !TextUtils.isEmpty(country); + final String variant = systemLocale.getVariant(); + final boolean hasVariant = !TextUtils.isEmpty(variant); + if (hasLanguage && hasCountry && hasVariant) { + systemLocaleLanguageCountryVariant = new Locale(language, country, variant); + } else { + systemLocaleLanguageCountryVariant = null; + } + if (hasLanguage && hasCountry) { + systemLocaleLanguageCountry = new Locale(language, country); + } else { + systemLocaleLanguageCountry = null; + } + if (hasLanguage) { + systemLocaleLanguage = new Locale(language); + } else { + systemLocaleLanguage = null; + } + } else { + systemLocaleLanguageCountryVariant = null; + systemLocaleLanguageCountry = null; + systemLocaleLanguage = null; + } + + final ArrayList<Locale> locales = new ArrayList<>(); + if (systemLocaleLanguageCountryVariant != null) { + locales.add(systemLocaleLanguageCountryVariant); + } + + if (Locale.ENGLISH.equals(systemLocaleLanguage)) { + if (systemLocaleLanguageCountry != null) { + // If the system language is English, and the region is also explicitly specified, + // following fallback order will be applied. + // - systemLocaleLanguageCountry [if systemLocaleLanguageCountry is non-null] + // - en_US [if systemLocaleLanguageCountry is non-null and not en_US] + // - en_GB [if systemLocaleLanguageCountry is non-null and not en_GB] + // - en + if (systemLocaleLanguageCountry != null) { + locales.add(systemLocaleLanguageCountry); + } + if (!Locale.US.equals(systemLocaleLanguageCountry)) { + locales.add(Locale.US); + } + if (!Locale.UK.equals(systemLocaleLanguageCountry)) { + locales.add(Locale.UK); + } + locales.add(Locale.ENGLISH); + } else { + // If the system language is English, but no region is specified, following + // fallback order will be applied. + // - en + // - en_US + // - en_GB + locales.add(Locale.ENGLISH); + locales.add(Locale.US); + locales.add(Locale.UK); + } + } else { + // If the system language is not English, the fallback order will be + // - systemLocaleLanguageCountry [if non-null] + // - systemLocaleLanguage [if non-null] + // - en_US + // - en_GB + // - en + if (systemLocaleLanguageCountry != null) { + locales.add(systemLocaleLanguageCountry); + } + if (systemLocaleLanguage != null) { + locales.add(systemLocaleLanguage); + } + locales.add(Locale.US); + locales.add(Locale.UK); + locales.add(Locale.ENGLISH); + } + return locales; + } } diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java index 3064afaeaab1..f731a4affb87 100644 --- a/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java +++ b/core/tests/coretests/src/com/android/internal/inputmethod/InputMethodUtilsTest.java @@ -71,15 +71,11 @@ public class InputMethodUtilsTest { private static final Locale LOCALE_FR = new Locale("fr"); private static final Locale LOCALE_FR_CA = new Locale("fr", "CA"); private static final Locale LOCALE_HI = new Locale("hi"); - private static final Locale LOCALE_JA = new Locale("ja"); private static final Locale LOCALE_JA_JP = new Locale("ja", "JP"); private static final Locale LOCALE_ZH_CN = new Locale("zh", "CN"); private static final Locale LOCALE_ZH_TW = new Locale("zh", "TW"); private static final Locale LOCALE_IN = new Locale("in"); private static final Locale LOCALE_ID = new Locale("id"); - private static final Locale LOCALE_TH = new Locale("ht"); - private static final Locale LOCALE_TH_TH = new Locale("ht", "TH"); - private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH"); private static final String SUBTYPE_MODE_KEYBOARD = "keyboard"; private static final String SUBTYPE_MODE_VOICE = "voice"; private static final String SUBTYPE_MODE_HANDWRITING = "handwriting"; @@ -1087,122 +1083,6 @@ public class InputMethodUtilsTest { } @Test - public void testGetSuitableLocalesForSpellChecker() throws Exception { - { - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US); - assertEquals(3, locales.size()); - assertEquals(LOCALE_EN_US, locales.get(0)); - assertEquals(LOCALE_EN_GB, locales.get(1)); - assertEquals(LOCALE_EN, locales.get(2)); - } - - { - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB); - assertEquals(3, locales.size()); - assertEquals(LOCALE_EN_GB, locales.get(0)); - assertEquals(LOCALE_EN_US, locales.get(1)); - assertEquals(LOCALE_EN, locales.get(2)); - } - - { - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN); - assertEquals(3, locales.size()); - assertEquals(LOCALE_EN, locales.get(0)); - assertEquals(LOCALE_EN_US, locales.get(1)); - assertEquals(LOCALE_EN_GB, locales.get(2)); - } - - { - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN); - assertEquals(4, locales.size()); - assertEquals(LOCALE_EN_IN, locales.get(0)); - assertEquals(LOCALE_EN_US, locales.get(1)); - assertEquals(LOCALE_EN_GB, locales.get(2)); - assertEquals(LOCALE_EN, locales.get(3)); - } - - { - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP); - assertEquals(5, locales.size()); - assertEquals(LOCALE_JA_JP, locales.get(0)); - assertEquals(LOCALE_JA, locales.get(1)); - assertEquals(LOCALE_EN_US, locales.get(2)); - assertEquals(LOCALE_EN_GB, locales.get(3)); - assertEquals(Locale.ENGLISH, locales.get(4)); - } - - // Test 3-letter language code. - { - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH); - assertEquals(5, locales.size()); - assertEquals(LOCALE_FIL_PH, locales.get(0)); - assertEquals(LOCALE_FIL, locales.get(1)); - assertEquals(LOCALE_EN_US, locales.get(2)); - assertEquals(LOCALE_EN_GB, locales.get(3)); - assertEquals(Locale.ENGLISH, locales.get(4)); - } - - // Test variant. - { - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH); - assertEquals(6, locales.size()); - assertEquals(LOCALE_TH_TH_TH, locales.get(0)); - assertEquals(LOCALE_TH_TH, locales.get(1)); - assertEquals(LOCALE_TH, locales.get(2)); - assertEquals(LOCALE_EN_US, locales.get(3)); - assertEquals(LOCALE_EN_GB, locales.get(4)); - assertEquals(Locale.ENGLISH, locales.get(5)); - } - - // Test Locale extension. - { - final Locale localeWithoutVariant = LOCALE_JA_JP; - final Locale localeWithVariant = new Locale.Builder() - .setLocale(LOCALE_JA_JP) - .setExtension('x', "android") - .build(); - assertFalse(localeWithoutVariant.equals(localeWithVariant)); - - final ArrayList<Locale> locales = - InputMethodUtils.getSuitableLocalesForSpellChecker(localeWithVariant); - assertEquals(5, locales.size()); - assertEquals(LOCALE_JA_JP, locales.get(0)); - assertEquals(LOCALE_JA, locales.get(1)); - assertEquals(LOCALE_EN_US, locales.get(2)); - assertEquals(LOCALE_EN_GB, locales.get(3)); - assertEquals(Locale.ENGLISH, locales.get(4)); - } - } - - @Test - public void testConstructLocaleFromString() throws Exception { - assertEquals(new Locale("en"), InputMethodUtils.constructLocaleFromString("en")); - assertEquals(new Locale("en", "US"), InputMethodUtils.constructLocaleFromString("en_US")); - assertEquals(new Locale("en", "US", "POSIX"), - InputMethodUtils.constructLocaleFromString("en_US_POSIX")); - - // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not - // support three letter language codes, and used "tl" (Tagalog) as the language string for - // "fil" (Filipino). - assertEquals(new Locale("fil"), InputMethodUtils.constructLocaleFromString("tl")); - assertEquals(new Locale("fil", "PH"), InputMethodUtils.constructLocaleFromString("tl_PH")); - assertEquals(new Locale("fil", "PH", "POSIX"), - InputMethodUtils.constructLocaleFromString("tl_PH_POSIX")); - - // So far rejecting an invalid/unexpected locale string is out of the scope of this method. - assertEquals(new Locale("a"), InputMethodUtils.constructLocaleFromString("a")); - assertEquals(new Locale("a b c"), InputMethodUtils.constructLocaleFromString("a b c")); - assertEquals(new Locale("en-US"), InputMethodUtils.constructLocaleFromString("en-US")); - } - - @Test public void testIsSoftInputModeStateVisibleAllowed() { // On pre-P devices, SOFT_INPUT_STATE_VISIBLE/SOFT_INPUT_STATE_ALWAYS_VISIBLE are always // allowed, regardless of the focused view state. diff --git a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java index 549511a420eb..7d0e646181c0 100644 --- a/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java +++ b/core/tests/coretests/src/com/android/internal/inputmethod/LocaleUtilsTest.java @@ -17,6 +17,7 @@ package com.android.internal.inputmethod; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import android.os.LocaleList; import android.support.test.filters.SmallTest; @@ -34,6 +35,18 @@ public class LocaleUtilsTest { private static final LocaleUtils.LocaleExtractor<Locale> sIdentityMapper = source -> source; + private static final Locale LOCALE_EN = new Locale("en"); + private static final Locale LOCALE_EN_US = new Locale("en", "US"); + private static final Locale LOCALE_EN_GB = new Locale("en", "GB"); + private static final Locale LOCALE_EN_IN = new Locale("en", "IN"); + private static final Locale LOCALE_FIL = new Locale("fil"); + private static final Locale LOCALE_FIL_PH = new Locale("fil", "PH"); + private static final Locale LOCALE_JA = new Locale("ja"); + private static final Locale LOCALE_JA_JP = new Locale("ja", "JP"); + private static final Locale LOCALE_TH = new Locale("ht"); + private static final Locale LOCALE_TH_TH = new Locale("ht", "TH"); + private static final Locale LOCALE_TH_TH_TH = new Locale("ht", "TH", "TH"); + @Test public void testFilterByLanguageEmptyLanguageList() throws Exception { final ArrayList<Locale> availableLocales = new ArrayList<>(); @@ -385,4 +398,120 @@ public class LocaleUtilsTest { assertEquals(availableLocales.get(3), dest.get(0)); } } + + @Test + public void testGetSuitableLocalesForSpellChecker() throws Exception { + { + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_US); + assertEquals(3, locales.size()); + assertEquals(LOCALE_EN_US, locales.get(0)); + assertEquals(LOCALE_EN_GB, locales.get(1)); + assertEquals(LOCALE_EN, locales.get(2)); + } + + { + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_GB); + assertEquals(3, locales.size()); + assertEquals(LOCALE_EN_GB, locales.get(0)); + assertEquals(LOCALE_EN_US, locales.get(1)); + assertEquals(LOCALE_EN, locales.get(2)); + } + + { + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN); + assertEquals(3, locales.size()); + assertEquals(LOCALE_EN, locales.get(0)); + assertEquals(LOCALE_EN_US, locales.get(1)); + assertEquals(LOCALE_EN_GB, locales.get(2)); + } + + { + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_EN_IN); + assertEquals(4, locales.size()); + assertEquals(LOCALE_EN_IN, locales.get(0)); + assertEquals(LOCALE_EN_US, locales.get(1)); + assertEquals(LOCALE_EN_GB, locales.get(2)); + assertEquals(LOCALE_EN, locales.get(3)); + } + + { + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_JA_JP); + assertEquals(5, locales.size()); + assertEquals(LOCALE_JA_JP, locales.get(0)); + assertEquals(LOCALE_JA, locales.get(1)); + assertEquals(LOCALE_EN_US, locales.get(2)); + assertEquals(LOCALE_EN_GB, locales.get(3)); + assertEquals(Locale.ENGLISH, locales.get(4)); + } + + // Test 3-letter language code. + { + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_FIL_PH); + assertEquals(5, locales.size()); + assertEquals(LOCALE_FIL_PH, locales.get(0)); + assertEquals(LOCALE_FIL, locales.get(1)); + assertEquals(LOCALE_EN_US, locales.get(2)); + assertEquals(LOCALE_EN_GB, locales.get(3)); + assertEquals(Locale.ENGLISH, locales.get(4)); + } + + // Test variant. + { + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(LOCALE_TH_TH_TH); + assertEquals(6, locales.size()); + assertEquals(LOCALE_TH_TH_TH, locales.get(0)); + assertEquals(LOCALE_TH_TH, locales.get(1)); + assertEquals(LOCALE_TH, locales.get(2)); + assertEquals(LOCALE_EN_US, locales.get(3)); + assertEquals(LOCALE_EN_GB, locales.get(4)); + assertEquals(Locale.ENGLISH, locales.get(5)); + } + + // Test Locale extension. + { + final Locale localeWithoutVariant = LOCALE_JA_JP; + final Locale localeWithVariant = new Locale.Builder() + .setLocale(LOCALE_JA_JP) + .setExtension('x', "android") + .build(); + assertFalse(localeWithoutVariant.equals(localeWithVariant)); + + final ArrayList<Locale> locales = + LocaleUtils.getSuitableLocalesForSpellChecker(localeWithVariant); + assertEquals(5, locales.size()); + assertEquals(LOCALE_JA_JP, locales.get(0)); + assertEquals(LOCALE_JA, locales.get(1)); + assertEquals(LOCALE_EN_US, locales.get(2)); + assertEquals(LOCALE_EN_GB, locales.get(3)); + assertEquals(Locale.ENGLISH, locales.get(4)); + } + } + + @Test + public void testConstructLocaleFromString() throws Exception { + assertEquals(new Locale("en"), LocaleUtils.constructLocaleFromString("en")); + assertEquals(new Locale("en", "US"), LocaleUtils.constructLocaleFromString("en_US")); + assertEquals(new Locale("en", "US", "POSIX"), + LocaleUtils.constructLocaleFromString("en_US_POSIX")); + + // Special rewrite rule for "tl" for versions of Android earlier than Lollipop that did not + // support three letter language codes, and used "tl" (Tagalog) as the language string for + // "fil" (Filipino). + assertEquals(new Locale("fil"), LocaleUtils.constructLocaleFromString("tl")); + assertEquals(new Locale("fil", "PH"), LocaleUtils.constructLocaleFromString("tl_PH")); + assertEquals(new Locale("fil", "PH", "POSIX"), + LocaleUtils.constructLocaleFromString("tl_PH_POSIX")); + + // So far rejecting an invalid/unexpected locale string is out of the scope of this method. + assertEquals(new Locale("a"), LocaleUtils.constructLocaleFromString("a")); + assertEquals(new Locale("a b c"), LocaleUtils.constructLocaleFromString("a b c")); + assertEquals(new Locale("en-US"), LocaleUtils.constructLocaleFromString("en-US")); + } } diff --git a/services/core/java/com/android/server/TextServicesManagerService.java b/services/core/java/com/android/server/TextServicesManagerService.java index 40f81b3c2850..708350d6f174 100644 --- a/services/core/java/com/android/server/TextServicesManagerService.java +++ b/services/core/java/com/android/server/TextServicesManagerService.java @@ -20,7 +20,7 @@ import static android.view.textservice.TextServicesManager.DISABLE_PER_PROFILE_S import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; -import com.android.internal.inputmethod.InputMethodUtils; +import com.android.internal.inputmethod.LocaleUtils; import com.android.internal.textservice.ISpellCheckerService; import com.android.internal.textservice.ISpellCheckerServiceCallback; import com.android.internal.textservice.ISpellCheckerSession; @@ -461,7 +461,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { // is pre-installed or not. final Locale systemLocal = mContext.getResources().getConfiguration().locale; final ArrayList<Locale> suitableLocales = - InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal); + LocaleUtils.getSuitableLocalesForSpellChecker(systemLocal); if (DBG) { Slog.w(TAG, "findAvailSystemSpellCheckerLocked suitableLocales=" + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()]))); @@ -475,7 +475,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { final int subtypeCount = info.getSubtypeCount(); for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) { final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex); - final Locale subtypeLocale = InputMethodUtils.constructLocaleFromString( + final Locale subtypeLocale = LocaleUtils.constructLocaleFromString( subtype.getLocale()); if (locale.equals(subtypeLocale)) { // TODO: We may have more spell checkers that fall into this category. |