Loading core/java/com/android/internal/inputmethod/InputMethodUtils.java +127 −0 Original line number Diff line number Diff line Loading @@ -1302,4 +1302,131 @@ public class InputMethodUtils { return enabledInputMethodAndSubtypes; } } // 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; } } core/tests/inputmethodtests/src/android/os/InputMethodTest.java +99 −0 Original line number Diff line number Diff line Loading @@ -51,11 +51,15 @@ public class InputMethodTest extends InstrumentationTestCase { 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_ANY = null; Loading Loading @@ -849,4 +853,99 @@ public class InputMethodTest extends InstrumentationTestCase { return preinstalledImes; } @SmallTest 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)); } } } services/core/java/com/android/server/TextServicesManagerService.java +38 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.inputmethod.InputMethodUtils; import com.android.internal.textservice.ISpellCheckerService; import com.android.internal.textservice.ISpellCheckerSession; import com.android.internal.textservice.ISpellCheckerSessionListener; Loading Loading @@ -61,9 +62,11 @@ import android.view.textservice.SpellCheckerSubtype; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; Loading Loading @@ -141,7 +144,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings); SpellCheckerInfo sci = getCurrentSpellChecker(null); if (sci == null) { sci = findAvailSpellCheckerLocked(null, null); sci = findAvailSpellCheckerLocked(null); if (sci != null) { // Set the current spell checker if there is one or more spell checkers // available. In this case, "sci" is the first one in the available spell Loading Loading @@ -190,7 +193,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE // Package modified || isPackageModified(packageName)) { sci = findAvailSpellCheckerLocked(null, packageName); sci = findAvailSpellCheckerLocked(packageName); if (sci != null) { setCurrentSpellCheckerLocked(sci.getId()); } Loading Loading @@ -331,8 +334,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { mSpellCheckerBindGroups.clear(); } // TODO: find an appropriate spell checker for specified locale private SpellCheckerInfo findAvailSpellCheckerLocked(String locale, String prefPackage) { private SpellCheckerInfo findAvailSpellCheckerLocked(String prefPackage) { final int spellCheckersCount = mSpellCheckerList.size(); if (spellCheckersCount == 0) { Slog.w(TAG, "no available spell checker services found"); Loading @@ -349,6 +351,38 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } } // Look up a spell checker based on the system locale. // TODO: Still there is a room to improve in the following logic: e.g., check if the package // is pre-installed or not. final Locale systemLocal = mContext.getResources().getConfiguration().locale; final ArrayList<Locale> suitableLocales = InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal); if (DBG) { Slog.w(TAG, "findAvailSpellCheckerLocked suitableLocales=" + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()]))); } final int localeCount = suitableLocales.size(); for (int localeIndex = 0; localeIndex < localeCount; ++localeIndex) { final Locale locale = suitableLocales.get(localeIndex); for (int spellCheckersIndex = 0; spellCheckersIndex < spellCheckersCount; ++spellCheckersIndex) { final SpellCheckerInfo info = mSpellCheckerList.get(spellCheckersIndex); final int subtypeCount = info.getSubtypeCount(); for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) { final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex); final Locale subtypeLocale = InputMethodUtils.constructLocaleFromString( subtype.getLocale()); if (locale.equals(subtypeLocale)) { // TODO: We may have more spell checkers that fall into this category. // Ideally we should pick up the most suitable one instead of simply // returning the first found one. return info; } } } } if (spellCheckersCount > 1) { Slog.w(TAG, "more than one spell checker service found, picking first"); } Loading Loading
core/java/com/android/internal/inputmethod/InputMethodUtils.java +127 −0 Original line number Diff line number Diff line Loading @@ -1302,4 +1302,131 @@ public class InputMethodUtils { return enabledInputMethodAndSubtypes; } } // 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; } }
core/tests/inputmethodtests/src/android/os/InputMethodTest.java +99 −0 Original line number Diff line number Diff line Loading @@ -51,11 +51,15 @@ public class InputMethodTest extends InstrumentationTestCase { 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_ANY = null; Loading Loading @@ -849,4 +853,99 @@ public class InputMethodTest extends InstrumentationTestCase { return preinstalledImes; } @SmallTest 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)); } } }
services/core/java/com/android/server/TextServicesManagerService.java +38 −4 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.server; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.PackageMonitor; import com.android.internal.inputmethod.InputMethodUtils; import com.android.internal.textservice.ISpellCheckerService; import com.android.internal.textservice.ISpellCheckerSession; import com.android.internal.textservice.ISpellCheckerSessionListener; Loading Loading @@ -61,9 +62,11 @@ import android.view.textservice.SpellCheckerSubtype; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.util.Arrays; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.concurrent.CopyOnWriteArrayList; Loading Loading @@ -141,7 +144,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { buildSpellCheckerMapLocked(mContext, mSpellCheckerList, mSpellCheckerMap, mSettings); SpellCheckerInfo sci = getCurrentSpellChecker(null); if (sci == null) { sci = findAvailSpellCheckerLocked(null, null); sci = findAvailSpellCheckerLocked(null); if (sci != null) { // Set the current spell checker if there is one or more spell checkers // available. In this case, "sci" is the first one in the available spell Loading Loading @@ -190,7 +193,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { change == PACKAGE_PERMANENT_CHANGE || change == PACKAGE_TEMPORARY_CHANGE // Package modified || isPackageModified(packageName)) { sci = findAvailSpellCheckerLocked(null, packageName); sci = findAvailSpellCheckerLocked(packageName); if (sci != null) { setCurrentSpellCheckerLocked(sci.getId()); } Loading Loading @@ -331,8 +334,7 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { mSpellCheckerBindGroups.clear(); } // TODO: find an appropriate spell checker for specified locale private SpellCheckerInfo findAvailSpellCheckerLocked(String locale, String prefPackage) { private SpellCheckerInfo findAvailSpellCheckerLocked(String prefPackage) { final int spellCheckersCount = mSpellCheckerList.size(); if (spellCheckersCount == 0) { Slog.w(TAG, "no available spell checker services found"); Loading @@ -349,6 +351,38 @@ public class TextServicesManagerService extends ITextServicesManager.Stub { } } } // Look up a spell checker based on the system locale. // TODO: Still there is a room to improve in the following logic: e.g., check if the package // is pre-installed or not. final Locale systemLocal = mContext.getResources().getConfiguration().locale; final ArrayList<Locale> suitableLocales = InputMethodUtils.getSuitableLocalesForSpellChecker(systemLocal); if (DBG) { Slog.w(TAG, "findAvailSpellCheckerLocked suitableLocales=" + Arrays.toString(suitableLocales.toArray(new Locale[suitableLocales.size()]))); } final int localeCount = suitableLocales.size(); for (int localeIndex = 0; localeIndex < localeCount; ++localeIndex) { final Locale locale = suitableLocales.get(localeIndex); for (int spellCheckersIndex = 0; spellCheckersIndex < spellCheckersCount; ++spellCheckersIndex) { final SpellCheckerInfo info = mSpellCheckerList.get(spellCheckersIndex); final int subtypeCount = info.getSubtypeCount(); for (int subtypeIndex = 0; subtypeIndex < subtypeCount; ++subtypeIndex) { final SpellCheckerSubtype subtype = info.getSubtypeAt(subtypeIndex); final Locale subtypeLocale = InputMethodUtils.constructLocaleFromString( subtype.getLocale()); if (locale.equals(subtypeLocale)) { // TODO: We may have more spell checkers that fall into this category. // Ideally we should pick up the most suitable one instead of simply // returning the first found one. return info; } } } } if (spellCheckersCount > 1) { Slog.w(TAG, "more than one spell checker service found, picking first"); } Loading