am adfb2627: Remove logic related to dictionary loading from LatinIME.
* commit 'adfb262797023c4ca57bb470e547f90c88f638ca': Remove logic related to dictionary loading from LatinIME.main
commit
ab0f3721fa
|
@ -26,15 +26,14 @@ 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.settings.SettingsValues;
|
||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||
import com.android.inputmethod.latin.utils.ExecutorUtils;
|
||||
import com.android.inputmethod.latin.utils.LanguageModelParam;
|
||||
import com.android.inputmethod.latin.utils.SuggestionResults;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
@ -50,197 +49,314 @@ public class DictionaryFacilitatorForSuggest {
|
|||
// dictionary.
|
||||
private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140;
|
||||
|
||||
private final Context mContext;
|
||||
private Dictionaries mDictionaries = new Dictionaries();
|
||||
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
|
||||
// To synchronize assigning mDictionaries to ensure closing dictionaries.
|
||||
private Object mLock = new Object();
|
||||
|
||||
/**
|
||||
* Class contains dictionaries for a locale.
|
||||
*/
|
||||
private static class Dictionaries {
|
||||
public final Locale mLocale;
|
||||
|
||||
private final ConcurrentHashMap<String, Dictionary> mDictionaries =
|
||||
public final ConcurrentHashMap<String, Dictionary> mDictMap =
|
||||
CollectionUtils.newConcurrentHashMap();
|
||||
// Main dictionary will be asynchronously loaded.
|
||||
public Dictionary mMainDictionary;
|
||||
public final ContactsBinaryDictionary mContactsDictionary;
|
||||
public final UserBinaryDictionary mUserDictionary;
|
||||
public final UserHistoryDictionary mUserHistoryDictionary;
|
||||
public final PersonalizationDictionary mPersonalizationDictionary;
|
||||
|
||||
private Dictionary mMainDictionary;
|
||||
private ContactsBinaryDictionary mContactsDictionary;
|
||||
private UserBinaryDictionary mUserDictionary;
|
||||
private UserHistoryDictionary mUserHistoryDictionary;
|
||||
private PersonalizationDictionary mPersonalizationDictionary;
|
||||
public Dictionaries() {
|
||||
mLocale = null;
|
||||
mMainDictionary = null;
|
||||
mContactsDictionary = null;
|
||||
mUserDictionary = null;
|
||||
mUserHistoryDictionary = null;
|
||||
mPersonalizationDictionary = null;
|
||||
}
|
||||
|
||||
private final CountDownLatch mLatchForWaitingLoadingMainDictionary;
|
||||
public Dictionaries(final Locale locale, final Dictionary mainDict,
|
||||
final ContactsBinaryDictionary contactsDict, final UserBinaryDictionary userDict,
|
||||
final UserHistoryDictionary userHistoryDict,
|
||||
final PersonalizationDictionary personalizationDict) {
|
||||
mLocale = locale;
|
||||
setMainDict(mainDict);
|
||||
mContactsDictionary = contactsDict;
|
||||
if (mContactsDictionary != null) {
|
||||
mDictMap.put(Dictionary.TYPE_CONTACTS, mContactsDictionary);
|
||||
}
|
||||
mUserDictionary = userDict;
|
||||
if (mUserDictionary != null) {
|
||||
mDictMap.put(Dictionary.TYPE_USER, mUserDictionary);
|
||||
}
|
||||
mUserHistoryDictionary = userHistoryDict;
|
||||
if (mUserHistoryDictionary != null) {
|
||||
mDictMap.put(Dictionary.TYPE_USER_HISTORY, mUserHistoryDictionary);
|
||||
}
|
||||
mPersonalizationDictionary = personalizationDict;
|
||||
if (mPersonalizationDictionary != null) {
|
||||
mDictMap.put(Dictionary.TYPE_PERSONALIZATION, mPersonalizationDictionary);
|
||||
}
|
||||
}
|
||||
|
||||
public void setMainDict(final Dictionary mainDict) {
|
||||
mMainDictionary = mainDict;
|
||||
// Close old dictionary if exists. Main dictionary can be assigned multiple times.
|
||||
final Dictionary oldDict;
|
||||
if (mMainDictionary != null) {
|
||||
oldDict = mDictMap.put(Dictionary.TYPE_MAIN, mMainDictionary);
|
||||
} else {
|
||||
oldDict = mDictMap.remove(Dictionary.TYPE_MAIN);
|
||||
}
|
||||
if (oldDict != null && mMainDictionary != oldDict) {
|
||||
oldDict.close();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasMainDict() {
|
||||
return mMainDictionary != null;
|
||||
}
|
||||
|
||||
public boolean hasContactsDict() {
|
||||
return mContactsDictionary != null;
|
||||
}
|
||||
|
||||
public boolean hasUserDict() {
|
||||
return mUserDictionary != null;
|
||||
}
|
||||
|
||||
public boolean hasUserHistoryDict() {
|
||||
return mUserHistoryDictionary != null;
|
||||
}
|
||||
|
||||
public boolean hasPersonalizationDict() {
|
||||
return mPersonalizationDictionary != null;
|
||||
}
|
||||
}
|
||||
|
||||
public interface DictionaryInitializationListener {
|
||||
public void onUpdateMainDictionaryAvailability(boolean isMainDictionaryAvailable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instance for initialization or when the locale is changed.
|
||||
*
|
||||
* @param context the context
|
||||
* @param locale the locale
|
||||
* @param settingsValues current settings values to control what dictionaries should be used
|
||||
* @param listener the listener
|
||||
* @param oldDictionaryFacilitator the instance having old dictionaries. This is null when the
|
||||
* instance is initially created.
|
||||
*/
|
||||
public DictionaryFacilitatorForSuggest(final Context context, final Locale locale,
|
||||
final SettingsValues settingsValues, final DictionaryInitializationListener listener,
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator) {
|
||||
mContext = context;
|
||||
mLocale = locale;
|
||||
mLatchForWaitingLoadingMainDictionary = new CountDownLatch(1);
|
||||
loadMainDict(context, locale, listener);
|
||||
setUserDictionary(new UserBinaryDictionary(context, locale));
|
||||
resetAdditionalDictionaries(oldDictionaryFacilitator, settingsValues);
|
||||
public DictionaryFacilitatorForSuggest() {}
|
||||
|
||||
public Locale getLocale() {
|
||||
return mDictionaries.mLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instance for reloading the main dict.
|
||||
*
|
||||
* @param listener the listener
|
||||
* @param oldDictionaryFacilitator the instance having old dictionaries. This must not be null.
|
||||
*/
|
||||
public DictionaryFacilitatorForSuggest(final DictionaryInitializationListener listener,
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator) {
|
||||
mContext = oldDictionaryFacilitator.mContext;
|
||||
mLocale = oldDictionaryFacilitator.mLocale;
|
||||
mLatchForWaitingLoadingMainDictionary = new CountDownLatch(1);
|
||||
loadMainDict(mContext, mLocale, listener);
|
||||
// Transfer user dictionary.
|
||||
setUserDictionary(oldDictionaryFacilitator.mUserDictionary);
|
||||
oldDictionaryFacilitator.removeDictionary(Dictionary.TYPE_USER);
|
||||
// Transfer contacts dictionary.
|
||||
setContactsDictionary(oldDictionaryFacilitator.mContactsDictionary);
|
||||
oldDictionaryFacilitator.removeDictionary(Dictionary.TYPE_CONTACTS);
|
||||
// Transfer user history dictionary.
|
||||
setUserHistoryDictionary(oldDictionaryFacilitator.mUserHistoryDictionary);
|
||||
oldDictionaryFacilitator.removeDictionary(Dictionary.TYPE_USER_HISTORY);
|
||||
// Transfer personalization dictionary.
|
||||
setPersonalizationDictionary(oldDictionaryFacilitator.mPersonalizationDictionary);
|
||||
oldDictionaryFacilitator.removeDictionary(Dictionary.TYPE_PERSONALIZATION);
|
||||
public void resetDictionaries(final Context context, final Locale newLocale,
|
||||
final boolean useContactsDict, final boolean usePersonalizedDicts,
|
||||
final boolean forceReloadMainDictionary,
|
||||
final DictionaryInitializationListener listener) {
|
||||
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;
|
||||
|
||||
final Dictionary newMainDict;
|
||||
if (reloadMainDictionary) {
|
||||
// The main dictionary will be asynchronously loaded.
|
||||
newMainDict = null;
|
||||
} else {
|
||||
newMainDict = mDictionaries.mMainDictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates instance for when the settings values have been changed.
|
||||
*
|
||||
* @param settingsValues the new settings values
|
||||
* @param oldDictionaryFacilitator the instance having old dictionaries. This must not be null.
|
||||
*/
|
||||
//
|
||||
public DictionaryFacilitatorForSuggest(final SettingsValues settingsValues,
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator) {
|
||||
mContext = oldDictionaryFacilitator.mContext;
|
||||
mLocale = oldDictionaryFacilitator.mLocale;
|
||||
mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
|
||||
// Transfer main dictionary.
|
||||
setMainDictionary(oldDictionaryFacilitator.mMainDictionary);
|
||||
oldDictionaryFacilitator.removeDictionary(Dictionary.TYPE_MAIN);
|
||||
// Transfer user dictionary.
|
||||
setUserDictionary(oldDictionaryFacilitator.mUserDictionary);
|
||||
oldDictionaryFacilitator.removeDictionary(Dictionary.TYPE_USER);
|
||||
// Transfer or create additional dictionaries depending on the settings values.
|
||||
resetAdditionalDictionaries(oldDictionaryFacilitator, settingsValues);
|
||||
// Open or move contacts dictionary.
|
||||
final ContactsBinaryDictionary newContactsDict;
|
||||
if (!closeContactsDictionary && mDictionaries.hasContactsDict()) {
|
||||
newContactsDict = mDictionaries.mContactsDictionary;
|
||||
} else if (useContactsDict) {
|
||||
newContactsDict = new ContactsBinaryDictionary(context, newLocale);
|
||||
} else {
|
||||
newContactsDict = null;
|
||||
}
|
||||
|
||||
// Open or move user dictionary.
|
||||
final UserBinaryDictionary newUserDictionary;
|
||||
if (!closeUserDictionary && mDictionaries.hasUserDict()) {
|
||||
newUserDictionary = mDictionaries.mUserDictionary;
|
||||
} else {
|
||||
newUserDictionary = new UserBinaryDictionary(context, newLocale);
|
||||
}
|
||||
|
||||
// Open or move user history dictionary.
|
||||
final UserHistoryDictionary newUserHistoryDict;
|
||||
if (!closeUserHistoryDictionary && mDictionaries.hasUserHistoryDict()) {
|
||||
newUserHistoryDict = mDictionaries.mUserHistoryDictionary;
|
||||
} else if (usePersonalizedDicts) {
|
||||
newUserHistoryDict = PersonalizationHelper.getUserHistoryDictionary(context, newLocale);
|
||||
} else {
|
||||
newUserHistoryDict = null;
|
||||
}
|
||||
|
||||
// Open or move personalization dictionary.
|
||||
final PersonalizationDictionary newPersonalizationDict;
|
||||
if (!closePersonalizationDictionary && mDictionaries.hasPersonalizationDict()) {
|
||||
newPersonalizationDict = mDictionaries.mPersonalizationDictionary;
|
||||
} else if (usePersonalizedDicts) {
|
||||
newPersonalizationDict =
|
||||
PersonalizationHelper.getPersonalizationDictionary(context, newLocale);
|
||||
} else {
|
||||
newPersonalizationDict = null;
|
||||
}
|
||||
|
||||
// Replace Dictionaries.
|
||||
final Dictionaries newDictionaries = new Dictionaries(newLocale, newMainDict,
|
||||
newContactsDict, newUserDictionary, newUserHistoryDict, newPersonalizationDict);
|
||||
if (listener != null) {
|
||||
listener.onUpdateMainDictionaryAvailability(newDictionaries.hasMainDict());
|
||||
}
|
||||
final Dictionaries oldDictionaries;
|
||||
synchronized (mLock) {
|
||||
oldDictionaries = mDictionaries;
|
||||
mDictionaries = newDictionaries;
|
||||
if (reloadMainDictionary) {
|
||||
asyncReloadMainDictionary(context, newLocale, listener);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up old dictionaries.
|
||||
oldDictionaries.mDictMap.clear();
|
||||
if (reloadMainDictionary && oldDictionaries.hasMainDict()) {
|
||||
oldDictionaries.mMainDictionary.close();
|
||||
}
|
||||
if (closeContactsDictionary && oldDictionaries.hasContactsDict()) {
|
||||
oldDictionaries.mContactsDictionary.close();
|
||||
}
|
||||
if (closeUserDictionary && oldDictionaries.hasUserDict()) {
|
||||
oldDictionaries.mUserDictionary.close();
|
||||
}
|
||||
if (closeUserHistoryDictionary && oldDictionaries.hasUserHistoryDict()) {
|
||||
oldDictionaries.mUserHistoryDictionary.close();
|
||||
}
|
||||
if (closePersonalizationDictionary && oldDictionaries.hasPersonalizationDict()) {
|
||||
oldDictionaries.mPersonalizationDictionary.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void asyncReloadMainDictionary(final Context context, final Locale locale,
|
||||
final DictionaryInitializationListener listener) {
|
||||
final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1);
|
||||
mLatchForWaitingLoadingMainDictionary = latchForWaitingLoadingMainDictionary;
|
||||
ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
final Dictionary mainDict =
|
||||
DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
||||
synchronized (mLock) {
|
||||
if (locale.equals(mDictionaries.mLocale)) {
|
||||
mDictionaries.setMainDict(mainDict);
|
||||
} else {
|
||||
// Dictionary facilitator has been reset for another locale.
|
||||
mainDict.close();
|
||||
}
|
||||
}
|
||||
if (listener != null) {
|
||||
listener.onUpdateMainDictionaryAvailability(mDictionaries.hasMainDict());
|
||||
}
|
||||
latchForWaitingLoadingMainDictionary.countDown();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@UsedForTesting
|
||||
public DictionaryFacilitatorForSuggest(final Context context, final Locale locale,
|
||||
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) {
|
||||
mContext = context;
|
||||
mLocale = locale;
|
||||
mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
|
||||
Dictionary mainDictionary = null;
|
||||
ContactsBinaryDictionary contactsDictionary = null;
|
||||
UserBinaryDictionary userDictionary = null;
|
||||
UserHistoryDictionary userHistoryDictionary = null;
|
||||
PersonalizationDictionary personalizationDictionary = null;
|
||||
|
||||
for (final String dictType : dictionaryTypes) {
|
||||
if (dictType.equals(Dictionary.TYPE_MAIN)) {
|
||||
final DictionaryCollection mainDictionary =
|
||||
DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
||||
setMainDictionary(mainDictionary);
|
||||
mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
||||
} else if (dictType.equals(Dictionary.TYPE_USER_HISTORY)) {
|
||||
final UserHistoryDictionary userHistoryDictionary =
|
||||
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();
|
||||
setUserHistoryDictionary(userHistoryDictionary);
|
||||
if (additionalDictAttributes.containsKey(dictType)) {
|
||||
userHistoryDictionary.clearAndFlushDictionaryWithAdditionalAttributes(
|
||||
additionalDictAttributes.get(dictType));
|
||||
}
|
||||
} else if (dictType.equals(Dictionary.TYPE_PERSONALIZATION)) {
|
||||
final PersonalizationDictionary personalizationDictionary =
|
||||
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();
|
||||
setPersonalizationDictionary(personalizationDictionary);
|
||||
if (additionalDictAttributes.containsKey(dictType)) {
|
||||
personalizationDictionary.clearAndFlushDictionaryWithAdditionalAttributes(
|
||||
additionalDictAttributes.get(dictType));
|
||||
}
|
||||
} else if (dictType.equals(Dictionary.TYPE_USER)) {
|
||||
final File file = dictionaryFiles.get(dictType);
|
||||
final UserBinaryDictionary userDictionary = new UserBinaryDictionary(
|
||||
context, locale, file);
|
||||
userDictionary = new UserBinaryDictionary(context, locale, file);
|
||||
userDictionary.reloadDictionaryIfRequired();
|
||||
userDictionary.waitAllTasksForTests();
|
||||
setUserDictionary(userDictionary);
|
||||
} else if (dictType.equals(Dictionary.TYPE_CONTACTS)) {
|
||||
final File file = dictionaryFiles.get(dictType);
|
||||
final ContactsBinaryDictionary contactsDictionary = new ContactsBinaryDictionary(
|
||||
context, locale, file);
|
||||
contactsDictionary = new ContactsBinaryDictionary(context, locale, file);
|
||||
contactsDictionary.reloadDictionaryIfRequired();
|
||||
contactsDictionary.waitAllTasksForTests();
|
||||
setContactsDictionary(contactsDictionary);
|
||||
} else {
|
||||
throw new RuntimeException("Unknown dictionary type: " + dictType);
|
||||
}
|
||||
}
|
||||
mDictionaries = new Dictionaries(locale, mainDictionary, contactsDictionary,
|
||||
userDictionary, userHistoryDictionary, personalizationDictionary);
|
||||
}
|
||||
|
||||
public boolean needsToBeRecreated(final Locale newLocale,
|
||||
final SettingsValues newSettingsValues) {
|
||||
return !mLocale.equals(newLocale)
|
||||
|| (newSettingsValues.mUseContactsDict != (mContactsDictionary != null))
|
||||
|| (newSettingsValues.mUsePersonalizedDicts != (mUserHistoryDictionary != null))
|
||||
|| (newSettingsValues.mUsePersonalizedDicts != hasPersonalizationDictionary());
|
||||
public void closeDictionaries() {
|
||||
final Dictionaries dictionaries;
|
||||
synchronized (mLock) {
|
||||
dictionaries = mDictionaries;
|
||||
mDictionaries = new Dictionaries();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
final HashSet<Dictionary> dictionaries = CollectionUtils.newHashSet();
|
||||
dictionaries.addAll(mDictionaries.values());
|
||||
for (final Dictionary dictionary : dictionaries) {
|
||||
dictionary.close();
|
||||
if (dictionaries.hasMainDict()) {
|
||||
dictionaries.mMainDictionary.close();
|
||||
}
|
||||
if (dictionaries.hasContactsDict()) {
|
||||
dictionaries.mContactsDictionary.close();
|
||||
}
|
||||
|
||||
private void loadMainDict(final Context context, final Locale locale,
|
||||
final DictionaryInitializationListener listener) {
|
||||
mMainDictionary = null;
|
||||
if (listener != null) {
|
||||
listener.onUpdateMainDictionaryAvailability(hasMainDictionary());
|
||||
if (dictionaries.hasUserDict()) {
|
||||
dictionaries.mUserDictionary.close();
|
||||
}
|
||||
ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
|
||||
public void run() {
|
||||
final DictionaryCollection newMainDict =
|
||||
DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
||||
setMainDictionary(newMainDict);
|
||||
if (listener != null) {
|
||||
listener.onUpdateMainDictionaryAvailability(hasMainDictionary());
|
||||
if (dictionaries.hasUserHistoryDict()) {
|
||||
dictionaries.mUserHistoryDictionary.close();
|
||||
}
|
||||
mLatchForWaitingLoadingMainDictionary.countDown();
|
||||
if (dictionaries.hasPersonalizationDict()) {
|
||||
dictionaries.mPersonalizationDictionary.close();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// The main dictionary could have been loaded asynchronously. Don't cache the return value
|
||||
// of this method.
|
||||
public boolean hasMainDictionary() {
|
||||
return null != mMainDictionary && mMainDictionary.isInitialized();
|
||||
public boolean hasInitializedMainDictionary() {
|
||||
final Dictionaries dictionaries = mDictionaries;
|
||||
return dictionaries.hasMainDict() && dictionaries.mMainDictionary.isInitialized();
|
||||
}
|
||||
|
||||
public boolean hasPersonalizationDictionary() {
|
||||
return null != mPersonalizationDictionary;
|
||||
return mDictionaries.hasPersonalizationDict();
|
||||
}
|
||||
|
||||
public void flushPersonalizationDictionary() {
|
||||
if (hasPersonalizationDictionary()) {
|
||||
mPersonalizationDictionary.flush();
|
||||
final PersonalizationDictionary personalizationDict =
|
||||
mDictionaries.mPersonalizationDictionary;
|
||||
if (personalizationDict != null) {
|
||||
personalizationDict.flush();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -253,177 +369,48 @@ public class DictionaryFacilitatorForSuggest {
|
|||
public void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
|
||||
throws InterruptedException {
|
||||
waitForLoadingMainDictionary(timeout, unit);
|
||||
if (mContactsDictionary != null) {
|
||||
mContactsDictionary.waitAllTasksForTests();
|
||||
final Dictionaries dictionaries = mDictionaries;
|
||||
if (dictionaries.hasContactsDict()) {
|
||||
dictionaries.mContactsDictionary.waitAllTasksForTests();
|
||||
}
|
||||
if (mUserDictionary != null) {
|
||||
mUserDictionary.waitAllTasksForTests();
|
||||
if (dictionaries.hasUserDict()) {
|
||||
dictionaries.mUserDictionary.waitAllTasksForTests();
|
||||
}
|
||||
if (mUserHistoryDictionary != null) {
|
||||
mUserHistoryDictionary.waitAllTasksForTests();
|
||||
if (dictionaries.hasUserHistoryDict()) {
|
||||
dictionaries.mUserHistoryDictionary.waitAllTasksForTests();
|
||||
}
|
||||
if (mPersonalizationDictionary != null) {
|
||||
mPersonalizationDictionary.waitAllTasksForTests();
|
||||
if (dictionaries.hasPersonalizationDict()) {
|
||||
dictionaries.mPersonalizationDictionary.waitAllTasksForTests();
|
||||
}
|
||||
}
|
||||
|
||||
private void setMainDictionary(final Dictionary mainDictionary) {
|
||||
mMainDictionary = mainDictionary;
|
||||
addOrReplaceDictionary(Dictionary.TYPE_MAIN, mainDictionary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an optional user dictionary resource to be loaded. The user dictionary is consulted
|
||||
* before the main dictionary, if set. This refers to the system-managed user dictionary.
|
||||
*/
|
||||
private void setUserDictionary(final UserBinaryDictionary userDictionary) {
|
||||
mUserDictionary = userDictionary;
|
||||
addOrReplaceDictionary(Dictionary.TYPE_USER, userDictionary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets an optional contacts dictionary resource to be loaded. It is also possible to remove
|
||||
* the contacts dictionary by passing null to this method. In this case no contacts dictionary
|
||||
* won't be used.
|
||||
*/
|
||||
private void setContactsDictionary(final ContactsBinaryDictionary contactsDictionary) {
|
||||
mContactsDictionary = contactsDictionary;
|
||||
addOrReplaceDictionary(Dictionary.TYPE_CONTACTS, contactsDictionary);
|
||||
}
|
||||
|
||||
private void setUserHistoryDictionary(final UserHistoryDictionary userHistoryDictionary) {
|
||||
mUserHistoryDictionary = userHistoryDictionary;
|
||||
addOrReplaceDictionary(Dictionary.TYPE_USER_HISTORY, userHistoryDictionary);
|
||||
}
|
||||
|
||||
private void setPersonalizationDictionary(
|
||||
final PersonalizationDictionary personalizationDictionary) {
|
||||
mPersonalizationDictionary = personalizationDictionary;
|
||||
addOrReplaceDictionary(Dictionary.TYPE_PERSONALIZATION, personalizationDictionary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset dictionaries that can be turned off according to the user settings.
|
||||
*
|
||||
* @param oldDictionaryFacilitator the instance having old dictionaries
|
||||
* @param settingsValues current SettingsValues
|
||||
*/
|
||||
private void resetAdditionalDictionaries(
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator,
|
||||
final SettingsValues settingsValues) {
|
||||
// Contacts dictionary
|
||||
resetContactsDictionary(null != oldDictionaryFacilitator ?
|
||||
oldDictionaryFacilitator.mContactsDictionary : null, settingsValues);
|
||||
// User history dictionary & Personalization dictionary
|
||||
resetPersonalizedDictionaries(oldDictionaryFacilitator, settingsValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the user history dictionary and personalization dictionary according to the user
|
||||
* settings.
|
||||
*
|
||||
* @param oldDictionaryFacilitator the instance that has been used
|
||||
* @param settingsValues current settingsValues
|
||||
*/
|
||||
// TODO: Consolidate resetPersonalizedDictionaries() and resetContactsDictionary(). Call up the
|
||||
// new method for each dictionary.
|
||||
private void resetPersonalizedDictionaries(
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator,
|
||||
final SettingsValues settingsValues) {
|
||||
final boolean shouldSetDictionaries = settingsValues.mUsePersonalizedDicts;
|
||||
|
||||
final UserHistoryDictionary oldUserHistoryDictionary = (null == oldDictionaryFacilitator) ?
|
||||
null : oldDictionaryFacilitator.mUserHistoryDictionary;
|
||||
final PersonalizationDictionary oldPersonalizationDictionary =
|
||||
(null == oldDictionaryFacilitator) ? null :
|
||||
oldDictionaryFacilitator.mPersonalizationDictionary;
|
||||
final UserHistoryDictionary userHistoryDictionaryToUse;
|
||||
final PersonalizationDictionary personalizationDictionaryToUse;
|
||||
if (!shouldSetDictionaries) {
|
||||
userHistoryDictionaryToUse = null;
|
||||
personalizationDictionaryToUse = null;
|
||||
} else {
|
||||
if (null != oldUserHistoryDictionary
|
||||
&& oldUserHistoryDictionary.mLocale.equals(mLocale)) {
|
||||
userHistoryDictionaryToUse = oldUserHistoryDictionary;
|
||||
} else {
|
||||
userHistoryDictionaryToUse =
|
||||
PersonalizationHelper.getUserHistoryDictionary(mContext, mLocale);
|
||||
}
|
||||
if (null != oldPersonalizationDictionary
|
||||
&& oldPersonalizationDictionary.mLocale.equals(mLocale)) {
|
||||
personalizationDictionaryToUse = oldPersonalizationDictionary;
|
||||
} else {
|
||||
personalizationDictionaryToUse =
|
||||
PersonalizationHelper.getPersonalizationDictionary(mContext, mLocale);
|
||||
}
|
||||
}
|
||||
setUserHistoryDictionary(userHistoryDictionaryToUse);
|
||||
setPersonalizationDictionary(personalizationDictionaryToUse);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the contacts dictionary according to the user settings.
|
||||
*
|
||||
* This method takes an optional contacts dictionary to use when the locale hasn't changed
|
||||
* since the contacts dictionary can be opened or closed as necessary depending on the settings.
|
||||
*
|
||||
* @param oldContactsDictionary an optional dictionary to use, or null
|
||||
* @param settingsValues current settingsValues
|
||||
*/
|
||||
private void resetContactsDictionary(final ContactsBinaryDictionary oldContactsDictionary,
|
||||
final SettingsValues settingsValues) {
|
||||
final boolean shouldSetDictionary = settingsValues.mUseContactsDict;
|
||||
final ContactsBinaryDictionary dictionaryToUse;
|
||||
if (!shouldSetDictionary) {
|
||||
// Make sure the dictionary is closed. If it is already closed, this is a no-op,
|
||||
// so it's safe to call it anyways.
|
||||
if (null != oldContactsDictionary) oldContactsDictionary.close();
|
||||
dictionaryToUse = null;
|
||||
} else {
|
||||
if (null != oldContactsDictionary) {
|
||||
if (!oldContactsDictionary.mLocale.equals(mLocale)) {
|
||||
// If the locale has changed then recreate the contacts dictionary. This
|
||||
// allows locale dependent rules for handling bigram name predictions.
|
||||
oldContactsDictionary.close();
|
||||
dictionaryToUse = new ContactsBinaryDictionary(mContext, mLocale);
|
||||
} else {
|
||||
// Make sure the old contacts dictionary is opened. If it is already open,
|
||||
// this is a no-op, so it's safe to call it anyways.
|
||||
oldContactsDictionary.reopen(mContext);
|
||||
dictionaryToUse = oldContactsDictionary;
|
||||
}
|
||||
} else {
|
||||
dictionaryToUse = new ContactsBinaryDictionary(mContext, mLocale);
|
||||
}
|
||||
}
|
||||
setContactsDictionary(dictionaryToUse);
|
||||
}
|
||||
|
||||
public boolean isUserDictionaryEnabled() {
|
||||
if (mUserDictionary == null) {
|
||||
final UserBinaryDictionary userDictionary = mDictionaries.mUserDictionary;
|
||||
if (userDictionary == null) {
|
||||
return false;
|
||||
}
|
||||
return mUserDictionary.mEnabled;
|
||||
return userDictionary.mEnabled;
|
||||
}
|
||||
|
||||
public void addWordToUserDictionary(String word) {
|
||||
if (mUserDictionary == null) {
|
||||
final UserBinaryDictionary userDictionary = mDictionaries.mUserDictionary;
|
||||
if (userDictionary == null) {
|
||||
return;
|
||||
}
|
||||
mUserDictionary.addWordToUserDictionary(word);
|
||||
userDictionary.addWordToUserDictionary(word);
|
||||
}
|
||||
|
||||
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
||||
final String previousWord, final int timeStampInSeconds) {
|
||||
if (mUserHistoryDictionary == null) {
|
||||
final Dictionaries dictionaries = mDictionaries;
|
||||
if (!dictionaries.hasUserHistoryDict()) {
|
||||
return;
|
||||
}
|
||||
final int maxFreq = getMaxFrequency(suggestion);
|
||||
if (maxFreq == 0) {
|
||||
return;
|
||||
}
|
||||
final String suggestionLowerCase = suggestion.toLowerCase(mLocale);
|
||||
final String suggestionLowerCase = suggestion.toLowerCase(dictionaries.mLocale);
|
||||
final String secondWord;
|
||||
if (wasAutoCapitalized) {
|
||||
secondWord = suggestionLowerCase;
|
||||
|
@ -432,11 +419,11 @@ public class DictionaryFacilitatorForSuggest {
|
|||
// History dictionary in order to avoid suggesting them until the dictionary
|
||||
// consolidation is done.
|
||||
// TODO: Remove this hack when ready.
|
||||
final int lowerCasefreqInMainDict = mMainDictionary != null ?
|
||||
mMainDictionary.getFrequency(suggestionLowerCase) :
|
||||
final int lowerCaseFreqInMainDict = dictionaries.hasMainDict() ?
|
||||
dictionaries.mMainDictionary.getFrequency(suggestionLowerCase) :
|
||||
Dictionary.NOT_A_PROBABILITY;
|
||||
if (maxFreq < lowerCasefreqInMainDict
|
||||
&& lowerCasefreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
|
||||
if (maxFreq < lowerCaseFreqInMainDict
|
||||
&& lowerCaseFreqInMainDict >= CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT) {
|
||||
// Use lower cased word as the word can be a distracter of the popular word.
|
||||
secondWord = suggestionLowerCase;
|
||||
} else {
|
||||
|
@ -446,54 +433,56 @@ public class DictionaryFacilitatorForSuggest {
|
|||
// We demote unrecognized words (frequency < 0, below) by specifying them as "invalid".
|
||||
// We don't add words with 0-frequency (assuming they would be profanity etc.).
|
||||
final boolean isValid = maxFreq > 0;
|
||||
mUserHistoryDictionary.addToDictionary(
|
||||
dictionaries.mUserHistoryDictionary.addToDictionary(
|
||||
previousWord, secondWord, isValid, timeStampInSeconds);
|
||||
}
|
||||
|
||||
public void cancelAddingUserHistory(final String previousWord, final String committedWord) {
|
||||
if (mUserHistoryDictionary != null) {
|
||||
mUserHistoryDictionary.cancelAddingUserHistory(previousWord, committedWord);
|
||||
final UserHistoryDictionary userHistoryDictionary = mDictionaries.mUserHistoryDictionary;
|
||||
if (userHistoryDictionary != null) {
|
||||
userHistoryDictionary.cancelAddingUserHistory(previousWord, committedWord);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Revise the way to fusion suggestion results.
|
||||
public void getSuggestions(final WordComposer composer,
|
||||
public SuggestionResults getSuggestionResults(final WordComposer composer,
|
||||
final String prevWord, final ProximityInfo proximityInfo,
|
||||
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
|
||||
final int sessionId, final Set<SuggestedWordInfo> suggestionSet,
|
||||
final ArrayList<SuggestedWordInfo> rawSuggestions) {
|
||||
for (final String key : mDictionaries.keySet()) {
|
||||
final Dictionary dictionary = mDictionaries.get(key);
|
||||
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);
|
||||
for (final Dictionary dictionary : dictMap.values()) {
|
||||
if (null == dictionary) continue;
|
||||
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
|
||||
dictionary.getSuggestionsWithSessionId(composer, prevWord, proximityInfo,
|
||||
blockOffensiveWords, additionalFeaturesOptions, sessionId);
|
||||
if (null == dictionarySuggestions) continue;
|
||||
suggestionSet.addAll(dictionarySuggestions);
|
||||
suggestionResults.addAll(dictionarySuggestions);
|
||||
if (null != rawSuggestions) {
|
||||
rawSuggestions.addAll(dictionarySuggestions);
|
||||
}
|
||||
}
|
||||
return suggestionResults;
|
||||
}
|
||||
|
||||
public boolean isValidMainDictWord(final String word) {
|
||||
if (TextUtils.isEmpty(word) || !hasMainDictionary()) {
|
||||
final Dictionaries dictionaries = mDictionaries;
|
||||
if (TextUtils.isEmpty(word) || !dictionaries.hasMainDict()) {
|
||||
return false;
|
||||
}
|
||||
return mMainDictionary.isValidWord(word);
|
||||
return dictionaries.mMainDictionary.isValidWord(word);
|
||||
}
|
||||
|
||||
public boolean isValidWord(final String word, final boolean ignoreCase) {
|
||||
if (TextUtils.isEmpty(word)) {
|
||||
return false;
|
||||
}
|
||||
final String lowerCasedWord = word.toLowerCase(mLocale);
|
||||
for (final String key : mDictionaries.keySet()) {
|
||||
final Dictionary dictionary = mDictionaries.get(key);
|
||||
// It's unclear how realistically 'dictionary' can be null, but the monkey is somehow
|
||||
// managing to get null in here. Presumably the language is changing to a language with
|
||||
// no main dictionary and the monkey manages to type a whole word before the thread
|
||||
// that reads the dictionary is started or something?
|
||||
final Dictionaries dictionaries = mDictionaries;
|
||||
final String lowerCasedWord = word.toLowerCase(dictionaries.mLocale);
|
||||
final Map<String, Dictionary> dictMap = dictionaries.mDictMap;
|
||||
for (final Dictionary dictionary : dictMap.values()) {
|
||||
// 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.
|
||||
|
@ -511,9 +500,8 @@ public class DictionaryFacilitatorForSuggest {
|
|||
return Dictionary.NOT_A_PROBABILITY;
|
||||
}
|
||||
int maxFreq = -1;
|
||||
for (final String key : mDictionaries.keySet()) {
|
||||
final Dictionary dictionary = mDictionaries.get(key);
|
||||
if (null == dictionary) continue;
|
||||
final Map<String, Dictionary> dictMap = mDictionaries.mDictMap;
|
||||
for (final Dictionary dictionary : dictMap.values()) {
|
||||
final int tempFreq = dictionary.getFrequency(word);
|
||||
if (tempFreq >= maxFreq) {
|
||||
maxFreq = tempFreq;
|
||||
|
@ -522,61 +510,50 @@ public class DictionaryFacilitatorForSuggest {
|
|||
return maxFreq;
|
||||
}
|
||||
|
||||
private void removeDictionary(final String key) {
|
||||
mDictionaries.remove(key);
|
||||
}
|
||||
|
||||
private void addOrReplaceDictionary(final String key, final Dictionary dict) {
|
||||
final Dictionary oldDict;
|
||||
if (dict == null) {
|
||||
oldDict = mDictionaries.remove(key);
|
||||
} else {
|
||||
oldDict = mDictionaries.put(key, dict);
|
||||
}
|
||||
if (oldDict != null && dict != oldDict) {
|
||||
oldDict.close();
|
||||
}
|
||||
}
|
||||
|
||||
public void clearUserHistoryDictionary() {
|
||||
if (mUserHistoryDictionary == null) {
|
||||
final UserHistoryDictionary userHistoryDict = mDictionaries.mUserHistoryDictionary;
|
||||
if (userHistoryDict == null) {
|
||||
return;
|
||||
}
|
||||
mUserHistoryDictionary.clearAndFlushDictionary();
|
||||
userHistoryDict.clearAndFlushDictionary();
|
||||
}
|
||||
|
||||
// This method gets called only when the IME receives a notification to remove the
|
||||
// personalization dictionary.
|
||||
public void clearPersonalizationDictionary() {
|
||||
if (!hasPersonalizationDictionary()) {
|
||||
final PersonalizationDictionary personalizationDict =
|
||||
mDictionaries.mPersonalizationDictionary;
|
||||
if (personalizationDict == null) {
|
||||
return;
|
||||
}
|
||||
mPersonalizationDictionary.clearAndFlushDictionary();
|
||||
personalizationDict.clearAndFlushDictionary();
|
||||
}
|
||||
|
||||
public void addMultipleDictionaryEntriesToPersonalizationDictionary(
|
||||
final ArrayList<LanguageModelParam> languageModelParams,
|
||||
final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) {
|
||||
if (!hasPersonalizationDictionary()) {
|
||||
final PersonalizationDictionary personalizationDict =
|
||||
mDictionaries.mPersonalizationDictionary;
|
||||
if (personalizationDict == null) {
|
||||
if (callback != null) {
|
||||
callback.onFinished();
|
||||
}
|
||||
return;
|
||||
}
|
||||
mPersonalizationDictionary.addMultipleDictionaryEntriesToDictionary(languageModelParams,
|
||||
callback);
|
||||
personalizationDict.addMultipleDictionaryEntriesToDictionary(languageModelParams, callback);
|
||||
}
|
||||
|
||||
public void dumpDictionaryForDebug(final String dictName) {
|
||||
final ExpandableBinaryDictionary dictToDump;
|
||||
if (dictName.equals(Dictionary.TYPE_CONTACTS)) {
|
||||
dictToDump = mContactsDictionary;
|
||||
dictToDump = mDictionaries.mContactsDictionary;
|
||||
} else if (dictName.equals(Dictionary.TYPE_USER)) {
|
||||
dictToDump = mUserDictionary;
|
||||
dictToDump = mDictionaries.mUserDictionary;
|
||||
} else if (dictName.equals(Dictionary.TYPE_USER_HISTORY)) {
|
||||
dictToDump = mUserHistoryDictionary;
|
||||
dictToDump = mDictionaries.mUserHistoryDictionary;
|
||||
} else if (dictName.equals(Dictionary.TYPE_PERSONALIZATION)) {
|
||||
dictToDump = mPersonalizationDictionary;
|
||||
dictToDump = mDictionaries.mPersonalizationDictionary;
|
||||
} else {
|
||||
dictToDump = null;
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
false /* includeResumedWordInSuggestions */);
|
||||
break;
|
||||
case MSG_REOPEN_DICTIONARIES:
|
||||
latinIme.initSuggest();
|
||||
latinIme.resetSuggest();
|
||||
// In theory we could call latinIme.updateSuggestionStrip() right away, but
|
||||
// in the practice, the dictionary is not finished opening yet so we wouldn't
|
||||
// get any suggestions. Wait one frame.
|
||||
|
@ -478,10 +478,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
// TODO: Resolve mutual dependencies of {@link #loadSettings()} and {@link #initSuggest()}.
|
||||
loadSettings();
|
||||
initSuggest();
|
||||
resetSuggest();
|
||||
|
||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||
ResearchLogger.getInstance().init(this, mKeyboardSwitcher);
|
||||
ResearchLogger.getInstance().initDictionary(
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator);
|
||||
}
|
||||
|
||||
// Register to receive ringer mode change and network state change.
|
||||
|
@ -520,31 +522,15 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// 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.
|
||||
initOrResetSuggestForSettingsValues(mInputLogic.mSuggest, locale, currentSettingsValues);
|
||||
if (!mHandler.hasPendingReopenDictionaries()) {
|
||||
resetSuggestForLocale(locale);
|
||||
}
|
||||
|
||||
private void initOrResetSuggestForSettingsValues(final Suggest oldSuggest,
|
||||
final Locale locale, final SettingsValues settingsValues) {
|
||||
if (!mHandler.hasPendingReopenDictionaries() && oldSuggest != null) {
|
||||
// May need to reset dictionaries depending on the user settings.
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator =
|
||||
oldSuggest.mDictionaryFacilitator;
|
||||
if (!oldDictionaryFacilitator.needsToBeRecreated(locale, settingsValues)) {
|
||||
// Continue to use the same dictionary facilitator if no configuration has changed.
|
||||
refreshPersonalizationDictionarySession();
|
||||
return;
|
||||
}
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
new DictionaryFacilitatorForSuggest(settingsValues, oldDictionaryFacilitator);
|
||||
// Create Suggest instance with the new dictionary facilitator.
|
||||
replaceSuggest(new Suggest(oldSuggest, dictionaryFacilitator));
|
||||
} else if (oldSuggest == null) {
|
||||
initSuggest();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshPersonalizationDictionarySession() {
|
||||
final Suggest suggest = mInputLogic.mSuggest;
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator;
|
||||
final boolean shouldKeepUserHistoryDictionaries;
|
||||
final boolean shouldKeepPersonalizationDictionaries;
|
||||
if (mSettings.getCurrent().mUsePersonalizedDicts) {
|
||||
|
@ -559,17 +545,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
if (!shouldKeepUserHistoryDictionaries) {
|
||||
// Remove user history dictionaries.
|
||||
PersonalizationHelper.removeAllUserHistoryDictionaries(this);
|
||||
if (suggest != null) {
|
||||
suggest.mDictionaryFacilitator.clearUserHistoryDictionary();
|
||||
}
|
||||
dictionaryFacilitator.clearUserHistoryDictionary();
|
||||
}
|
||||
if (!shouldKeepPersonalizationDictionaries) {
|
||||
// Remove personalization dictionaries.
|
||||
PersonalizationHelper.removeAllPersonalizationDictionaries(this);
|
||||
PersonalizationDictionarySessionRegistrar.resetAll(this);
|
||||
} else {
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
(suggest == null) ? null : suggest.mDictionaryFacilitator;
|
||||
PersonalizationDictionarySessionRegistrar.init(this, dictionaryFacilitator);
|
||||
}
|
||||
}
|
||||
|
@ -583,7 +565,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
}
|
||||
|
||||
private void initSuggest() {
|
||||
private void resetSuggest() {
|
||||
final Locale switcherSubtypeLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
|
||||
final String switcherLocaleStr = switcherSubtypeLocale.toString();
|
||||
final Locale subtypeLocale;
|
||||
|
@ -599,47 +581,42 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
} else {
|
||||
subtypeLocale = switcherSubtypeLocale;
|
||||
}
|
||||
initSuggestForLocale(mInputLogic.mSuggest, subtypeLocale);
|
||||
resetSuggestForLocale(subtypeLocale);
|
||||
}
|
||||
|
||||
private void initSuggestForLocale(final Suggest oldSuggest, final Locale locale) {
|
||||
final SettingsValues settingsValues = mSettings.getCurrent();
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator =
|
||||
(oldSuggest == null) ? null : oldSuggest.mDictionaryFacilitator;
|
||||
// Creates new dictionary facilitator for the new locale.
|
||||
/**
|
||||
* Reset suggest by loading dictionaries for the locale and the current settings values.
|
||||
*
|
||||
* @param locale the locale
|
||||
*/
|
||||
private void resetSuggestForLocale(final Locale locale) {
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
new DictionaryFacilitatorForSuggest(this /* context */, locale, settingsValues,
|
||||
this /* DictionaryInitializationListener */, oldDictionaryFacilitator);
|
||||
final Suggest newSuggest = new Suggest(locale, dictionaryFacilitator);
|
||||
if (settingsValues.mCorrectionEnabled) {
|
||||
newSuggest.setAutoCorrectionThreshold(settingsValues.mAutoCorrectionThreshold);
|
||||
}
|
||||
replaceSuggest(newSuggest);
|
||||
}
|
||||
|
||||
/* package private */ void resetSuggestMainDict() {
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator =
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator;
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
new DictionaryFacilitatorForSuggest(this /* listener */, oldDictionaryFacilitator);
|
||||
replaceSuggest(new Suggest(mInputLogic.mSuggest /* oldSuggest */, dictionaryFacilitator));
|
||||
final SettingsValues settingsValues = mSettings.getCurrent();
|
||||
dictionaryFacilitator.resetDictionaries(this /* context */, locale,
|
||||
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
|
||||
false /* forceReloadMainDictionary */, this);
|
||||
if (settingsValues.mCorrectionEnabled) {
|
||||
mInputLogic.mSuggest.setAutoCorrectionThreshold(
|
||||
settingsValues.mAutoCorrectionThreshold);
|
||||
}
|
||||
}
|
||||
|
||||
private void replaceSuggest(final Suggest newSuggest) {
|
||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||
ResearchLogger.getInstance().initDictionary(newSuggest.mDictionaryFacilitator);
|
||||
}
|
||||
mInputLogic.replaceSuggest(newSuggest);
|
||||
refreshPersonalizationDictionarySession();
|
||||
/**
|
||||
* Reset suggest by loading the main dictionary of the current locale.
|
||||
*/
|
||||
/* package private */ void resetSuggestMainDict() {
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator;
|
||||
final SettingsValues settingsValues = mSettings.getCurrent();
|
||||
dictionaryFacilitator.resetDictionaries(this /* context */,
|
||||
dictionaryFacilitator.getLocale(), settingsValues.mUseContactsDict,
|
||||
settingsValues.mUsePersonalizedDicts, true /* forceReloadMainDictionary */, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
final Suggest suggest = mInputLogic.mSuggest;
|
||||
if (suggest != null) {
|
||||
suggest.close();
|
||||
mInputLogic.mSuggest = null;
|
||||
}
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator.closeDictionaries();
|
||||
mSettings.onDestroy();
|
||||
unregisterReceiver(mReceiver);
|
||||
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
|
||||
|
@ -802,10 +779,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
// Note: the following does a round-trip IPC on the main thread: be careful
|
||||
final Locale currentLocale = mSubtypeSwitcher.getCurrentSubtypeLocale();
|
||||
Suggest suggest = mInputLogic.mSuggest;
|
||||
if (null != suggest && null != currentLocale && !currentLocale.equals(suggest.mLocale)) {
|
||||
initSuggest();
|
||||
suggest = mInputLogic.mSuggest;
|
||||
final Suggest suggest = mInputLogic.mSuggest;
|
||||
if (null != currentLocale && !currentLocale.equals(suggest.getLocale())) {
|
||||
// TODO: Do this automatically.
|
||||
resetSuggest();
|
||||
}
|
||||
|
||||
// TODO[IL]: Can the following be moved to InputLogic#startInput?
|
||||
|
@ -833,13 +810,12 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
if (isDifferentTextField ||
|
||||
!currentSettingsValues.hasSameOrientation(getResources().getConfiguration())) {
|
||||
loadSettings();
|
||||
suggest = mInputLogic.mSuggest;
|
||||
}
|
||||
if (isDifferentTextField) {
|
||||
mainKeyboardView.closing();
|
||||
currentSettingsValues = mSettings.getCurrent();
|
||||
|
||||
if (suggest != null && currentSettingsValues.mCorrectionEnabled) {
|
||||
if (currentSettingsValues.mCorrectionEnabled) {
|
||||
suggest.setAutoCorrectionThreshold(currentSettingsValues.mAutoCorrectionThreshold);
|
||||
}
|
||||
|
||||
|
@ -865,8 +841,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
|
||||
mHandler.cancelUpdateSuggestionStrip();
|
||||
|
||||
mainKeyboardView.setMainDictionaryAvailability(null != suggest
|
||||
? suggest.mDictionaryFacilitator.hasMainDictionary() : false);
|
||||
mainKeyboardView.setMainDictionaryAvailability(
|
||||
suggest.mDictionaryFacilitator.hasInitializedMainDictionary());
|
||||
mainKeyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn,
|
||||
currentSettingsValues.mKeyPreviewPopupDismissDelay);
|
||||
mainKeyboardView.setSlidingKeyInputPreviewEnabled(
|
||||
|
@ -1407,8 +1383,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
public void getSuggestedWords(final int sessionId, final int sequenceNumber,
|
||||
final OnGetSuggestedWordsCallback callback) {
|
||||
final Keyboard keyboard = mKeyboardSwitcher.getKeyboard();
|
||||
final Suggest suggest = mInputLogic.mSuggest;
|
||||
if (keyboard == null || suggest == null) {
|
||||
if (keyboard == null) {
|
||||
callback.onGetSuggestedWords(SuggestedWords.EMPTY);
|
||||
return;
|
||||
}
|
||||
|
@ -1437,7 +1412,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
}
|
||||
}
|
||||
suggest.getSuggestedWords(mInputLogic.mWordComposer,
|
||||
mInputLogic.mSuggest.getSuggestedWords(mInputLogic.mWordComposer,
|
||||
mInputLogic.mWordComposer.getPreviousWordForSuggestion(),
|
||||
keyboard.getProximityInfo(), currentSettings.mBlockPotentiallyOffensive,
|
||||
currentSettings.mCorrectionEnabled, additionalFeaturesOptions, sessionId,
|
||||
|
@ -1722,12 +1697,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
// 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) {
|
||||
final DictionaryFacilitatorForSuggest oldDictionaryFacilitator =
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator;
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
new DictionaryFacilitatorForSuggest(this, locale, mSettings.getCurrent(),
|
||||
this /* listener */, oldDictionaryFacilitator);
|
||||
replaceSuggest(new Suggest(locale, dictionaryFacilitator));
|
||||
final SettingsValues settingsValues = mSettings.getCurrent();
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator.resetDictionaries(this, locale,
|
||||
settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
|
||||
false /* forceReloadMainDictionary */, this /* listener */);
|
||||
}
|
||||
|
||||
// DO NOT USE THIS for any other purpose than testing.
|
||||
|
@ -1738,8 +1711,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
|||
}
|
||||
|
||||
public void dumpDictionaryForDebug(final String dictName) {
|
||||
if (mInputLogic.mSuggest == null) {
|
||||
initSuggest();
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator;
|
||||
if (dictionaryFacilitator.getLocale() == null) {
|
||||
resetSuggest();
|
||||
}
|
||||
mInputLogic.mSuggest.mDictionaryFacilitator.dumpDictionaryForDebug(dictName);
|
||||
}
|
||||
|
|
|
@ -23,12 +23,11 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
|||
import com.android.inputmethod.latin.define.ProductionFlag;
|
||||
import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
|
||||
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
|
||||
import com.android.inputmethod.latin.utils.BoundedTreeSet;
|
||||
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||
import com.android.inputmethod.latin.utils.StringUtils;
|
||||
import com.android.inputmethod.latin.utils.SuggestionResults;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
|
@ -53,29 +52,16 @@ public final class Suggest {
|
|||
private static final int SUPPRESS_SUGGEST_THRESHOLD = -2000000000;
|
||||
|
||||
private static final boolean DBG = LatinImeLogger.sDBG;
|
||||
public final DictionaryFacilitatorForSuggest mDictionaryFacilitator;
|
||||
public final DictionaryFacilitatorForSuggest mDictionaryFacilitator =
|
||||
new DictionaryFacilitatorForSuggest();
|
||||
|
||||
private float mAutoCorrectionThreshold;
|
||||
|
||||
// Locale used for upper- and title-casing words
|
||||
public final Locale mLocale;
|
||||
|
||||
// TODO: Move dictionaryFacilitator constructing logics from LatinIME to Suggest.
|
||||
public Suggest(final Locale locale,
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator) {
|
||||
mLocale = locale;
|
||||
mDictionaryFacilitator = dictionaryFacilitator;
|
||||
public Locale getLocale() {
|
||||
return mDictionaryFacilitator.getLocale();
|
||||
}
|
||||
|
||||
// Creates instance with new dictionary facilitator.
|
||||
public Suggest(final Suggest oldSuggst,
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator) {
|
||||
mLocale = oldSuggst.mLocale;
|
||||
mAutoCorrectionThreshold = oldSuggst.mAutoCorrectionThreshold;
|
||||
mDictionaryFacilitator = dictionaryFacilitator;
|
||||
}
|
||||
|
||||
public void setAutoCorrectionThreshold(float threshold) {
|
||||
public void setAutoCorrectionThreshold(final float threshold) {
|
||||
mAutoCorrectionThreshold = threshold;
|
||||
}
|
||||
|
||||
|
@ -108,9 +94,6 @@ public final class Suggest {
|
|||
final int[] additionalFeaturesOptions, final int sequenceNumber,
|
||||
final OnGetSuggestedWordsCallback callback) {
|
||||
final int trailingSingleQuotesCount = wordComposer.trailingSingleQuotesCount();
|
||||
final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator,
|
||||
SuggestedWords.MAX_SUGGESTIONS);
|
||||
|
||||
final String typedWord = wordComposer.getTypedWord();
|
||||
final String consideredWord = trailingSingleQuotesCount > 0
|
||||
? typedWord.substring(0, typedWord.length() - trailingSingleQuotesCount)
|
||||
|
@ -132,20 +115,20 @@ public final class Suggest {
|
|||
} else {
|
||||
rawSuggestions = null;
|
||||
}
|
||||
mDictionaryFacilitator.getSuggestions(wordComposerForLookup, prevWordForBigram,
|
||||
proximityInfo, blockOffensiveWords, additionalFeaturesOptions, SESSION_TYPING,
|
||||
suggestionsSet, rawSuggestions);
|
||||
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
|
||||
wordComposerForLookup, prevWordForBigram, proximityInfo, blockOffensiveWords,
|
||||
additionalFeaturesOptions, SESSION_TYPING, rawSuggestions);
|
||||
|
||||
final boolean isFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
|
||||
final boolean isAllUpperCase = wordComposer.isAllUpperCase();
|
||||
final String firstSuggestion;
|
||||
final String whitelistedWord;
|
||||
if (suggestionsSet.isEmpty()) {
|
||||
if (suggestionResults.isEmpty()) {
|
||||
whitelistedWord = firstSuggestion = null;
|
||||
} else {
|
||||
final SuggestedWordInfo firstSuggestedWordInfo = getTransformedSuggestedWordInfo(
|
||||
suggestionsSet.first(), mLocale, isAllUpperCase, isFirstCharCapitalized,
|
||||
trailingSingleQuotesCount);
|
||||
suggestionResults.first(), suggestionResults.mLocale, isAllUpperCase,
|
||||
isFirstCharCapitalized, trailingSingleQuotesCount);
|
||||
firstSuggestion = firstSuggestedWordInfo.mWord;
|
||||
if (SuggestedWordInfo.KIND_WHITELIST != firstSuggestedWordInfo.mKind) {
|
||||
whitelistedWord = null;
|
||||
|
@ -175,10 +158,10 @@ public final class Suggest {
|
|||
// the current settings. It may also be useful to know, when the setting is off, whether
|
||||
// the word *would* have been auto-corrected.
|
||||
if (!isCorrectionEnabled || !allowsToBeAutoCorrected || isPrediction
|
||||
|| suggestionsSet.isEmpty() || wordComposer.hasDigits()
|
||||
|| suggestionResults.isEmpty() || wordComposer.hasDigits()
|
||||
|| wordComposer.isMostlyCaps() || wordComposer.isResumed()
|
||||
|| !mDictionaryFacilitator.hasMainDictionary()
|
||||
|| SuggestedWordInfo.KIND_SHORTCUT == suggestionsSet.first().mKind) {
|
||||
|| !mDictionaryFacilitator.hasInitializedMainDictionary()
|
||||
|| SuggestedWordInfo.KIND_SHORTCUT == suggestionResults.first().mKind) {
|
||||
// If we don't have a main dictionary, we never want to auto-correct. The reason for
|
||||
// this is, the user may have a contact whose name happens to match a valid word in
|
||||
// their language, and it will unexpectedly auto-correct. For example, if the user
|
||||
|
@ -190,17 +173,17 @@ public final class Suggest {
|
|||
hasAutoCorrection = false;
|
||||
} else {
|
||||
hasAutoCorrection = AutoCorrectionUtils.suggestionExceedsAutoCorrectionThreshold(
|
||||
suggestionsSet.first(), consideredWord, mAutoCorrectionThreshold);
|
||||
suggestionResults.first(), consideredWord, mAutoCorrectionThreshold);
|
||||
}
|
||||
|
||||
final ArrayList<SuggestedWordInfo> suggestionsContainer =
|
||||
CollectionUtils.newArrayList(suggestionsSet);
|
||||
CollectionUtils.newArrayList(suggestionResults);
|
||||
final int suggestionsCount = suggestionsContainer.size();
|
||||
if (isFirstCharCapitalized || isAllUpperCase || 0 != trailingSingleQuotesCount) {
|
||||
for (int i = 0; i < suggestionsCount; ++i) {
|
||||
final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
|
||||
final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
|
||||
wordInfo, mLocale, isAllUpperCase, isFirstCharCapitalized,
|
||||
wordInfo, suggestionResults.mLocale, isAllUpperCase, isFirstCharCapitalized,
|
||||
trailingSingleQuotesCount);
|
||||
suggestionsContainer.set(i, transformedWordInfo);
|
||||
}
|
||||
|
@ -244,23 +227,21 @@ public final class Suggest {
|
|||
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
|
||||
final int sessionId, final int sequenceNumber,
|
||||
final OnGetSuggestedWordsCallback callback) {
|
||||
final BoundedTreeSet suggestionsSet = new BoundedTreeSet(sSuggestedWordInfoComparator,
|
||||
SuggestedWords.MAX_SUGGESTIONS);
|
||||
final ArrayList<SuggestedWordInfo> rawSuggestions;
|
||||
if (ProductionFlag.INCLUDE_RAW_SUGGESTIONS) {
|
||||
rawSuggestions = CollectionUtils.newArrayList();
|
||||
} else {
|
||||
rawSuggestions = null;
|
||||
}
|
||||
mDictionaryFacilitator.getSuggestions(wordComposer, prevWordForBigram, proximityInfo,
|
||||
blockOffensiveWords, additionalFeaturesOptions, sessionId, suggestionsSet,
|
||||
rawSuggestions);
|
||||
for (SuggestedWordInfo wordInfo : suggestionsSet) {
|
||||
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
|
||||
wordComposer, prevWordForBigram, proximityInfo, blockOffensiveWords,
|
||||
additionalFeaturesOptions, sessionId, rawSuggestions);
|
||||
for (SuggestedWordInfo wordInfo : suggestionResults) {
|
||||
LatinImeLogger.onAddSuggestedWord(wordInfo.mWord, wordInfo.mSourceDict.mDictType);
|
||||
}
|
||||
|
||||
final ArrayList<SuggestedWordInfo> suggestionsContainer =
|
||||
CollectionUtils.newArrayList(suggestionsSet);
|
||||
CollectionUtils.newArrayList(suggestionResults);
|
||||
final int suggestionsCount = suggestionsContainer.size();
|
||||
final boolean isFirstCharCapitalized = wordComposer.wasShiftedNoLock();
|
||||
final boolean isAllUpperCase = wordComposer.isAllUpperCase();
|
||||
|
@ -268,7 +249,7 @@ public final class Suggest {
|
|||
for (int i = 0; i < suggestionsCount; ++i) {
|
||||
final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
|
||||
final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
|
||||
wordInfo, mLocale, isAllUpperCase, isFirstCharCapitalized,
|
||||
wordInfo, suggestionResults.mLocale, isAllUpperCase, isFirstCharCapitalized,
|
||||
0 /* trailingSingleQuotesCount */);
|
||||
suggestionsContainer.set(i, transformedWordInfo);
|
||||
}
|
||||
|
@ -326,22 +307,6 @@ public final class Suggest {
|
|||
return suggestionsList;
|
||||
}
|
||||
|
||||
private static final class SuggestedWordInfoComparator
|
||||
implements Comparator<SuggestedWordInfo> {
|
||||
// This comparator ranks the word info with the higher frequency first. That's because
|
||||
// that's the order we want our elements in.
|
||||
@Override
|
||||
public int compare(final SuggestedWordInfo o1, final SuggestedWordInfo o2) {
|
||||
if (o1.mScore > o2.mScore) return -1;
|
||||
if (o1.mScore < o2.mScore) return 1;
|
||||
if (o1.mCodePointCount < o2.mCodePointCount) return -1;
|
||||
if (o1.mCodePointCount > o2.mCodePointCount) return 1;
|
||||
return o1.mWord.compareTo(o2.mWord);
|
||||
}
|
||||
}
|
||||
private static final SuggestedWordInfoComparator sSuggestedWordInfoComparator =
|
||||
new SuggestedWordInfoComparator();
|
||||
|
||||
/* package for test */ static SuggestedWordInfo getTransformedSuggestedWordInfo(
|
||||
final SuggestedWordInfo wordInfo, final Locale locale, final boolean isAllUpperCase,
|
||||
final boolean isFirstCharCapitalized, final int trailingSingleQuotesCount) {
|
||||
|
@ -365,8 +330,4 @@ public final class Suggest {
|
|||
wordInfo.mSourceDict, wordInfo.mIndexOfTouchPointOfSecondWord,
|
||||
wordInfo.mAutoCommitFirstWordConfidence);
|
||||
}
|
||||
|
||||
public void close() {
|
||||
mDictionaryFacilitator.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,6 +32,7 @@ import com.android.inputmethod.event.InputTransaction;
|
|||
import com.android.inputmethod.keyboard.KeyboardSwitcher;
|
||||
import com.android.inputmethod.latin.Constants;
|
||||
import com.android.inputmethod.latin.Dictionary;
|
||||
import com.android.inputmethod.latin.DictionaryFacilitatorForSuggest;
|
||||
import com.android.inputmethod.latin.InputPointers;
|
||||
import com.android.inputmethod.latin.LastComposedWord;
|
||||
import com.android.inputmethod.latin.LatinIME;
|
||||
|
@ -77,8 +78,7 @@ public final class InputLogic {
|
|||
private int mSpaceState;
|
||||
// Never null
|
||||
public SuggestedWords mSuggestedWords = SuggestedWords.EMPTY;
|
||||
// TODO: mSuggest should be touched by a single thread.
|
||||
public volatile Suggest mSuggest;
|
||||
public final Suggest mSuggest = new Suggest();
|
||||
|
||||
public LastComposedWord mLastComposedWord = LastComposedWord.NOT_A_COMPOSED_WORD;
|
||||
public final WordComposer mWordComposer;
|
||||
|
@ -106,15 +106,6 @@ public final class InputLogic {
|
|||
mInputLogicHandler = InputLogicHandler.NULL_HANDLER;
|
||||
}
|
||||
|
||||
// Replace the old Suggest with the passed Suggest and close it.
|
||||
public void replaceSuggest(final Suggest newSuggest) {
|
||||
final Suggest oldSuggest = mSuggest;
|
||||
mSuggest = newSuggest;
|
||||
if (oldSuggest != null) {
|
||||
oldSuggest.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the input logic for input in an editor.
|
||||
*
|
||||
|
@ -283,23 +274,18 @@ public final class InputLogic {
|
|||
|
||||
// We should show the "Touch again to save" hint if the user pressed the first entry
|
||||
// AND it's in none of our current dictionaries (main, user or otherwise).
|
||||
// Please note that if mSuggest is null, it means that everything is off: suggestion
|
||||
// and correction, so we shouldn't try to show the hint
|
||||
final Suggest suggest = mSuggest;
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator =
|
||||
mSuggest.mDictionaryFacilitator;
|
||||
final boolean showingAddToDictionaryHint =
|
||||
(SuggestedWordInfo.KIND_TYPED == suggestionInfo.mKind
|
||||
|| SuggestedWordInfo.KIND_OOV_CORRECTION == suggestionInfo.mKind)
|
||||
&& suggest != null
|
||||
// If the suggestion is not in the dictionary, the hint should be shown.
|
||||
&& !suggest.mDictionaryFacilitator.isValidWord(suggestion,
|
||||
true /* ignoreCase */);
|
||||
&& !dictionaryFacilitator.isValidWord(suggestion, true /* ignoreCase */);
|
||||
|
||||
if (settingsValues.mIsInternal) {
|
||||
LatinImeLoggerUtils.onSeparator((char)Constants.CODE_SPACE,
|
||||
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
|
||||
}
|
||||
if (showingAddToDictionaryHint
|
||||
&& suggest.mDictionaryFacilitator.isUserDictionaryEnabled()) {
|
||||
if (showingAddToDictionaryHint && dictionaryFacilitator.isUserDictionaryEnabled()) {
|
||||
mSuggestionStripViewAccessor.showAddToDictionaryHint(suggestion);
|
||||
} else {
|
||||
// If we're not showing the "Touch again to save", then update the suggestion strip.
|
||||
|
@ -1231,20 +1217,17 @@ public final class InputLogic {
|
|||
if (!settingsValues.mCorrectionEnabled) return;
|
||||
|
||||
if (TextUtils.isEmpty(suggestion)) return;
|
||||
final Suggest suggest = mSuggest;
|
||||
if (suggest == null) return;
|
||||
|
||||
final boolean wasAutoCapitalized =
|
||||
mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps();
|
||||
final int timeStampInSeconds = (int)TimeUnit.MILLISECONDS.toSeconds(
|
||||
System.currentTimeMillis());
|
||||
suggest.mDictionaryFacilitator.addToUserHistory(suggestion, wasAutoCapitalized, prevWord,
|
||||
mSuggest.mDictionaryFacilitator.addToUserHistory(suggestion, wasAutoCapitalized, prevWord,
|
||||
timeStampInSeconds);
|
||||
}
|
||||
|
||||
public void performUpdateSuggestionStripSync(final SettingsValues settingsValues) {
|
||||
// Check if we have a suggestion engine attached.
|
||||
if (mSuggest == null || !settingsValues.isSuggestionsRequested()) {
|
||||
if (!settingsValues.isSuggestionsRequested()) {
|
||||
if (mWordComposer.isComposingWord()) {
|
||||
Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not "
|
||||
+ "requested!");
|
||||
|
@ -1446,11 +1429,9 @@ public final class InputLogic {
|
|||
}
|
||||
mConnection.deleteSurroundingText(deleteLength, 0);
|
||||
if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
|
||||
if (mSuggest != null) {
|
||||
mSuggest.mDictionaryFacilitator.cancelAddingUserHistory(
|
||||
previousWord, committedWordString);
|
||||
}
|
||||
}
|
||||
final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString;
|
||||
final SpannableString textToCommit = new SpannableString(stringToCommit);
|
||||
if (committedWord instanceof SpannableString) {
|
||||
|
|
|
@ -1,49 +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.utils;
|
||||
|
||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* A TreeSet that is bounded in size and throws everything that's smaller than its limit
|
||||
*/
|
||||
public final class BoundedTreeSet extends TreeSet<SuggestedWordInfo> {
|
||||
private final int mCapacity;
|
||||
public BoundedTreeSet(final Comparator<SuggestedWordInfo> comparator, final int capacity) {
|
||||
super(comparator);
|
||||
mCapacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(final SuggestedWordInfo e) {
|
||||
if (size() < mCapacity) return super.add(e);
|
||||
if (comparator().compare(e, last()) > 0) return false;
|
||||
super.add(e);
|
||||
pollLast(); // removes the last element
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(final Collection<? extends SuggestedWordInfo> e) {
|
||||
if (null == e) return false;
|
||||
return super.addAll(e);
|
||||
}
|
||||
}
|
|
@ -119,7 +119,7 @@ public final class LanguageModelParam {
|
|||
private static LanguageModelParam detectWhetherVaildWordOrNotAndGetLanguageModelParam(
|
||||
final String prevWord, final String targetWord, final int timestamp,
|
||||
final DictionaryFacilitatorForSuggest dictionaryFacilitator) {
|
||||
final Locale locale = dictionaryFacilitator.mLocale;
|
||||
final Locale locale = dictionaryFacilitator.getLocale();
|
||||
if (!dictionaryFacilitator.isValidWord(targetWord, true /* ignoreCase */)) {
|
||||
// OOV word.
|
||||
return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* Copyright (C) 2014 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.utils;
|
||||
|
||||
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Locale;
|
||||
import java.util.TreeSet;
|
||||
|
||||
/**
|
||||
* A TreeSet of SuggestedWordInfo that is bounded in size and throws everything that's smaller
|
||||
* than its limit
|
||||
*/
|
||||
public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
|
||||
public final Locale mLocale;
|
||||
private final int mCapacity;
|
||||
|
||||
public SuggestionResults(final Locale locale, final int capacity) {
|
||||
this(locale, sSuggestedWordInfoComparator, capacity);
|
||||
}
|
||||
|
||||
public SuggestionResults(final Locale locale, final Comparator<SuggestedWordInfo> comparator,
|
||||
final int capacity) {
|
||||
super(comparator);
|
||||
mLocale = locale;
|
||||
mCapacity = capacity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(final SuggestedWordInfo e) {
|
||||
if (size() < mCapacity) return super.add(e);
|
||||
if (comparator().compare(e, last()) > 0) return false;
|
||||
super.add(e);
|
||||
pollLast(); // removes the last element
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(final Collection<? extends SuggestedWordInfo> e) {
|
||||
if (null == e) return false;
|
||||
return super.addAll(e);
|
||||
}
|
||||
|
||||
private static final class SuggestedWordInfoComparator
|
||||
implements Comparator<SuggestedWordInfo> {
|
||||
// This comparator ranks the word info with the higher frequency first. That's because
|
||||
// that's the order we want our elements in.
|
||||
@Override
|
||||
public int compare(final SuggestedWordInfo o1, final SuggestedWordInfo o2) {
|
||||
if (o1.mScore > o2.mScore) return -1;
|
||||
if (o1.mScore < o2.mScore) return 1;
|
||||
if (o1.mCodePointCount < o2.mCodePointCount) return -1;
|
||||
if (o1.mCodePointCount > o2.mCodePointCount) return 1;
|
||||
return o1.mWord.compareTo(o2.mWord);
|
||||
}
|
||||
}
|
||||
|
||||
private static final SuggestedWordInfoComparator sSuggestedWordInfoComparator =
|
||||
new SuggestedWordInfoComparator();
|
||||
}
|
|
@ -155,7 +155,8 @@ public abstract class MainLogBuffer extends FixedLogBuffer {
|
|||
}
|
||||
// Reload the dictionary in case it has changed (e.g., because the user has changed
|
||||
// languages).
|
||||
if ((mDictionaryFacilitator == null || !mDictionaryFacilitator.hasMainDictionary())
|
||||
if ((mDictionaryFacilitator == null
|
||||
|| !mDictionaryFacilitator.hasInitializedMainDictionary())
|
||||
&& mDictionaryForTesting == null) {
|
||||
// Main dictionary is unavailable. Since we cannot check it, we cannot tell if a
|
||||
// word is out-of-vocabulary or not. Therefore, we must judge the entire buffer
|
||||
|
|
Loading…
Reference in New Issue