am 7e1dfaae: Merge "Remove ALS from LatinIME."

* commit '7e1dfaae3d6ca9aff1acfa9b358ad0b759ef0ec8':
  Remove ALS from LatinIME.
main
Dan Zivkovic 2015-03-12 17:22:37 +00:00 committed by Android Git Automerger
commit b724ff1d11
21 changed files with 247 additions and 549 deletions

View File

@ -23,7 +23,6 @@ import com.android.inputmethod.latin.SuggestedWords;
import com.android.inputmethod.latin.common.InputPointers;
import com.android.inputmethod.latin.inputlogic.PrivateCommandPerformer;
import java.util.List;
import java.util.Locale;
/**
@ -39,7 +38,7 @@ public class GestureConsumer {
public static GestureConsumer newInstance(
final EditorInfo editorInfo, final PrivateCommandPerformer commandPerformer,
final List<Locale> locales, final Keyboard keyboard) {
final Locale locale, final Keyboard keyboard) {
return GestureConsumer.NULL_GESTURE_CONSUMER;
}
@ -50,10 +49,10 @@ public class GestureConsumer {
return false;
}
public void onInit(final List<Locale> locales, final Keyboard keyboard) {
public void onInit(final Locale locale, final Keyboard keyboard) {
}
public void onGestureStarted(final List<Locale> locales, final Keyboard keyboard) {
public void onGestureStarted(final Locale locale, final Keyboard keyboard) {
}
public void onGestureCanceled() {

View File

@ -287,7 +287,7 @@ public class Key implements Comparable<Key> {
mLabelFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyLabelFlags)
| row.getDefaultKeyLabelFlags();
final boolean needsToUpcase = needsToUpcase(mLabelFlags, params.mId.mElementId);
final Locale localeForUpcasing = params.mId.getLocales()[0];
final Locale localeForUpcasing = params.mId.getLocale();
int actionFlags = style.getFlags(keyAttr, R.styleable.Keyboard_Key_keyActionFlags);
String[] moreKeys = style.getStringArray(keyAttr, R.styleable.Keyboard_Key_moreKeys);

View File

@ -164,8 +164,8 @@ public final class KeyboardId {
return InputTypeUtils.getImeOptionsActionIdFromEditorInfo(mEditorInfo);
}
public Locale[] getLocales() {
return mSubtype.getLocales();
public Locale getLocale() {
return mSubtype.getLocale();
}
@Override
@ -182,7 +182,7 @@ public final class KeyboardId {
public String toString() {
return String.format(Locale.ROOT, "[%s %s:%s %dx%d %s %s%s%s%s%s%s%s%s%s]",
elementIdToName(mElementId),
Arrays.deepToString(mSubtype.getLocales()),
mSubtype.getLocale(),
mSubtype.getExtraValueOf(KEYBOARD_LAYOUT_SET),
mWidth, mHeight,
modeName(mMode),

View File

@ -121,8 +121,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
mKeyboardLayoutSet = builder.build();
try {
mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState);
// TODO: revisit this for multi-lingual input
mKeyboardTextsSet.setLocale(mRichImm.getCurrentSubtypeLocales()[0], mThemeContext);
mKeyboardTextsSet.setLocale(mRichImm.getCurrentSubtypeLocale(), mThemeContext);
} catch (KeyboardLayoutSetException e) {
Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
}

View File

@ -843,15 +843,6 @@ public final class MainKeyboardView extends KeyboardView implements DrawingProxy
// Layout language name on spacebar.
private String layoutLanguageOnSpacebar(final Paint paint,
final RichInputMethodSubtype subtype, final int width) {
if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarUtils.FORMAT_TYPE_MULTIPLE) {
final Locale[] locales = subtype.getLocales();
final String[] languages = new String[locales.length];
for (int i = 0; i < locales.length; ++i) {
languages[i] = locales[i].getLanguage().toUpperCase(Locale.ROOT);
}
return TextUtils.join(" / ", languages);
}
// Choose appropriate language name to fit into the width.
if (mLanguageOnSpacebarFormatType == LanguageOnSpacebarUtils.FORMAT_TYPE_FULL_LOCALE) {
final String fullText = subtype.getFullDisplayName();

View File

@ -281,8 +281,7 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
params.mThemeId = keyboardAttr.getInt(R.styleable.Keyboard_themeId, 0);
params.mIconsSet.loadIcons(keyboardAttr);
// TODO: this needs to be revisited for multi-lingual input.
params.mTextsSet.setLocale(params.mId.getLocales()[0], mContext);
params.mTextsSet.setLocale(params.mId.getLocale(), mContext);
final int resourceId = keyboardAttr.getResourceId(
R.styleable.Keyboard_touchPositionCorrectionData, 0);
@ -673,10 +672,10 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
R.styleable.Keyboard_Case_imeAction, id.imeAction());
final boolean isIconDefinedMatched = isIconDefined(caseAttr,
R.styleable.Keyboard_Case_isIconDefined, mParams.mIconsSet);
final Locale[] locales = id.getLocales();
final boolean localeCodeMatched = matchLocaleCodes(caseAttr, locales);
final boolean languageCodeMatched = matchLanguageCodes(caseAttr, locales);
final boolean countryCodeMatched = matchCountryCodes(caseAttr, locales);
final Locale locale = id.getLocale();
final boolean localeCodeMatched = matchLocaleCodes(caseAttr, locale);
final boolean languageCodeMatched = matchLanguageCodes(caseAttr, locale);
final boolean countryCodeMatched = matchCountryCodes(caseAttr, locale);
final boolean splitLayoutMatched = matchBoolean(caseAttr,
R.styleable.Keyboard_Case_isSplitLayout, id.mIsSplitLayout);
final boolean selected = keyboardLayoutSetMatched && keyboardLayoutSetElementMatched
@ -732,21 +731,16 @@ public class KeyboardBuilder<KP extends KeyboardParams> {
}
}
private static boolean matchLocaleCodes(TypedArray caseAttr, final Locale[] locales) {
// TODO: adujst this for multilingual input
return matchString(caseAttr, R.styleable.Keyboard_Case_localeCode, locales[0].toString());
private static boolean matchLocaleCodes(TypedArray caseAttr, final Locale locale) {
return matchString(caseAttr, R.styleable.Keyboard_Case_localeCode, locale.toString());
}
private static boolean matchLanguageCodes(TypedArray caseAttr, Locale[] locales) {
// TODO: adujst this for multilingual input
return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode,
locales[0].getLanguage());
private static boolean matchLanguageCodes(TypedArray caseAttr, Locale locale) {
return matchString(caseAttr, R.styleable.Keyboard_Case_languageCode, locale.getLanguage());
}
private static boolean matchCountryCodes(TypedArray caseAttr, Locale[] locales) {
// TODO: adujst this for multilingual input
return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode,
locales[0].getCountry());
private static boolean matchCountryCodes(TypedArray caseAttr, Locale locale) {
return matchString(caseAttr, R.styleable.Keyboard_Case_countryCode, locale.getCountry());
}
private static boolean matchInteger(final TypedArray a, final int index, final int value) {

View File

@ -72,11 +72,11 @@ public interface DictionaryFacilitator {
Dictionary.TYPE_CONTACTS};
/**
* Returns whether this facilitator is exactly for this list of locales.
* Returns whether this facilitator is exactly for this locale.
*
* @param locales the list of locales to test against
* @param locale the locale to test against
*/
boolean isForLocales(final Locale[] locales);
boolean isForLocale(final Locale locale);
/**
* Returns whether this facilitator is exactly for this account.
@ -91,25 +91,11 @@ public interface DictionaryFacilitator {
boolean isActive();
/**
* Returns the most probable locale among all currently active locales. BE CAREFUL using this.
*
* DO NOT USE THIS just because it's convenient. Use it when it's correct, for example when
* choosing what dictionary to put a word in, or when changing the capitalization of a typed
* string.
* @return the most probable locale
*/
Locale getMostProbableLocale();
Locale[] getLocales();
void switchMostProbableLanguage(@Nullable final Locale locale);
boolean isConfidentAboutCurrentLanguageBeing(final Locale mLocale);
Locale getLocale();
void resetDictionaries(
final Context context,
final Locale[] newLocales,
final Locale newLocale,
final boolean useContactsDict,
final boolean usePersonalizedDicts,
final boolean forceReloadMainDictionary,
@ -120,7 +106,7 @@ public interface DictionaryFacilitator {
@UsedForTesting
void resetDictionariesForTesting(
final Context context,
final Locale[] locales,
final Locale locale,
final ArrayList<String> dictionaryTypes,
final HashMap<String, File> dictionaryFiles,
final Map<String, Map<String, String>> additionalDictAttributes,

View File

@ -63,12 +63,8 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
// HACK: This threshold is being used when adding a capitalized entry in the User History
// dictionary.
private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140;
// How many words we need to type in a row ({@see mConfidenceInMostProbableLanguage}) to
// declare we are confident the user is typing in the most probable language.
private static final int CONFIDENCE_THRESHOLD = 3;
private DictionaryGroup[] mDictionaryGroups = new DictionaryGroup[] { new DictionaryGroup() };
private DictionaryGroup mMostProbableDictionaryGroup = mDictionaryGroups[0];
private DictionaryGroup mDictionaryGroup = new DictionaryGroup();
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0);
// To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
private final Object mLock = new Object();
@ -86,28 +82,9 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES =
new Class[] { Context.class, Locale.class, File.class, String.class, String.class };
/**
* Returns whether this facilitator is exactly for this list of locales.
*
* @param locales the list of locales to test against
*/
public boolean isForLocales(final Locale[] locales) {
if (locales.length != mDictionaryGroups.length) {
return false;
}
for (final Locale locale : locales) {
boolean found = false;
for (final DictionaryGroup group : mDictionaryGroups) {
if (locale.equals(group.mLocale)) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
@Override
public boolean isForLocale(final Locale locale) {
return locale != null && locale.equals(mDictionaryGroup.mLocale);
}
/**
@ -116,12 +93,7 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
* @param account the account to test against.
*/
public boolean isForAccount(@Nullable final String account) {
for (final DictionaryGroup group : mDictionaryGroups) {
if (!TextUtils.equals(group.mAccount, account)) {
return false;
}
}
return true;
return TextUtils.equals(mDictionaryGroup.mAccount, account);
}
/**
@ -231,75 +203,12 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
}
public boolean isActive() {
return null != mDictionaryGroups[0].mLocale;
return mDictionaryGroup.mLocale != null;
}
/**
* Returns the most probable locale among all currently active locales. BE CAREFUL using this.
*
* DO NOT USE THIS just because it's convenient. Use it when it's correct, for example when
* choosing what dictionary to put a word in, or when changing the capitalization of a typed
* string.
* @return the most probable locale
*/
public Locale getMostProbableLocale() {
return getDictionaryGroupForMostProbableLanguage().mLocale;
}
public Locale[] getLocales() {
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
final Locale[] locales = new Locale[dictionaryGroups.length];
for (int i = 0; i < dictionaryGroups.length; ++i) {
locales[i] = dictionaryGroups[i].mLocale;
}
return locales;
}
private DictionaryGroup getDictionaryGroupForMostProbableLanguage() {
return mMostProbableDictionaryGroup;
}
public void switchMostProbableLanguage(@Nullable final Locale locale) {
if (null == locale) {
// In many cases, there is no locale to a committed word. For example, a typed word
// that is in none of the currently active dictionaries but still does not
// auto-correct to anything has no locale. In this case we simply do not change
// the most probable language and do not touch confidence.
return;
}
final DictionaryGroup newMostProbableDictionaryGroup =
findDictionaryGroupWithLocale(mDictionaryGroups, locale);
if (null == newMostProbableDictionaryGroup) {
// It seems this may happen as a race condition; pressing the globe key and space
// in quick succession could commit a word out of a dictionary that's not in the
// facilitator any more. In this case, just not changing things is fine.
return;
}
if (newMostProbableDictionaryGroup == mMostProbableDictionaryGroup) {
++newMostProbableDictionaryGroup.mConfidence;
} else {
mMostProbableDictionaryGroup.mWeightForTypingInLocale =
DictionaryGroup.WEIGHT_FOR_TYPING_IN_NOT_MOST_PROBABLE_LANGUAGE;
mMostProbableDictionaryGroup.mWeightForGesturingInLocale =
DictionaryGroup.WEIGHT_FOR_GESTURING_IN_NOT_MOST_PROBABLE_LANGUAGE;
mMostProbableDictionaryGroup.mConfidence = 0;
newMostProbableDictionaryGroup.mWeightForTypingInLocale =
DictionaryGroup.WEIGHT_FOR_MOST_PROBABLE_LANGUAGE;
newMostProbableDictionaryGroup.mWeightForGesturingInLocale =
DictionaryGroup.WEIGHT_FOR_MOST_PROBABLE_LANGUAGE;
mMostProbableDictionaryGroup = newMostProbableDictionaryGroup;
}
}
public boolean isConfidentAboutCurrentLanguageBeing(final Locale mLocale) {
final DictionaryGroup mostProbableDictionaryGroup = mMostProbableDictionaryGroup;
if (!mostProbableDictionaryGroup.mLocale.equals(mLocale)) {
return false;
}
if (mDictionaryGroups.length <= 1) {
return true;
}
return mostProbableDictionaryGroup.mConfidence >= CONFIDENCE_THRESHOLD;
@Override
public Locale getLocale() {
return mDictionaryGroup.mLocale;
}
@Nullable
@ -325,19 +234,15 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
}
@Nullable
static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
static DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup dictionaryGroup,
final Locale locale) {
for (DictionaryGroup dictionaryGroup : dictionaryGroups) {
if (locale.equals(dictionaryGroup.mLocale)) {
return dictionaryGroup;
}
}
return null;
return locale.equals(dictionaryGroup.mLocale) ? dictionaryGroup : null;
}
@Override
public void resetDictionaries(
final Context context,
final Locale[] newLocales,
final Locale newLocale,
final boolean useContactsDict,
final boolean usePersonalizedDicts,
final boolean forceReloadMainDictionary,
@ -356,14 +261,11 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
}
// Gather all dictionaries. We'll remove them from the list to clean up later.
for (final Locale newLocale : newLocales) {
final ArrayList<String> dictTypeForLocale = new ArrayList<>();
existingDictionariesToCleanup.put(newLocale, dictTypeForLocale);
final DictionaryGroup currentDictionaryGroupForLocale =
findDictionaryGroupWithLocale(mDictionaryGroups, newLocale);
if (null == currentDictionaryGroupForLocale) {
continue;
}
final ArrayList<String> dictTypeForLocale = new ArrayList<>();
existingDictionariesToCleanup.put(newLocale, dictTypeForLocale);
final DictionaryGroup currentDictionaryGroupForLocale =
findDictionaryGroupWithLocale(mDictionaryGroup, newLocale);
if (currentDictionaryGroupForLocale != null) {
for (final String dictType : DYNAMIC_DICTIONARY_TYPES) {
if (currentDictionaryGroupForLocale.hasDict(dictType, account)) {
dictTypeForLocale.add(dictType);
@ -374,50 +276,46 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
}
}
final DictionaryGroup[] newDictionaryGroups = new DictionaryGroup[newLocales.length];
for (int i = 0; i < newLocales.length; ++i) {
final Locale newLocale = newLocales[i];
final DictionaryGroup dictionaryGroupForLocale =
findDictionaryGroupWithLocale(mDictionaryGroups, newLocale);
final ArrayList<String> dictTypesToCleanupForLocale =
existingDictionariesToCleanup.get(newLocale);
final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale);
final DictionaryGroup dictionaryGroupForLocale =
findDictionaryGroupWithLocale(mDictionaryGroup, newLocale);
final ArrayList<String> dictTypesToCleanupForLocale =
existingDictionariesToCleanup.get(newLocale);
final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale);
final Dictionary mainDict;
if (forceReloadMainDictionary || noExistingDictsForThisLocale
|| !dictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN, account)) {
mainDict = null;
} else {
mainDict = dictionaryGroupForLocale.getDict(Dictionary.TYPE_MAIN);
dictTypesToCleanupForLocale.remove(Dictionary.TYPE_MAIN);
}
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
for (final String subDictType : subDictTypesToUse) {
final ExpandableBinaryDictionary subDict;
if (noExistingDictsForThisLocale
|| !dictionaryGroupForLocale.hasDict(subDictType, account)) {
// Create a new dictionary.
subDict = getSubDict(subDictType, context, newLocale, null /* dictFile */,
dictNamePrefix, account);
} else {
// Reuse the existing dictionary, and don't close it at the end
subDict = dictionaryGroupForLocale.getSubDict(subDictType);
dictTypesToCleanupForLocale.remove(subDictType);
}
subDicts.put(subDictType, subDict);
}
newDictionaryGroups[i] = new DictionaryGroup(newLocale, mainDict, account, subDicts);
final Dictionary mainDict;
if (forceReloadMainDictionary || noExistingDictsForThisLocale
|| !dictionaryGroupForLocale.hasDict(Dictionary.TYPE_MAIN, account)) {
mainDict = null;
} else {
mainDict = dictionaryGroupForLocale.getDict(Dictionary.TYPE_MAIN);
dictTypesToCleanupForLocale.remove(Dictionary.TYPE_MAIN);
}
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
for (final String subDictType : subDictTypesToUse) {
final ExpandableBinaryDictionary subDict;
if (noExistingDictsForThisLocale
|| !dictionaryGroupForLocale.hasDict(subDictType, account)) {
// Create a new dictionary.
subDict = getSubDict(subDictType, context, newLocale, null /* dictFile */,
dictNamePrefix, account);
} else {
// Reuse the existing dictionary, and don't close it at the end
subDict = dictionaryGroupForLocale.getSubDict(subDictType);
dictTypesToCleanupForLocale.remove(subDictType);
}
subDicts.put(subDictType, subDict);
}
DictionaryGroup newDictionaryGroup =
new DictionaryGroup(newLocale, mainDict, account, subDicts);
// Replace Dictionaries.
final DictionaryGroup[] oldDictionaryGroups;
final DictionaryGroup oldDictionaryGroup;
synchronized (mLock) {
oldDictionaryGroups = mDictionaryGroups;
mDictionaryGroups = newDictionaryGroups;
mMostProbableDictionaryGroup = newDictionaryGroups[0];
oldDictionaryGroup = mDictionaryGroup;
mDictionaryGroup = newDictionaryGroup;
if (hasAtLeastOneUninitializedMainDictionary()) {
asyncReloadUninitializedMainDictionaries(context, newLocales, listener);
asyncReloadUninitializedMainDictionaries(context, newLocale, listener);
}
}
if (listener != null) {
@ -429,7 +327,7 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
final ArrayList<String> dictTypesToCleanUp =
existingDictionariesToCleanup.get(localeToCleanUp);
final DictionaryGroup dictionarySetToCleanup =
findDictionaryGroupWithLocale(oldDictionaryGroups, localeToCleanUp);
findDictionaryGroupWithLocale(oldDictionaryGroup, localeToCleanUp);
for (final String dictType : dictTypesToCleanUp) {
dictionarySetToCleanup.closeDict(dictType);
}
@ -437,123 +335,105 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
}
private void asyncReloadUninitializedMainDictionaries(final Context context,
final Locale[] locales, final DictionaryInitializationListener listener) {
final Locale locale, final DictionaryInitializationListener listener) {
final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1);
mLatchForWaitingLoadingMainDictionaries = latchForWaitingLoadingMainDictionary;
ExecutorUtils.getBackgroundExecutor().execute(new Runnable() {
@Override
public void run() {
doReloadUninitializedMainDictionaries(
context, locales, listener, latchForWaitingLoadingMainDictionary);
context, locale, listener, latchForWaitingLoadingMainDictionary);
}
});
}
void doReloadUninitializedMainDictionaries(final Context context, final Locale[] locales,
void doReloadUninitializedMainDictionaries(final Context context, final Locale locale,
final DictionaryInitializationListener listener,
final CountDownLatch latchForWaitingLoadingMainDictionary) {
for (final Locale locale : locales) {
final DictionaryGroup dictionaryGroup =
findDictionaryGroupWithLocale(mDictionaryGroups, locale);
if (null == dictionaryGroup) {
// This should never happen, but better safe than crashy
Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
continue;
}
final Dictionary mainDict =
DictionaryFactory.createMainDictionaryFromManager(context, locale);
synchronized (mLock) {
if (locale.equals(dictionaryGroup.mLocale)) {
dictionaryGroup.setMainDict(mainDict);
} else {
// Dictionary facilitator has been reset for another locale.
mainDict.close();
}
final DictionaryGroup dictionaryGroup =
findDictionaryGroupWithLocale(mDictionaryGroup, locale);
if (null == dictionaryGroup) {
// This should never happen, but better safe than crashy
Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
return;
}
final Dictionary mainDict =
DictionaryFactory.createMainDictionaryFromManager(context, locale);
synchronized (mLock) {
if (locale.equals(dictionaryGroup.mLocale)) {
dictionaryGroup.setMainDict(mainDict);
} else {
// Dictionary facilitator has been reset for another locale.
mainDict.close();
}
}
if (listener != null) {
listener.onUpdateMainDictionaryAvailability(
hasAtLeastOneInitializedMainDictionary());
listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary());
}
latchForWaitingLoadingMainDictionary.countDown();
}
@UsedForTesting
public void resetDictionariesForTesting(final Context context, final Locale[] locales,
public void resetDictionariesForTesting(final Context context, final Locale locale,
final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
final Map<String, Map<String, String>> additionalDictAttributes,
@Nullable final String account) {
Dictionary mainDictionary = null;
final Map<String, ExpandableBinaryDictionary> subDicts = new HashMap<>();
final DictionaryGroup[] dictionaryGroups = new DictionaryGroup[locales.length];
for (int i = 0; i < locales.length; ++i) {
final Locale locale = locales[i];
for (final String dictType : dictionaryTypes) {
if (dictType.equals(Dictionary.TYPE_MAIN)) {
mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context,
locale);
} else {
final File dictFile = dictionaryFiles.get(dictType);
final ExpandableBinaryDictionary dict = getSubDict(
dictType, context, locale, dictFile, "" /* dictNamePrefix */, account);
if (additionalDictAttributes.containsKey(dictType)) {
dict.clearAndFlushDictionaryWithAdditionalAttributes(
additionalDictAttributes.get(dictType));
}
if (dict == null) {
throw new RuntimeException("Unknown dictionary type: " + dictType);
}
dict.reloadDictionaryIfRequired();
dict.waitAllTasksForTests();
subDicts.put(dictType, dict);
for (final String dictType : dictionaryTypes) {
if (dictType.equals(Dictionary.TYPE_MAIN)) {
mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context,
locale);
} else {
final File dictFile = dictionaryFiles.get(dictType);
final ExpandableBinaryDictionary dict = getSubDict(
dictType, context, locale, dictFile, "" /* dictNamePrefix */, account);
if (additionalDictAttributes.containsKey(dictType)) {
dict.clearAndFlushDictionaryWithAdditionalAttributes(
additionalDictAttributes.get(dictType));
}
if (dict == null) {
throw new RuntimeException("Unknown dictionary type: " + dictType);
}
dict.reloadDictionaryIfRequired();
dict.waitAllTasksForTests();
subDicts.put(dictType, dict);
}
dictionaryGroups[i] = new DictionaryGroup(locale, mainDictionary, account, subDicts);
}
mDictionaryGroups = dictionaryGroups;
mMostProbableDictionaryGroup = dictionaryGroups[0];
mDictionaryGroup = new DictionaryGroup(locale, mainDictionary, account, subDicts);
}
public void closeDictionaries() {
final DictionaryGroup[] dictionaryGroups;
final DictionaryGroup dictionaryGroupToClose;
synchronized (mLock) {
dictionaryGroups = mDictionaryGroups;
mMostProbableDictionaryGroup = new DictionaryGroup();
mDictionaryGroups = new DictionaryGroup[] { mMostProbableDictionaryGroup };
dictionaryGroupToClose = mDictionaryGroup;
mDictionaryGroup = new DictionaryGroup();
}
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
for (final String dictType : ALL_DICTIONARY_TYPES) {
dictionaryGroup.closeDict(dictType);
}
for (final String dictType : ALL_DICTIONARY_TYPES) {
dictionaryGroupToClose.closeDict(dictType);
}
}
@UsedForTesting
public ExpandableBinaryDictionary getSubDictForTesting(final String dictName) {
return mMostProbableDictionaryGroup.getSubDict(dictName);
return mDictionaryGroup.getSubDict(dictName);
}
// The main dictionaries are loaded asynchronously. Don't cache the return value
// of these methods.
public boolean hasAtLeastOneInitializedMainDictionary() {
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
final Dictionary mainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN);
if (mainDict != null && mainDict.isInitialized()) {
return true;
}
final Dictionary mainDict = mDictionaryGroup.getDict(Dictionary.TYPE_MAIN);
if (mainDict != null && mainDict.isInitialized()) {
return true;
}
return false;
}
public boolean hasAtLeastOneUninitializedMainDictionary() {
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
final Dictionary mainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN);
if (mainDict == null || !mainDict.isInitialized()) {
return true;
}
final Dictionary mainDict = mDictionaryGroup.getDict(Dictionary.TYPE_MAIN);
if (mainDict == null || !mainDict.isInitialized()) {
return true;
}
return false;
}
@ -567,25 +447,22 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
public void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
throws InterruptedException {
waitForLoadingMainDictionaries(timeout, unit);
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
for (final ExpandableBinaryDictionary dict : dictionaryGroup.mSubDictMap.values()) {
dict.waitAllTasksForTests();
}
for (final ExpandableBinaryDictionary dict : mDictionaryGroup.mSubDictMap.values()) {
dict.waitAllTasksForTests();
}
}
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
@Nonnull final NgramContext ngramContext, final long timeStampInSeconds,
final boolean blockPotentiallyOffensive) {
final DictionaryGroup dictionaryGroup = getDictionaryGroupForMostProbableLanguage();
final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
NgramContext ngramContextForCurrentWord = ngramContext;
for (int i = 0; i < words.length; i++) {
final String currentWord = words[i];
final boolean wasCurrentWordAutoCapitalized = (i == 0) ? wasAutoCapitalized : false;
addWordToUserHistory(dictionaryGroup, ngramContextForCurrentWord, currentWord,
wasCurrentWordAutoCapitalized, (int) timeStampInSeconds, blockPotentiallyOffensive);
addWordToUserHistory(mDictionaryGroup, ngramContextForCurrentWord, currentWord,
wasCurrentWordAutoCapitalized, (int) timeStampInSeconds,
blockPotentiallyOffensive);
ngramContextForCurrentWord =
ngramContextForCurrentWord.getNextNgramContext(new WordInfo(currentWord));
}
@ -596,8 +473,7 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
final int timeStampInSeconds, final boolean blockPotentiallyOffensive) {
final ExpandableBinaryDictionary userHistoryDictionary =
dictionaryGroup.getSubDict(Dictionary.TYPE_USER_HISTORY);
if (userHistoryDictionary == null
|| !isConfidentAboutCurrentLanguageBeing(userHistoryDictionary.mLocale)) {
if (userHistoryDictionary == null || !isForLocale(userHistoryDictionary.mLocale)) {
return;
}
final int maxFreq = getFrequency(word);
@ -644,8 +520,7 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
}
private void removeWord(final String dictName, final String word) {
final ExpandableBinaryDictionary dictionary =
getDictionaryGroupForMostProbableLanguage().getSubDict(dictName);
final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName);
if (dictionary != null) {
dictionary.removeUnigramEntryDynamically(word);
}
@ -668,28 +543,25 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
SettingsValuesForSuggestion settingsValuesForSuggestion, int sessionId,
int inputStyle) {
long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo();
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
final SuggestionResults suggestionResults = new SuggestionResults(
SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext(),
false /* firstSuggestionExceedsConfidenceThreshold */);
final float[] weightOfLangModelVsSpatialModel =
new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL };
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
for (final String dictType : DICTIONARY_TYPES_FOR_SUGGESTIONS) {
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
if (null == dictionary) continue;
final float weightForLocale = composedData.mIsBatchMode
? dictionaryGroup.mWeightForGesturingInLocale
: dictionaryGroup.mWeightForTypingInLocale;
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
dictionary.getSuggestions(composedData, ngramContext,
proximityInfoHandle, settingsValuesForSuggestion, sessionId,
weightForLocale, weightOfLangModelVsSpatialModel);
if (null == dictionarySuggestions) continue;
suggestionResults.addAll(dictionarySuggestions);
if (null != suggestionResults.mRawSuggestions) {
suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
}
for (final String dictType : DICTIONARY_TYPES_FOR_SUGGESTIONS) {
final Dictionary dictionary = mDictionaryGroup.getDict(dictType);
if (null == dictionary) continue;
final float weightForLocale = composedData.mIsBatchMode
? mDictionaryGroup.mWeightForGesturingInLocale
: mDictionaryGroup.mWeightForTypingInLocale;
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
dictionary.getSuggestions(composedData, ngramContext,
proximityInfoHandle, settingsValuesForSuggestion, sessionId,
weightForLocale, weightOfLangModelVsSpatialModel);
if (null == dictionarySuggestions) continue;
suggestionResults.addAll(dictionarySuggestions);
if (null != suggestionResults.mRawSuggestions) {
suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
}
}
return suggestionResults;
@ -707,20 +579,17 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
if (TextUtils.isEmpty(word)) {
return false;
}
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
if (dictionaryGroup.mLocale == null) {
continue;
}
for (final String dictType : dictionariesToCheck) {
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
// Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
// would be immutable once it's finished initializing, but concretely a null test is
// probably good enough for the time being.
if (null == dictionary) continue;
if (dictionary.isValidWord(word)) {
return true;
}
if (mDictionaryGroup.mLocale == null) {
return false;
}
for (final String dictType : dictionariesToCheck) {
final Dictionary dictionary = mDictionaryGroup.getDict(dictType);
// Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
// would be immutable once it's finished initializing, but concretely a null test is
// probably good enough for the time being.
if (null == dictionary) continue;
if (dictionary.isValidWord(word)) {
return true;
}
}
return false;
@ -731,27 +600,21 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
return Dictionary.NOT_A_PROBABILITY;
}
int maxFreq = Dictionary.NOT_A_PROBABILITY;
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
for (final String dictType : ALL_DICTIONARY_TYPES) {
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
if (dictionary == null) continue;
final int tempFreq = dictionary.getFrequency(word);
if (tempFreq >= maxFreq) {
maxFreq = tempFreq;
}
for (final String dictType : ALL_DICTIONARY_TYPES) {
final Dictionary dictionary = mDictionaryGroup.getDict(dictType);
if (dictionary == null) continue;
final int tempFreq = dictionary.getFrequency(word);
if (tempFreq >= maxFreq) {
maxFreq = tempFreq;
}
}
return maxFreq;
}
private void clearSubDictionary(final String dictName) {
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(dictName);
if (dictionary != null) {
dictionary.clear();
}
final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName);
if (dictionary != null) {
dictionary.clear();
}
}
@ -762,28 +625,22 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator {
@Override
public void dumpDictionaryForDebug(final String dictName) {
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
final ExpandableBinaryDictionary dictToDump = dictionaryGroup.getSubDict(dictName);
if (dictToDump == null) {
Log.e(TAG, "Cannot dump " + dictName + ". "
+ "The dictionary is not being used for suggestion or cannot be dumped.");
return;
}
dictToDump.dumpAllWordsForDebug();
final ExpandableBinaryDictionary dictToDump = mDictionaryGroup.getSubDict(dictName);
if (dictToDump == null) {
Log.e(TAG, "Cannot dump " + dictName + ". "
+ "The dictionary is not being used for suggestion or cannot be dumped.");
return;
}
dictToDump.dumpAllWordsForDebug();
}
@Override
public ArrayList<Pair<String, DictionaryStats>> getStatsOfEnabledSubDicts() {
final ArrayList<Pair<String, DictionaryStats>> statsOfEnabledSubDicts = new ArrayList<>();
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
for (final String dictType : DYNAMIC_DICTIONARY_TYPES) {
final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(dictType);
if (dictionary == null) continue;
statsOfEnabledSubDicts.add(new Pair<>(dictType, dictionary.getDictionaryStats()));
}
for (final String dictType : DYNAMIC_DICTIONARY_TYPES) {
final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictType);
if (dictionary == null) continue;
statsOfEnabledSubDicts.add(new Pair<>(dictType, dictionary.getDictionaryStats()));
}
return statsOfEnabledSubDicts;
}

View File

@ -68,7 +68,7 @@ public class DictionaryFacilitatorLruCache {
// Nothing to do if the locale is null. This would be the case before any get() calls.
if (mLocale != null) {
// Note: Given that personalized dictionaries are not used here; we can pass null account.
mDictionaryFacilitator.resetDictionaries(mContext, new Locale[]{mLocale},
mDictionaryFacilitator.resetDictionaries(mContext, mLocale,
mUseContactsDictionary, false /* usePersonalizedDicts */,
false /* forceReloadMainDictionary */, null /* account */,
mDictionaryNamePrefix, null /* listener */);
@ -89,7 +89,7 @@ public class DictionaryFacilitatorLruCache {
public DictionaryFacilitator get(final Locale locale) {
synchronized (mLock) {
if (!mDictionaryFacilitator.isForLocales(new Locale[]{locale})) {
if (!mDictionaryFacilitator.isForLocale(locale)) {
mLocale = locale;
resetDictionariesForLocaleLocked();
}

View File

@ -588,19 +588,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Has to be package-visible for unit tests
@UsedForTesting
void loadSettings() {
final Locale[] locales = mRichImm.getCurrentSubtypeLocales();
final Locale locale = mRichImm.getCurrentSubtypeLocale();
final EditorInfo editorInfo = getCurrentInputEditorInfo();
final InputAttributes inputAttributes = new InputAttributes(
editorInfo, isFullscreenMode(), getPackageName());
// TODO: pass the array instead
mSettings.loadSettings(this, locales[0], inputAttributes);
mSettings.loadSettings(this, locale, inputAttributes);
final SettingsValues currentSettingsValues = mSettings.getCurrent();
AudioAndHapticFeedbackManager.getInstance().onSettingsChanged(currentSettingsValues);
// This method is called on startup and language switch, before the new layout has
// been displayed. Opening dictionaries never affects responsivity as dictionaries are
// asynchronously loaded.
if (!mHandler.hasPendingReopenDictionaries()) {
resetDictionaryFacilitator(locales);
resetDictionaryFacilitator(locale);
}
refreshPersonalizationDictionarySession(currentSettingsValues);
resetDictionaryFacilitatorIfNecessary();
@ -630,35 +629,35 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
void resetDictionaryFacilitatorIfNecessary() {
final Locale[] subtypeSwitcherLocales = mRichImm.getCurrentSubtypeLocales();
if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)
&& mDictionaryFacilitator.isForAccount(mSettings.getCurrent().mAccount)) {
return;
}
final Locale[] subtypeLocales;
if (0 == subtypeSwitcherLocales.length) {
final Locale subtypeSwitcherLocale = mRichImm.getCurrentSubtypeLocale();
final Locale subtypeLocale;
if (subtypeSwitcherLocale == null) {
// This happens in very rare corner cases - for example, immediately after a switch
// to LatinIME has been requested, about a frame later another switch happens. In this
// case, we are about to go down but we still don't know it, however the system tells
// us there is no current subtype.
Log.e(TAG, "System is reporting no current subtype.");
subtypeLocales = new Locale[] { getResources().getConfiguration().locale };
subtypeLocale = getResources().getConfiguration().locale;
} else {
subtypeLocales = subtypeSwitcherLocales;
subtypeLocale = subtypeSwitcherLocale;
}
resetDictionaryFacilitator(subtypeLocales);
if (mDictionaryFacilitator.isForLocale(subtypeLocale)
&& mDictionaryFacilitator.isForAccount(mSettings.getCurrent().mAccount)) {
return;
}
resetDictionaryFacilitator(subtypeLocale);
}
/**
* Reset the facilitator by loading dictionaries for the locales and
* Reset the facilitator by loading dictionaries for the given locale and
* the current settings values.
*
* @param locales the locales
* @param locale the locale
*/
// TODO: make sure the current settings always have the right locales, and read from them.
private void resetDictionaryFacilitator(final Locale[] locales) {
private void resetDictionaryFacilitator(final Locale locale) {
final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this /* context */, locales,
mDictionaryFacilitator.resetDictionaries(this /* context */, locale,
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
false /* forceReloadMainDictionary */,
settingsValues.mAccount, "" /* dictNamePrefix */,
@ -676,7 +675,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
/* package private */ void resetSuggestMainDict() {
final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this /* context */,
mDictionaryFacilitator.getLocales(), settingsValues.mUseContactsDict,
mDictionaryFacilitator.getLocale(), settingsValues.mUseContactsDict,
settingsValues.mUsePersonalizedDicts,
true /* forceReloadMainDictionary */,
settingsValues.mAccount, "" /* dictNamePrefix */,
@ -843,7 +842,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// Update to a gesture consumer with the current editor and IME state.
mGestureConsumer = GestureConsumer.newInstance(editorInfo,
mInputLogic.getPrivateCommandPerformer(),
Arrays.asList(mRichImm.getCurrentSubtypeLocales()),
mRichImm.getCurrentSubtypeLocale(),
switcher.getKeyboard());
// Forward this event to the accessibility utilities, if enabled.
@ -1379,7 +1378,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
public void onStartBatchInput() {
mInputLogic.onStartBatchInput(mSettings.getCurrent(), mKeyboardSwitcher, mHandler);
mGestureConsumer.onGestureStarted(
Arrays.asList(mRichImm.getCurrentSubtypeLocales()),
mRichImm.getCurrentSubtypeLocale(),
mKeyboardSwitcher.getKeyboard());
}
@ -1767,23 +1766,23 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// TODO: can this be removed somehow without breaking the tests?
@UsedForTesting
/* package for test */ SuggestedWords getSuggestedWordsForTest() {
SuggestedWords getSuggestedWordsForTest() {
// You may not use this method for anything else than debug
return DebugFlags.DEBUG_ENABLED ? mInputLogic.mSuggestedWords : null;
}
// DO NOT USE THIS for any other purpose than testing. This is information private to LatinIME.
@UsedForTesting
/* package for test */ void waitForLoadingDictionaries(final long timeout, final TimeUnit unit)
void waitForLoadingDictionaries(final long timeout, final TimeUnit unit)
throws InterruptedException {
mDictionaryFacilitator.waitForLoadingDictionariesForTesting(timeout, unit);
}
// DO NOT USE THIS for any other purpose than testing. This can break the keyboard badly.
@UsedForTesting
/* package for test */ void replaceDictionariesForTest(final Locale locale) {
void replaceDictionariesForTest(final Locale locale) {
final SettingsValues settingsValues = mSettings.getCurrent();
mDictionaryFacilitator.resetDictionaries(this, new Locale[] { locale },
mDictionaryFacilitator.resetDictionaries(this, locale,
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
false /* forceReloadMainDictionary */,
settingsValues.mAccount, "", /* dictionaryNamePrefix */
@ -1792,12 +1791,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// DO NOT USE THIS for any other purpose than testing.
@UsedForTesting
/* package for test */ void clearPersonalizedDictionariesForTest() {
void clearPersonalizedDictionariesForTest() {
mDictionaryFacilitator.clearUserHistoryDictionary(this);
}
@UsedForTesting
/* package for test */ List<InputMethodSubtype> getEnabledSubtypesForTest() {
List<InputMethodSubtype> getEnabledSubtypesForTest() {
return (mRichImm != null) ? mRichImm.getMyEnabledInputMethodSubtypeList(
true /* allowsImplicitlySelectedSubtypes */) : new ArrayList<InputMethodSubtype>();
}

View File

@ -334,11 +334,11 @@ public class RichInputMethodManager {
}
@Nonnull
public Locale[] getCurrentSubtypeLocales() {
public Locale getCurrentSubtypeLocale() {
if (null != sForcedSubtypeForTesting) {
return sForcedSubtypeForTesting.getLocales();
return sForcedSubtypeForTesting.getLocale();
}
return getCurrentSubtype().getLocales();
return getCurrentSubtype().getLocale();
}
@Nonnull

View File

@ -26,7 +26,6 @@ import com.android.inputmethod.latin.common.Constants;
import com.android.inputmethod.latin.common.LocaleUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
import java.util.Arrays;
import java.util.Locale;
import javax.annotation.Nonnull;
@ -43,14 +42,11 @@ public final class RichInputMethodSubtype {
@Nonnull
private final InputMethodSubtype mSubtype;
@Nonnull
private final Locale[] mLocales;
private final Locale mLocale;
public RichInputMethodSubtype(@Nonnull final InputMethodSubtype subtype,
@Nonnull final Locale... locales) {
public RichInputMethodSubtype(@Nonnull final InputMethodSubtype subtype) {
mSubtype = subtype;
mLocales = new Locale[locales.length + 1];
mLocales[0] = LocaleUtils.constructLocaleFromString(mSubtype.getLocale());
System.arraycopy(locales, 0, mLocales, 1, locales.length);
mLocale = LocaleUtils.constructLocaleFromString(mSubtype.getLocale());
}
// Extra values are determined by the primary subtype. This is probably right, but
@ -65,9 +61,6 @@ public final class RichInputMethodSubtype {
}
public boolean isNoLanguage() {
if (mLocales.length > 1) {
return false;
}
return SubtypeLocaleUtils.NO_LANGUAGE.equals(mSubtype.getLocale());
}
@ -116,27 +109,27 @@ public final class RichInputMethodSubtype {
return false;
}
final RichInputMethodSubtype other = (RichInputMethodSubtype)o;
return mSubtype.equals(other.mSubtype) && Arrays.equals(mLocales, other.mLocales);
return mSubtype.equals(other.mSubtype) && mLocale.equals(other.mLocale);
}
@Override
public int hashCode() {
return mSubtype.hashCode() + Arrays.hashCode(mLocales);
return mSubtype.hashCode() + mLocale.hashCode();
}
@Override
public String toString() {
return "Multi-lingual subtype: " + mSubtype.toString() + ", " + Arrays.toString(mLocales);
return "Multi-lingual subtype: " + mSubtype + ", " + mLocale;
}
@Nonnull
public Locale[] getLocales() {
return mLocales;
public Locale getLocale() {
return mLocale;
}
public boolean isRtlSubtype() {
// The subtype is considered RTL if the language of the main subtype is RTL.
return LocaleUtils.isRtlLanguage(mLocales[0]);
return LocaleUtils.isRtlLanguage(mLocale);
}
// TODO: remove this method

View File

@ -176,13 +176,13 @@ public final class Suggest {
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
wordComposer.getComposedDataSnapshot(), ngramContext, keyboard,
settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction);
final Locale mostProbableLocale = mDictionaryFacilitator.getMostProbableLocale();
final Locale locale = mDictionaryFacilitator.getLocale();
final ArrayList<SuggestedWordInfo> suggestionsContainer =
getTransformedSuggestedWordInfoList(wordComposer, suggestionResults,
trailingSingleQuotesCount,
// For transforming suggestions that don't come for any dictionary, we
// use the currently most probable locale as it's our best bet.
mostProbableLocale);
locale);
boolean typedWordExistsInAnotherLanguage = false;
int qualityOfFoundSourceDictionary = QUALITY_NO_MATCH;
@ -191,7 +191,7 @@ public final class Suggest {
// Search for the best dictionary, defined as the first one with the highest match
// quality we can find.
if (typedWordString.equals(info.mWord)) {
if (mostProbableLocale.equals(info.mSourceDict.mLocale)) {
if (locale.equals(info.mSourceDict.mLocale)) {
if (qualityOfFoundSourceDictionary < QUALITY_MATCH_PREFERRED_LOCALE) {
// Use this source if the old match had lower quality than this match
sourceDictionaryOfRemovedWord = info.mSourceDict;
@ -217,8 +217,7 @@ public final class Suggest {
getWhitelistedWordInfoOrNull(suggestionsContainer);
final String whitelistedWord;
if (null != whitelistedWordInfo &&
(mDictionaryFacilitator.isConfidentAboutCurrentLanguageBeing(
whitelistedWordInfo.mSourceDict.mLocale)
(mDictionaryFacilitator.isForLocale(whitelistedWordInfo.mSourceDict.mLocale)
|| (!typedWordExistsInAnotherLanguage
&& !hasPlausibleCandidateInAnyOtherLanguage(suggestionsContainer,
consideredWord, whitelistedWordInfo)))) {
@ -351,7 +350,7 @@ public final class Suggest {
wordComposer.getComposedDataSnapshot(), ngramContext, keyboard,
settingsValuesForSuggestion, SESSION_ID_GESTURE, inputStyle);
// For transforming words that don't come from a dictionary, because it's our best bet
final Locale defaultLocale = mDictionaryFacilitator.getMostProbableLocale();
final Locale locale = mDictionaryFacilitator.getLocale();
final ArrayList<SuggestedWordInfo> suggestionsContainer =
new ArrayList<>(suggestionResults);
final int suggestionsCount = suggestionsContainer.size();
@ -362,7 +361,7 @@ public final class Suggest {
final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
final Locale wordlocale = wordInfo.mSourceDict.mLocale;
final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
wordInfo, null == wordlocale ? defaultLocale : wordlocale, isAllUpperCase,
wordInfo, null == wordlocale ? locale : wordlocale, isAllUpperCase,
isFirstCharCapitalized, 0 /* trailingSingleQuotesCount */);
suggestionsContainer.set(i, transformedWordInfo);
}

View File

@ -279,7 +279,6 @@ public final class InputLogic {
currentKeyboardScriptId, handler);
}
mDictionaryFacilitator.switchMostProbableLanguage(suggestionInfo.mSourceDict.mLocale);
final Event event = Event.createSuggestionPickedEvent(suggestionInfo);
final InputTransaction inputTransaction = new InputTransaction(settingsValues,
event, SystemClock.uptimeMillis(), mSpaceState, keyboardShiftState);
@ -2042,10 +2041,6 @@ public final class InputLogic {
final boolean isBatchMode = mWordComposer.isBatchMode();
commitChosenWord(settingsValues, stringToCommit,
LastComposedWord.COMMIT_TYPE_DECIDED_WORD, separator);
if (null != autoCorrectionOrNull) {
mDictionaryFacilitator.switchMostProbableLanguage(
autoCorrectionOrNull.mSourceDict.mLocale);
}
if (!typedWord.equals(stringToCommit)) {
// This will make the correction flash for a short while as a visual clue
// to the user that auto-correction happened. It has no other effect; in particular

View File

@ -33,7 +33,6 @@ public final class LanguageOnSpacebarUtils {
public static final int FORMAT_TYPE_NONE = 0;
public static final int FORMAT_TYPE_LANGUAGE_ONLY = 1;
public static final int FORMAT_TYPE_FULL_LOCALE = 2;
public static final int FORMAT_TYPE_MULTIPLE = 3;
private static List<InputMethodSubtype> sEnabledSubtypes = Collections.emptyList();
private static boolean sIsSystemLanguageSameAsInputLanguage;
@ -51,11 +50,11 @@ public final class LanguageOnSpacebarUtils {
if (sEnabledSubtypes.size() < 2 && sIsSystemLanguageSameAsInputLanguage) {
return FORMAT_TYPE_NONE;
}
final Locale[] locales = subtype.getLocales();
if (1 < locales.length) {
return FORMAT_TYPE_MULTIPLE;
final Locale locale = subtype.getLocale();
if (locale == null) {
return FORMAT_TYPE_NONE;
}
final String keyboardLanguage = locales[0].getLanguage();
final String keyboardLanguage = locale.getLanguage();
final String keyboardLayout = subtype.getKeyboardLayoutSetName();
int sameLanguageAndLayoutCount = 0;
for (final InputMethodSubtype ims : sEnabledSubtypes) {
@ -77,14 +76,7 @@ public final class LanguageOnSpacebarUtils {
public static void onSubtypeChanged(@Nonnull final RichInputMethodSubtype subtype,
final boolean implicitlyEnabledSubtype, @Nonnull final Locale systemLocale) {
final Locale[] newLocales = subtype.getLocales();
if (newLocales.length > 1) {
// In multi-locales mode, the system language is never the same as the input language
// because there is no single input language.
sIsSystemLanguageSameAsInputLanguage = false;
return;
}
final Locale newLocale = newLocales[0];
final Locale newLocale = subtype.getLocale();
if (systemLocale.equals(newLocale)) {
sIsSystemLanguageSameAsInputLanguage = true;
return;

View File

@ -1102,25 +1102,4 @@ public class BinaryDictionaryTests extends AndroidTestCase {
assertEquals(bigramProbability,
binaryDictionary.getNgramProbability(beginningOfSentenceContext, "bbb"));
}
public void testGetMaxFrequencyOfExactMatches() {
for (final int formatVersion : DICT_FORMAT_VERSIONS) {
testGetMaxFrequencyOfExactMatches(formatVersion);
}
}
private void testGetMaxFrequencyOfExactMatches(final int formatVersion) {
final BinaryDictionary binaryDictionary = getEmptyBinaryDictionary(formatVersion);
addUnigramWord(binaryDictionary, "abc", 10);
addUnigramWord(binaryDictionary, "aBc", 15);
assertEquals(15, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
addUnigramWord(binaryDictionary, "ab'c", 20);
assertEquals(20, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
addUnigramWord(binaryDictionary, "a-b-c", 25);
assertEquals(25, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
addUnigramWord(binaryDictionary, "ab-'-'-'-c", 30);
assertEquals(30, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
addUnigramWord(binaryDictionary, "ab c", 255);
assertEquals(30, binaryDictionary.getMaxFrequencyOfExactMatches("abc"));
}
}

View File

@ -29,28 +29,14 @@ public class DictionaryFacilitatorLruCacheTests extends AndroidTestCase {
final DictionaryFacilitator dictionaryFacilitatorEnUs = cache.get(Locale.US);
assertNotNull(dictionaryFacilitatorEnUs);
assertTrue(dictionaryFacilitatorEnUs.isForLocales(new Locale[] { Locale.US }));
assertTrue(dictionaryFacilitatorEnUs.isForLocale(Locale.US));
final DictionaryFacilitator dictionaryFacilitatorFr = cache.get(Locale.FRENCH);
assertNotNull(dictionaryFacilitatorEnUs);
assertTrue(dictionaryFacilitatorFr.isForLocales(new Locale[] { Locale.FRENCH }));
assertTrue(dictionaryFacilitatorFr.isForLocale(Locale.FRENCH));
final DictionaryFacilitator dictionaryFacilitatorDe = cache.get(Locale.GERMANY);
assertNotNull(dictionaryFacilitatorDe);
assertTrue(dictionaryFacilitatorDe.isForLocales(new Locale[] { Locale.GERMANY }));
}
public void testSetUseContactsDictionary() {
final DictionaryFacilitatorLruCache cache =
new DictionaryFacilitatorLruCache(getContext(), "");
assertNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
cache.setUseContactsDictionary(true /* useContactsDictionary */);
assertNotNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
assertNotNull(cache.get(Locale.FRENCH).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
assertNotNull(cache.get(Locale.GERMANY).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
cache.setUseContactsDictionary(false /* useContactsDictionary */);
assertNull(cache.get(Locale.GERMANY).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
assertNull(cache.get(Locale.US).getSubDictForTesting(Dictionary.TYPE_CONTACTS));
assertTrue(dictionaryFacilitatorDe.isForLocale(Locale.GERMANY));
}
}

View File

@ -1,56 +0,0 @@
/*
* Copyright (C) 2012 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.inputmethod.latin;
import android.test.AndroidTestCase;
import android.test.suitebuilder.annotation.SmallTest;
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
import com.android.inputmethod.latin.makedict.FusionDictionary;
import com.android.inputmethod.latin.makedict.ProbabilityInfo;
import com.android.inputmethod.latin.makedict.FusionDictionary.PtNodeArray;
import java.util.HashMap;
/**
* Unit test for FusionDictionary
*/
@SmallTest
public class FusionDictionaryTests extends AndroidTestCase {
public void testFindWordInTree() {
FusionDictionary dict = new FusionDictionary(new PtNodeArray(),
new DictionaryOptions(new HashMap<String,String>()));
dict.add("abc", new ProbabilityInfo(10), false /* isNotAWord */,
false /* isPossiblyOffensive */);
assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "abc"));
dict.add("aa", new ProbabilityInfo(10), false /* isNotAWord */,
false /* isPossiblyOffensive */);
assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aaa"));
assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "aa"));
dict.add("babcd", new ProbabilityInfo(10), false /* isNotAWord */,
false /* isPossiblyOffensive */);
dict.add("bacde", new ProbabilityInfo(10), false /* isNotAWord */,
false /* isPossiblyOffensive */);
assertNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "ba"));
assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "babcd"));
assertNotNull(FusionDictionary.findWordInTree(dict.mRootNodeArray, "bacde"));
}
}

View File

@ -164,17 +164,12 @@ public class RichInputMethodSubtypeTests extends AndroidTestCase {
final String subtypeName = SubtypeLocaleUtils
.getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
final String spacebarText = subtype.getFullDisplayName();
final Locale[] locales = subtype.getLocales();
if (1 == locales.length) {
final String languageName = SubtypeLocaleUtils
.getSubtypeLocaleDisplayName(locales[0].toString());
if (subtype.isNoLanguage()) {
assertFalse(subtypeName, spacebarText.contains(languageName));
} else {
assertTrue(subtypeName, spacebarText.contains(languageName));
}
final String languageName = SubtypeLocaleUtils
.getSubtypeLocaleDisplayName(subtype.getLocale().toString());
if (subtype.isNoLanguage()) {
assertFalse(subtypeName, spacebarText.contains(languageName));
} else {
// TODO: test multi-lingual subtype spacebar display
assertTrue(subtypeName, spacebarText.contains(languageName));
}
}
}
@ -183,12 +178,7 @@ public class RichInputMethodSubtypeTests extends AndroidTestCase {
for (final RichInputMethodSubtype subtype : mSubtypesList) {
final String subtypeName = SubtypeLocaleUtils
.getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
final Locale[] locales = subtype.getLocales();
if (locales.length > 1) {
// TODO: test multi-lingual subtype spacebar display
continue;
}
final Locale locale = locales[0];
final Locale locale = subtype.getLocale();
final Locale displayLocale = SubtypeLocaleUtils.getDisplayLocaleOfSubtypeLocale(
locale.toString());
if (Locale.ROOT.equals(displayLocale)) {

View File

@ -94,7 +94,7 @@ public class LanguageOnSpacebarUtilsTests extends AndroidTestCase {
final boolean implicitlyEnabledSubtype, final Locale systemLocale,
final int expectedFormat) {
LanguageOnSpacebarUtils.onSubtypeChanged(subtype, implicitlyEnabledSubtype, systemLocale);
assertEquals(subtype.getLocales()[0] + " implicitly=" + implicitlyEnabledSubtype
assertEquals(subtype.getLocale() + " implicitly=" + implicitlyEnabledSubtype
+ " in " + systemLocale, expectedFormat,
LanguageOnSpacebarUtils.getLanguageOnSpacebarFormatType(subtype));
}

View File

@ -147,19 +147,14 @@ public class SubtypeLocaleUtilsTests extends AndroidTestCase {
for (final RichInputMethodSubtype subtype : mSubtypesList) {
final String subtypeName = SubtypeLocaleUtils
.getSubtypeDisplayNameInSystemLocale(subtype.getRawSubtype());
final Locale[] locales = subtype.getLocales();
if (1 == locales.length) {
if (subtype.isNoLanguage()) {
final String layoutName = SubtypeLocaleUtils
.getKeyboardLayoutSetDisplayName(subtype.getRawSubtype());
assertTrue(subtypeName, subtypeName.contains(layoutName));
} else {
final String languageName = SubtypeLocaleUtils
.getSubtypeLocaleDisplayNameInSystemLocale(locales[0].toString());
assertTrue(subtypeName, subtypeName.contains(languageName));
}
if (subtype.isNoLanguage()) {
final String layoutName = SubtypeLocaleUtils
.getKeyboardLayoutSetDisplayName(subtype.getRawSubtype());
assertTrue(subtypeName, subtypeName.contains(layoutName));
} else {
// TODO: test multi-lingual subtype spacebar display
final String languageName = SubtypeLocaleUtils
.getSubtypeLocaleDisplayNameInSystemLocale(subtype.getLocale().toString());
assertTrue(subtypeName, subtypeName.contains(languageName));
}
}
}