aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/MainKeyboardView.java4
-rw-r--r--java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java17
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java259
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java29
-rw-r--r--java/src/com/android/inputmethod/latin/UserBinaryDictionary.java20
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java23
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java16
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java13
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java11
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java7
10 files changed, 200 insertions, 199 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
index e24d4e909..8f79a9128 100644
--- a/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/MainKeyboardView.java
@@ -772,7 +772,9 @@ public final class MainKeyboardView extends KeyboardView implements PointerTrack
}
public void onHideWindow() {
- mAccessibilityDelegate.onHideWindow();
+ if (AccessibilityUtils.getInstance().isAccessibilityEnabled()) {
+ mAccessibilityDelegate.onHideWindow();
+ }
}
/**
diff --git a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
index 09d0ea210..9bc01a2b1 100644
--- a/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ContactsBinaryDictionary.java
@@ -29,6 +29,7 @@ import android.provider.ContactsContract.Contacts;
import android.text.TextUtils;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.personalization.AccountUtils;
import com.android.inputmethod.latin.utils.StringUtils;
@@ -61,9 +62,6 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
/** The number of contacts in the most recent dictionary rebuild. */
static private int sContactCountAtLastRebuild = 0;
- /** The locale for this contacts dictionary. Controls name bigram predictions. */
- public final Locale mLocale;
-
private ContentObserver mObserver;
/**
@@ -71,11 +69,7 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
*/
private final boolean mUseFirstLastBigrams;
- public ContactsBinaryDictionary(final Context context, final Locale locale) {
- this(context, locale, null /* dictFile */);
- }
-
- public ContactsBinaryDictionary(final Context context, final Locale locale,
+ private ContactsBinaryDictionary(final Context context, final Locale locale,
final File dictFile) {
this(context, locale, dictFile, NAME);
}
@@ -84,12 +78,17 @@ public class ContactsBinaryDictionary extends ExpandableBinaryDictionary {
final File dictFile, final String name) {
super(context, getDictName(name, locale, dictFile), locale, Dictionary.TYPE_CONTACTS,
dictFile);
- mLocale = locale;
mUseFirstLastBigrams = useFirstLastBigramsForLocale(locale);
registerObserver(context);
reloadDictionaryIfRequired();
}
+ @UsedForTesting
+ public static ContactsBinaryDictionary getDictionary(final Context context, final Locale locale,
+ final File dictFile) {
+ return new ContactsBinaryDictionary(context, locale, dictFile);
+ }
+
private synchronized void registerObserver(final Context context) {
if (mObserver != null) return;
ContentResolver cres = context.getContentResolver();
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index b6fcbd1d6..627793f18 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -24,7 +24,6 @@ import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
-import com.android.inputmethod.latin.personalization.PersonalizationHelper;
import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.ExecutorUtils;
@@ -32,10 +31,14 @@ import com.android.inputmethod.latin.utils.LanguageModelParam;
import com.android.inputmethod.latin.utils.SuggestionResults;
import java.io.File;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
+import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -54,7 +57,7 @@ public class DictionaryFacilitatorForSuggest {
// To synchronize assigning mDictionaries to ensure closing dictionaries.
private Object mLock = new Object();
- private static final String[] dictTypesOrderedToGetSuggestion =
+ private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTION =
new String[] {
Dictionary.TYPE_MAIN,
Dictionary.TYPE_USER_HISTORY,
@@ -63,13 +66,30 @@ public class DictionaryFacilitatorForSuggest {
Dictionary.TYPE_CONTACTS
};
+ private static final Map<String, Class<? extends ExpandableBinaryDictionary>>
+ DICT_TYPE_TO_CLASS = CollectionUtils.newHashMap();
+
+ static {
+ DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER_HISTORY, UserHistoryDictionary.class);
+ DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_PERSONALIZATION, PersonalizationDictionary.class);
+ DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_USER, UserBinaryDictionary.class);
+ DICT_TYPE_TO_CLASS.put(Dictionary.TYPE_CONTACTS, ContactsBinaryDictionary.class);
+ }
+
+ private static final String DICT_FACTORY_METHOD_NAME = "getDictionary";
+ private static final Class<?>[] DICT_FACTORY_METHOD_ARG_TYPES =
+ new Class[] { Context.class, Locale.class, File.class };
+
+ private static final String[] SUB_DICT_TYPES =
+ Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTION, 1 /* start */,
+ DICT_TYPES_ORDERED_TO_GET_SUGGESTION.length);
+
/**
* Class contains dictionaries for a locale.
*/
private static class Dictionaries {
public final Locale mLocale;
- public final ConcurrentHashMap<String, Dictionary> mDictMap =
- CollectionUtils.newConcurrentHashMap();
+ private Dictionary mMainDict;
public final ConcurrentHashMap<String, ExpandableBinaryDictionary> mSubDictMap =
CollectionUtils.newConcurrentHashMap();
@@ -78,41 +98,36 @@ public class DictionaryFacilitatorForSuggest {
}
public Dictionaries(final Locale locale, final Dictionary mainDict,
- final ExpandableBinaryDictionary contactsDict,
- final ExpandableBinaryDictionary userDict,
- final ExpandableBinaryDictionary userHistoryDict,
- final ExpandableBinaryDictionary personalizationDict) {
+ final Map<String, ExpandableBinaryDictionary> subDicts) {
mLocale = locale;
// Main dictionary can be asynchronously loaded.
setMainDict(mainDict);
- setSubDict(Dictionary.TYPE_CONTACTS, contactsDict);
- setSubDict(Dictionary.TYPE_USER, userDict);
- setSubDict(Dictionary.TYPE_USER_HISTORY, userHistoryDict);
- setSubDict(Dictionary.TYPE_PERSONALIZATION, personalizationDict);
+ for (final Map.Entry<String, ExpandableBinaryDictionary> entry : subDicts.entrySet()) {
+ setSubDict(entry.getKey(), entry.getValue());
+ }
}
private void setSubDict(final String dictType, final ExpandableBinaryDictionary dict) {
if (dict != null) {
- mDictMap.put(dictType, dict);
mSubDictMap.put(dictType, dict);
}
}
public void setMainDict(final Dictionary mainDict) {
// Close old dictionary if exists. Main dictionary can be assigned multiple times.
- final Dictionary oldDict;
- if (mainDict != null) {
- oldDict = mDictMap.put(Dictionary.TYPE_MAIN, mainDict);
- } else {
- oldDict = mDictMap.remove(Dictionary.TYPE_MAIN);
- }
+ final Dictionary oldDict = mMainDict;
+ mMainDict = mainDict;
if (oldDict != null && mainDict != oldDict) {
oldDict.close();
}
}
- public Dictionary getMainDict() {
- return mDictMap.get(Dictionary.TYPE_MAIN);
+ public Dictionary getDict(final String dictType) {
+ if (Dictionary.TYPE_MAIN.equals(dictType)) {
+ return mMainDict;
+ } else {
+ return getSubDict(dictType);
+ }
}
public ExpandableBinaryDictionary getSubDict(final String dictType) {
@@ -120,12 +135,20 @@ public class DictionaryFacilitatorForSuggest {
}
public boolean hasDict(final String dictType) {
- return mDictMap.containsKey(dictType);
+ if (Dictionary.TYPE_MAIN.equals(dictType)) {
+ return mMainDict != null;
+ } else {
+ return mSubDictMap.containsKey(dictType);
+ }
}
public void closeDict(final String dictType) {
- final Dictionary dict = mDictMap.remove(dictType);
- mSubDictMap.remove(dictType);
+ final Dictionary dict;
+ if (Dictionary.TYPE_MAIN.equals(dictType)) {
+ dict = mMainDict;
+ } else {
+ dict = mSubDictMap.remove(dictType);
+ }
if (dict != null) {
dict.close();
}
@@ -142,6 +165,26 @@ public class DictionaryFacilitatorForSuggest {
return mDictionaries.mLocale;
}
+ private static ExpandableBinaryDictionary getSubDict(final String dictType,
+ final Context context, final Locale locale, final File dictFile) {
+ final Class<? extends ExpandableBinaryDictionary> dictClass =
+ DICT_TYPE_TO_CLASS.get(dictType);
+ if (dictClass == null) {
+ return null;
+ }
+ try {
+ final Method factoryMethod = dictClass.getMethod(DICT_FACTORY_METHOD_NAME,
+ DICT_FACTORY_METHOD_ARG_TYPES);
+ final Object dict = factoryMethod.invoke(null /* obj */,
+ new Object[] { context, locale, dictFile });
+ return (ExpandableBinaryDictionary) dict;
+ } catch (final NoSuchMethodException | SecurityException | IllegalAccessException
+ | IllegalArgumentException | InvocationTargetException e) {
+ Log.e(TAG, "Cannot create dictionary: " + dictType, e);
+ return null;
+ }
+ }
+
public void resetDictionaries(final Context context, final Locale newLocale,
final boolean useContactsDict, final boolean usePersonalizedDicts,
final boolean forceReloadMainDictionary,
@@ -149,64 +192,44 @@ public class DictionaryFacilitatorForSuggest {
final boolean localeHasBeenChanged = !newLocale.equals(mDictionaries.mLocale);
// We always try to have the main dictionary. Other dictionaries can be unused.
final boolean reloadMainDictionary = localeHasBeenChanged || forceReloadMainDictionary;
- final boolean closeContactsDictionary = localeHasBeenChanged || !useContactsDict;
- final boolean closeUserDictionary = localeHasBeenChanged;
- final boolean closeUserHistoryDictionary = localeHasBeenChanged || !usePersonalizedDicts;
- final boolean closePersonalizationDictionary =
- localeHasBeenChanged || !usePersonalizedDicts;
+ // TODO: Make subDictTypesToUse configurable by resource or a static final list.
+ final Set<String> subDictTypesToUse = CollectionUtils.newHashSet();
+ if (useContactsDict) {
+ subDictTypesToUse.add(Dictionary.TYPE_CONTACTS);
+ }
+ subDictTypesToUse.add(Dictionary.TYPE_USER);
+ if (usePersonalizedDicts) {
+ subDictTypesToUse.add(Dictionary.TYPE_USER_HISTORY);
+ subDictTypesToUse.add(Dictionary.TYPE_PERSONALIZATION);
+ }
final Dictionary newMainDict;
if (reloadMainDictionary) {
// The main dictionary will be asynchronously loaded.
newMainDict = null;
} else {
- newMainDict = mDictionaries.getMainDict();
- }
-
- // Open or move contacts dictionary.
- final ExpandableBinaryDictionary newContactsDict;
- if (!closeContactsDictionary && mDictionaries.hasDict(Dictionary.TYPE_CONTACTS)) {
- newContactsDict = mDictionaries.getSubDict(Dictionary.TYPE_CONTACTS);
- } else if (useContactsDict) {
- newContactsDict = new ContactsBinaryDictionary(context, newLocale);
- } else {
- newContactsDict = null;
- }
-
- // Open or move user dictionary.
- final ExpandableBinaryDictionary newUserDictionary;
- if (!closeUserDictionary && mDictionaries.hasDict(Dictionary.TYPE_USER)) {
- newUserDictionary = mDictionaries.getSubDict(Dictionary.TYPE_USER);
- } else {
- newUserDictionary = new UserBinaryDictionary(context, newLocale);
- mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context);
+ newMainDict = mDictionaries.getDict(Dictionary.TYPE_MAIN);
}
- // Open or move user history dictionary.
- final ExpandableBinaryDictionary newUserHistoryDict;
- if (!closeUserHistoryDictionary && mDictionaries.hasDict(Dictionary.TYPE_USER_HISTORY)) {
- newUserHistoryDict = mDictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
- } else if (usePersonalizedDicts) {
- newUserHistoryDict = PersonalizationHelper.getUserHistoryDictionary(context, newLocale);
- } else {
- newUserHistoryDict = null;
- }
-
- // Open or move personalization dictionary.
- final ExpandableBinaryDictionary newPersonalizationDict;
- if (!closePersonalizationDictionary
- && mDictionaries.hasDict(Dictionary.TYPE_PERSONALIZATION)) {
- newPersonalizationDict = mDictionaries.getSubDict(Dictionary.TYPE_PERSONALIZATION);
- } else if (usePersonalizedDicts) {
- newPersonalizationDict =
- PersonalizationHelper.getPersonalizationDictionary(context, newLocale);
- } else {
- newPersonalizationDict = null;
+ final Map<String, ExpandableBinaryDictionary> subDicts = CollectionUtils.newHashMap();
+ for (final String dictType : SUB_DICT_TYPES) {
+ if (!subDictTypesToUse.contains(dictType)) {
+ // This dictionary will not be used.
+ continue;
+ }
+ final ExpandableBinaryDictionary dict;
+ if (!localeHasBeenChanged && mDictionaries.hasDict(dictType)) {
+ // Continue to use current dictionary.
+ dict = mDictionaries.getSubDict(dictType);
+ } else {
+ // Start to use new dictionary.
+ dict = getSubDict(dictType, context, newLocale, null /* dictFile */);
+ }
+ subDicts.put(dictType, dict);
}
// Replace Dictionaries.
- final Dictionaries newDictionaries = new Dictionaries(newLocale, newMainDict,
- newContactsDict, newUserDictionary, newUserHistoryDict, newPersonalizationDict);
+ final Dictionaries newDictionaries = new Dictionaries(newLocale, newMainDict, subDicts);
final Dictionaries oldDictionaries;
synchronized (mLock) {
oldDictionaries = mDictionaries;
@@ -218,24 +241,15 @@ public class DictionaryFacilitatorForSuggest {
if (listener != null) {
listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary());
}
-
// Clean up old dictionaries.
if (reloadMainDictionary) {
oldDictionaries.closeDict(Dictionary.TYPE_MAIN);
}
- if (closeContactsDictionary) {
- oldDictionaries.closeDict(Dictionary.TYPE_CONTACTS);
- }
- if (closeUserDictionary) {
- oldDictionaries.closeDict(Dictionary.TYPE_USER);
- }
- if (closeUserHistoryDictionary) {
- oldDictionaries.closeDict(Dictionary.TYPE_USER_HISTORY);
- }
- if (closePersonalizationDictionary) {
- oldDictionaries.closeDict(Dictionary.TYPE_PERSONALIZATION);
+ for (final String dictType : SUB_DICT_TYPES) {
+ if (localeHasBeenChanged || !subDictTypesToUse.contains(dictType)) {
+ oldDictionaries.closeDict(dictType);
+ }
}
- oldDictionaries.mDictMap.clear();
oldDictionaries.mSubDictMap.clear();
}
@@ -269,52 +283,28 @@ public class DictionaryFacilitatorForSuggest {
final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
final Map<String, Map<String, String>> additionalDictAttributes) {
Dictionary mainDictionary = null;
- ContactsBinaryDictionary contactsDictionary = null;
- UserBinaryDictionary userDictionary = null;
- UserHistoryDictionary userHistoryDictionary = null;
- PersonalizationDictionary personalizationDictionary = null;
+ final Map<String, ExpandableBinaryDictionary> subDicts = CollectionUtils.newHashMap();
for (final String dictType : dictionaryTypes) {
if (dictType.equals(Dictionary.TYPE_MAIN)) {
mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context, locale);
- } else if (dictType.equals(Dictionary.TYPE_USER_HISTORY)) {
- userHistoryDictionary =
- PersonalizationHelper.getUserHistoryDictionary(context, locale);
- // Staring with an empty user history dictionary for testing.
- // Testing program may populate this dictionary before actual testing.
- userHistoryDictionary.reloadDictionaryIfRequired();
- userHistoryDictionary.waitAllTasksForTests();
+ } else {
+ final File dictFile = dictionaryFiles.get(dictType);
+ final ExpandableBinaryDictionary dict = getSubDict(
+ dictType, context, locale, dictFile);
if (additionalDictAttributes.containsKey(dictType)) {
- userHistoryDictionary.clearAndFlushDictionaryWithAdditionalAttributes(
+ dict.clearAndFlushDictionaryWithAdditionalAttributes(
additionalDictAttributes.get(dictType));
}
- } else if (dictType.equals(Dictionary.TYPE_PERSONALIZATION)) {
- personalizationDictionary =
- PersonalizationHelper.getPersonalizationDictionary(context, locale);
- // Staring with an empty personalization dictionary for testing.
- // Testing program may populate this dictionary before actual testing.
- personalizationDictionary.reloadDictionaryIfRequired();
- personalizationDictionary.waitAllTasksForTests();
- if (additionalDictAttributes.containsKey(dictType)) {
- personalizationDictionary.clearAndFlushDictionaryWithAdditionalAttributes(
- additionalDictAttributes.get(dictType));
+ if (dict == null) {
+ throw new RuntimeException("Unknown dictionary type: " + dictType);
}
- } else if (dictType.equals(Dictionary.TYPE_USER)) {
- final File file = dictionaryFiles.get(dictType);
- userDictionary = new UserBinaryDictionary(context, locale, file);
- userDictionary.reloadDictionaryIfRequired();
- userDictionary.waitAllTasksForTests();
- } else if (dictType.equals(Dictionary.TYPE_CONTACTS)) {
- final File file = dictionaryFiles.get(dictType);
- contactsDictionary = new ContactsBinaryDictionary(context, locale, file);
- contactsDictionary.reloadDictionaryIfRequired();
- contactsDictionary.waitAllTasksForTests();
- } else {
- throw new RuntimeException("Unknown dictionary type: " + dictType);
+ dict.reloadDictionaryIfRequired();
+ dict.waitAllTasksForTests();
+ subDicts.put(dictType, dict);
}
}
- mDictionaries = new Dictionaries(locale, mainDictionary, contactsDictionary,
- userDictionary, userHistoryDictionary, personalizationDictionary);
+ mDictionaries = new Dictionaries(locale, mainDictionary, subDicts);
}
public void closeDictionaries() {
@@ -323,15 +313,15 @@ public class DictionaryFacilitatorForSuggest {
dictionaries = mDictionaries;
mDictionaries = new Dictionaries();
}
- for (final Dictionary dict : dictionaries.mDictMap.values()) {
- dict.close();
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ dictionaries.closeDict(dictType);
}
}
// The main dictionary could have been loaded asynchronously. Don't cache the return value
// of this method.
public boolean hasInitializedMainDictionary() {
- final Dictionary mainDict = mDictionaries.getMainDict();
+ final Dictionary mainDict = mDictionaries.getDict(Dictionary.TYPE_MAIN);
return mainDict != null && mainDict.isInitialized();
}
@@ -408,7 +398,7 @@ public class DictionaryFacilitatorForSuggest {
// consolidation is done.
// TODO: Remove this hack when ready.
final int lowerCaseFreqInMainDict = dictionaries.hasDict(Dictionary.TYPE_MAIN) ?
- dictionaries.getMainDict().getFrequency(suggestionLowerCase) :
+ dictionaries.getDict(Dictionary.TYPE_MAIN).getFrequency(suggestionLowerCase) :
Dictionary.NOT_A_PROBABILITY;
if (maxFreq < lowerCaseFreqInMainDict
&& lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
@@ -439,12 +429,11 @@ public class DictionaryFacilitatorForSuggest {
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
final int sessionId, final ArrayList<SuggestedWordInfo> rawSuggestions) {
final Dictionaries dictionaries = mDictionaries;
- final Map<String, Dictionary> dictMap = dictionaries.mDictMap;
final SuggestionResults suggestionResults =
new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS);
final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
- for (final String dictType : dictTypesOrderedToGetSuggestion) {
- final Dictionary dictionary = dictMap.get(dictType);
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ final Dictionary dictionary = dictionaries.getDict(dictType);
if (null == dictionary) continue;
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
dictionary.getSuggestionsWithSessionId(composer, prevWord, proximityInfo,
@@ -460,11 +449,11 @@ public class DictionaryFacilitatorForSuggest {
}
public boolean isValidMainDictWord(final String word) {
- final Dictionaries dictionaries = mDictionaries;
- if (TextUtils.isEmpty(word) || !dictionaries.hasDict(Dictionary.TYPE_MAIN)) {
+ final Dictionary mainDict = mDictionaries.getDict(Dictionary.TYPE_MAIN);
+ if (TextUtils.isEmpty(word) || mainDict == null) {
return false;
}
- return dictionaries.getMainDict().isValidWord(word);
+ return mainDict.isValidWord(word);
}
public boolean isValidWord(final String word, final boolean ignoreCase) {
@@ -476,8 +465,8 @@ public class DictionaryFacilitatorForSuggest {
return false;
}
final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
- final Map<String, Dictionary> dictMap = dictionaries.mDictMap;
- for (final Dictionary dictionary : dictMap.values()) {
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ final Dictionary dictionary = dictionaries.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.
@@ -495,8 +484,10 @@ public class DictionaryFacilitatorForSuggest {
return Dictionary.NOT_A_PROBABILITY;
}
int maxFreq = -1;
- final Map<String, Dictionary> dictMap = mDictionaries.mDictMap;
- for (final Dictionary dictionary : dictMap.values()) {
+ final Dictionaries dictionaries = mDictionaries;
+ for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
+ final Dictionary dictionary = dictionaries.getDict(dictType);
+ if (dictionary == null) continue;
final int tempFreq = dictionary.getFrequency(word);
if (tempFreq >= maxFreq) {
maxFreq = tempFreq;
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 550db4a6c..c825ca462 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -97,6 +97,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
private final ReentrantReadWriteLock mLock;
+ private Map<String, String> mAdditionalAttributeMap = null;
+
/* A extension for a binary dictionary file. */
protected static final String DICT_FILE_EXTENSION = ".dict";
@@ -196,6 +198,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
protected Map<String, String> getHeaderAttributeMap() {
HashMap<String, String> attributeMap = new HashMap<String, String>();
+ if (mAdditionalAttributeMap != null) {
+ attributeMap.putAll(mAdditionalAttributeMap);
+ }
attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, mDictName);
attributeMap.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, mLocale.toString());
attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
@@ -523,17 +528,17 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
} else if (mBinaryDictionary == null) {
// Otherwise, load the existing dictionary.
loadBinaryDictionaryLocked();
+ if (mBinaryDictionary != null && !(isValidDictionaryLocked()
+ // TODO: remove the check below
+ && matchesExpectedBinaryDictFormatVersionForThisType(
+ mBinaryDictionary.getFormatVersion()))) {
+ // Binary dictionary or its format version is not valid. Regenerate
+ // the dictionary file. writeBinaryDictionary will remove the
+ // existing files if appropriate.
+ createNewDictionaryLocked();
+ }
}
mNeedsToReload = false;
- if (mBinaryDictionary != null && !(isValidDictionaryLocked()
- // TODO: remove the check below
- && matchesExpectedBinaryDictFormatVersionForThisType(
- mBinaryDictionary.getFormatVersion()))) {
- // Binary dictionary or its format version is not valid. Regenerate
- // the dictionary file. writeBinaryDictionary will remove the
- // existing files if appropriate.
- createNewDictionaryLocked();
- }
} finally {
mIsReloading.set(false);
}
@@ -592,6 +597,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
@UsedForTesting
+ public void clearAndFlushDictionaryWithAdditionalAttributes(
+ final Map<String, String> attributeMap) {
+ mAdditionalAttributeMap = attributeMap;
+ clear();
+ }
+
public void dumpAllWordsForDebug() {
reloadDictionaryIfRequired();
asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() {
diff --git a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
index 2006a5c89..e1cda696c 100644
--- a/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/UserBinaryDictionary.java
@@ -28,6 +28,7 @@ import android.provider.UserDictionary.Words;
import android.text.TextUtils;
import android.util.Log;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.compat.UserDictionaryCompatUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -66,17 +67,8 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
final private String mLocale;
final private boolean mAlsoUseMoreRestrictiveLocales;
- public UserBinaryDictionary(final Context context, final Locale locale) {
- this(context, locale, false /* alsoUseMoreRestrictiveLocales */, null /* dictFile */);
- }
-
- public UserBinaryDictionary(final Context context, final Locale locale, final File dictFile) {
- this(context, locale, false /* alsoUseMoreRestrictiveLocales */, dictFile);
- }
-
- public UserBinaryDictionary(final Context context, final Locale locale,
- final boolean alsoUseMoreRestrictiveLocales, final File dictFile) {
- this(context, locale, alsoUseMoreRestrictiveLocales, dictFile, NAME);
+ private UserBinaryDictionary(final Context context, final Locale locale, final File dictFile) {
+ this(context, locale, false /* alsoUseMoreRestrictiveLocales */, dictFile, NAME);
}
protected UserBinaryDictionary(final Context context, final Locale locale,
@@ -113,6 +105,12 @@ public class UserBinaryDictionary extends ExpandableBinaryDictionary {
reloadDictionaryIfRequired();
}
+ @UsedForTesting
+ public static UserBinaryDictionary getDictionary(final Context context, final Locale locale,
+ final File dictFile) {
+ return new UserBinaryDictionary(context, locale, dictFile);
+ }
+
@Override
public synchronized void close() {
if (mObserver != null) {
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index d2100d415..75432fbac 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -784,11 +784,11 @@ public final class InputLogic {
// TODO: remove this argument
final LatinIME.UIHandler handler) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
+ final SettingsValues settingsValues = inputTransaction.mSettingsValues;
boolean didAutoCorrect = false;
// We avoid sending spaces in languages without spaces if we were composing.
final boolean shouldAvoidSendingCode = Constants.CODE_SPACE == codePoint
- && !inputTransaction.mSettingsValues.mSpacingAndPunctuations
- .mCurrentLanguageHasSpaces
+ && !settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces
&& mWordComposer.isComposingWord();
if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) {
// If we are in the middle of a recorrection, we need to commit the recorrection
@@ -798,13 +798,13 @@ public final class InputLogic {
}
// isComposingWord() may have changed since we stored wasComposing
if (mWordComposer.isComposingWord()) {
- if (inputTransaction.mSettingsValues.mCorrectionEnabled) {
+ if (settingsValues.mCorrectionEnabled) {
final String separator = shouldAvoidSendingCode ? LastComposedWord.NOT_A_SEPARATOR
: StringUtils.newSingleCodePointString(codePoint);
- commitCurrentAutoCorrection(inputTransaction.mSettingsValues, separator, handler);
+ commitCurrentAutoCorrection(settingsValues, separator, handler);
didAutoCorrect = true;
} else {
- commitTyped(inputTransaction.mSettingsValues,
+ commitTyped(settingsValues,
StringUtils.newSingleCodePointString(codePoint));
}
}
@@ -821,20 +821,23 @@ public final class InputLogic {
// Double quotes behave like they are usually preceded by space iff we are
// not inside a double quote or after a digit.
needsPrecedingSpace = !isInsideDoubleQuoteOrAfterDigit;
+ } else if (settingsValues.mSpacingAndPunctuations.isClusteringSymbol(codePoint)
+ && settingsValues.mSpacingAndPunctuations.isClusteringSymbol(
+ mConnection.getCodePointBeforeCursor())) {
+ needsPrecedingSpace = false;
} else {
- needsPrecedingSpace = inputTransaction.mSettingsValues.isUsuallyPrecededBySpace(
- codePoint);
+ needsPrecedingSpace = settingsValues.isUsuallyPrecededBySpace(codePoint);
}
if (needsPrecedingSpace) {
- promotePhantomSpace(inputTransaction.mSettingsValues);
+ promotePhantomSpace(settingsValues);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
ResearchLogger.latinIME_handleSeparator(codePoint, mWordComposer.isComposingWord());
}
if (!shouldAvoidSendingCode) {
- sendKeyCodePoint(inputTransaction.mSettingsValues, codePoint);
+ sendKeyCodePoint(settingsValues, codePoint);
}
if (Constants.CODE_SPACE == codePoint) {
@@ -852,7 +855,7 @@ public final class InputLogic {
swapSwapperAndSpace(inputTransaction);
mSpaceState = SpaceState.SWAP_PUNCTUATION;
} else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
- && inputTransaction.mSettingsValues.isUsuallyFollowedBySpace(codePoint))
+ && settingsValues.isUsuallyFollowedBySpace(codePoint))
|| (Constants.CODE_DOUBLE_QUOTE == codePoint
&& isInsideDoubleQuoteOrAfterDigit)) {
// If we are in phantom space state, and the user presses a separator, we want to
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 352288f8b..38c28a734 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -18,15 +18,11 @@ package com.android.inputmethod.latin.personalization;
import android.content.Context;
-import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.ExpandableBinaryDictionary;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
-import com.android.inputmethod.latin.utils.LanguageModelParam;
import java.io.File;
-import java.util.ArrayList;
import java.util.Locale;
import java.util.Map;
@@ -47,8 +43,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
/** The locale for this dictionary. */
public final Locale mLocale;
- private Map<String, String> mAdditionalAttributeMap = null;
-
protected DecayingExpandableBinaryDictionaryBase(final Context context,
final String dictName, final Locale locale, final String dictionaryType,
final File dictFile) {
@@ -72,9 +66,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
@Override
protected Map<String, String> getHeaderAttributeMap() {
final Map<String, String> attributeMap = super.getHeaderAttributeMap();
- if (mAdditionalAttributeMap != null) {
- attributeMap.putAll(mAdditionalAttributeMap);
- }
attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
@@ -92,13 +83,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
// No initial contents.
}
- @UsedForTesting
- public void clearAndFlushDictionaryWithAdditionalAttributes(
- final Map<String, String> attributeMap) {
- mAdditionalAttributeMap = attributeMap;
- clear();
- }
-
/* package */ void runGCIfRequired() {
runGCIfRequired(false /* mindsBlockByGC */);
}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
index 4afd5b4c9..1423fceff 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin.personalization;
import android.content.Context;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Dictionary;
import java.io.File;
@@ -26,14 +27,16 @@ import java.util.Locale;
public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase {
/* package */ static final String NAME = PersonalizationDictionary.class.getSimpleName();
+ // TODO: Make this constructor private
/* package */ PersonalizationDictionary(final Context context, final Locale locale) {
- this(context, locale, null /* dictFile */);
+ super(context, getDictName(NAME, locale, null /* dictFile */), locale,
+ Dictionary.TYPE_PERSONALIZATION, null /* dictFile */);
}
- public PersonalizationDictionary(final Context context, final Locale locale,
- final File dictFile) {
- super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_PERSONALIZATION,
- dictFile);
+ @UsedForTesting
+ public static PersonalizationDictionary getDictionary(final Context context,
+ final Locale locale, final File dictFile) {
+ return PersonalizationHelper.getPersonalizationDictionary(context, locale);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
index 8a29c354d..818cd9a5f 100644
--- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java
@@ -18,6 +18,7 @@ package com.android.inputmethod.latin.personalization;
import android.content.Context;
+import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.ExpandableBinaryDictionary;
@@ -32,14 +33,16 @@ import java.util.Locale;
public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase {
/* package */ static final String NAME = UserHistoryDictionary.class.getSimpleName();
+ // TODO: Make this constructor private
/* package */ UserHistoryDictionary(final Context context, final Locale locale) {
- this(context, locale, null /* dictFile */);
+ super(context, getDictName(NAME, locale, null /* dictFile */), locale,
+ Dictionary.TYPE_USER_HISTORY, null /* dictFile */);
}
- public UserHistoryDictionary(final Context context, final Locale locale,
+ @UsedForTesting
+ public static UserHistoryDictionary getDictionary(final Context context, final Locale locale,
final File dictFile) {
- super(context, getDictName(NAME, locale, dictFile), locale, Dictionary.TYPE_USER_HISTORY,
- dictFile);
+ return PersonalizationHelper.getUserHistoryDictionary(context, locale);
}
@Override
diff --git a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
index 796921f71..b8d2a2248 100644
--- a/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
+++ b/java/src/com/android/inputmethod/latin/settings/SpacingAndPunctuations.java
@@ -30,6 +30,7 @@ import java.util.Locale;
public final class SpacingAndPunctuations {
private final int[] mSortedSymbolsPrecededBySpace;
private final int[] mSortedSymbolsFollowedBySpace;
+ private final int[] mSortedSymbolsClusteringTogether;
private final int[] mSortedWordConnectors;
public final int[] mSortedWordSeparators;
public final PunctuationSuggestions mSuggestPuncList;
@@ -46,6 +47,8 @@ public final class SpacingAndPunctuations {
// To be able to binary search the code point. See {@link #isUsuallyFollowedBySpace(int)}.
mSortedSymbolsFollowedBySpace = StringUtils.toSortedCodePointArray(
res.getString(R.string.symbols_followed_by_space));
+ mSortedSymbolsClusteringTogether = StringUtils.toSortedCodePointArray(
+ res.getString(R.string.symbols_clustering_together));
// To be able to binary search the code point. See {@link #isWordConnector(int)}.
mSortedWordConnectors = StringUtils.toSortedCodePointArray(
res.getString(R.string.symbols_word_connectors));
@@ -85,6 +88,10 @@ public final class SpacingAndPunctuations {
return Arrays.binarySearch(mSortedSymbolsFollowedBySpace, code) >= 0;
}
+ public boolean isClusteringSymbol(final int code) {
+ return Arrays.binarySearch(mSortedSymbolsClusteringTogether, code) >= 0;
+ }
+
public boolean isSentenceSeparator(final int code) {
return code == mSentenceSeparator;
}