diff options
| author | 2018-09-15 16:40:23 +0000 | |
|---|---|---|
| committer | 2018-09-15 16:40:23 +0000 | |
| commit | ef25beb18ab7edd4090ebae1a6fe0d06bcbdf0c9 (patch) | |
| tree | bb9180c71c589c5ad73c03d8baa41a9eb66df25a | |
| parent | 7e84efb275af4e61fe667f0348b0c9cde0314ccd (diff) | |
| parent | 3781ca8c64bf5e912f3ecefcc6b423fe47c670d0 (diff) | |
Merge "Extract getSuitableLocalesForSpellChecker()"
5 files changed, 287 insertions, 227 deletions
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java index 1e5b5c80f31b..fe6706590abb 100644 --- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java +++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java @@ -1320,133 +1320,6 @@ 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) { 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..4dd5fcb5d2cc 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,101 +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")); diff --git a/services/core/java/com/android/server/textservices/LocaleUtils.java b/services/core/java/com/android/server/textservices/LocaleUtils.java new file mode 100644 index 000000000000..89d8c1e96614 --- /dev/null +++ b/services/core/java/com/android/server/textservices/LocaleUtils.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2018 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.server.textservices; + +import android.annotation.Nullable; +import android.text.TextUtils; + +import java.util.ArrayList; +import java.util.Locale; + +/** + * Provides {@code Locale} related utility methods for {@link TextServicesManagerService}. + * <p>This class is intentionally package-private. Utility methods here are tightly coupled with + * implementation details in {@link TextServicesManagerService}. Hence this class is not suitable + * for other components to directly use.</p> + */ +final class LocaleUtils { + /** + * 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/services/core/java/com/android/server/textservices/TextServicesManagerService.java b/services/core/java/com/android/server/textservices/TextServicesManagerService.java index 5c420ea13601..e5166655d18c 100644 --- a/services/core/java/com/android/server/textservices/TextServicesManagerService.java +++ b/services/core/java/com/android/server/textservices/TextServicesManagerService.java @@ -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()]))); diff --git a/services/tests/servicestests/src/com/android/server/textservices/LocaleUtilsTest.java b/services/tests/servicestests/src/com/android/server/textservices/LocaleUtilsTest.java new file mode 100644 index 000000000000..3766d24b93d0 --- /dev/null +++ b/services/tests/servicestests/src/com/android/server/textservices/LocaleUtilsTest.java @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018 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.server.textservices; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Locale; + +public class LocaleUtilsTest { + 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 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)); + } + } +} |