[ML7] Have multiple DictionaryGroup instances in facilitator
This is the central change of multilingual input. Bug: 11230254 Change-Id: Id8b68fb101e837e8cf182ab4bc1e55e4da5cc49dmain
parent
97b465044f
commit
8cd5326622
|
@ -61,9 +61,9 @@ public class DictionaryFacilitator {
|
||||||
// dictionary.
|
// dictionary.
|
||||||
private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140;
|
private static final int CAPITALIZED_FORM_MAX_PROBABILITY_FOR_INSERT = 140;
|
||||||
|
|
||||||
private DictionaryGroup mDictionaryGroup = new DictionaryGroup();
|
private DictionaryGroup[] mDictionaryGroups = new DictionaryGroup[] { new DictionaryGroup() };
|
||||||
private boolean mIsUserDictEnabled = false;
|
private boolean mIsUserDictEnabled = false;
|
||||||
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0);
|
private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0);
|
||||||
// To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
|
// To synchronize assigning mDictionaryGroup to ensure closing dictionaries.
|
||||||
private final Object mLock = new Object();
|
private final Object mLock = new Object();
|
||||||
private final DistracterFilter mDistracterFilter;
|
private final DistracterFilter mDistracterFilter;
|
||||||
|
@ -193,8 +193,9 @@ public class DictionaryFacilitator {
|
||||||
mPersonalizationHelper.setIsMonolingualUser(isMonolingualUser);
|
mPersonalizationHelper.setIsMonolingualUser(isMonolingualUser);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove this, replace with version returning multiple locales
|
||||||
public Locale getLocale() {
|
public Locale getLocale() {
|
||||||
return mDictionaryGroup.mLocale;
|
return mDictionaryGroups[0].mLocale;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ExpandableBinaryDictionary getSubDict(final String dictType,
|
private static ExpandableBinaryDictionary getSubDict(final String dictType,
|
||||||
|
@ -226,6 +227,21 @@ public class DictionaryFacilitator {
|
||||||
usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
|
usePersonalizedDicts, forceReloadMainDictionary, listener, "" /* dictNamePrefix */);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private DictionaryGroup findDictionaryGroupWithLocale(final DictionaryGroup[] dictionaryGroups,
|
||||||
|
final Locale locale) {
|
||||||
|
for (int i = 0; i < dictionaryGroups.length; ++i) {
|
||||||
|
if (locale.equals(dictionaryGroups[i].mLocale)) {
|
||||||
|
return dictionaryGroups[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private DictionaryGroup getDictionaryGroupForActiveLanguage() {
|
||||||
|
// TODO: implement this
|
||||||
|
return mDictionaryGroups[0];
|
||||||
|
}
|
||||||
|
|
||||||
public void resetDictionariesWithDictNamePrefix(final Context context,
|
public void resetDictionariesWithDictNamePrefix(final Context context,
|
||||||
final Locale newLocaleToUse,
|
final Locale newLocaleToUse,
|
||||||
final boolean useContactsDict, final boolean usePersonalizedDicts,
|
final boolean useContactsDict, final boolean usePersonalizedDicts,
|
||||||
|
@ -252,7 +268,7 @@ public class DictionaryFacilitator {
|
||||||
final ArrayList<String> dictsForLocale = new ArrayList<>();
|
final ArrayList<String> dictsForLocale = new ArrayList<>();
|
||||||
existingDictsToCleanup.put(newLocale, dictsForLocale);
|
existingDictsToCleanup.put(newLocale, dictsForLocale);
|
||||||
final DictionaryGroup currentDictionaryGroupForLocale =
|
final DictionaryGroup currentDictionaryGroupForLocale =
|
||||||
newLocale.equals(mDictionaryGroup.mLocale) ? mDictionaryGroup : null;
|
findDictionaryGroupWithLocale(mDictionaryGroups, newLocale);
|
||||||
if (null == currentDictionaryGroupForLocale) {
|
if (null == currentDictionaryGroupForLocale) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -266,10 +282,11 @@ public class DictionaryFacilitator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final HashMap<Locale, DictionaryGroup> newDictionaryGroups = new HashMap<>();
|
final DictionaryGroup[] newDictionaryGroups = new DictionaryGroup[newLocales.length];
|
||||||
for (final Locale newLocale : newLocales) {
|
for (int i = 0; i < newLocales.length; ++i) {
|
||||||
|
final Locale newLocale = newLocales[i];
|
||||||
final DictionaryGroup dictionaryGroupForLocale =
|
final DictionaryGroup dictionaryGroupForLocale =
|
||||||
newLocale.equals(mDictionaryGroup.mLocale) ? mDictionaryGroup : null;
|
findDictionaryGroupWithLocale(mDictionaryGroups, newLocale);
|
||||||
final ArrayList<String> dictsToCleanupForLocale = existingDictsToCleanup.get(newLocale);
|
final ArrayList<String> dictsToCleanupForLocale = existingDictsToCleanup.get(newLocale);
|
||||||
final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale);
|
final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale);
|
||||||
|
|
||||||
|
@ -297,30 +314,29 @@ public class DictionaryFacilitator {
|
||||||
}
|
}
|
||||||
subDicts.put(subDictType, subDict);
|
subDicts.put(subDictType, subDict);
|
||||||
}
|
}
|
||||||
newDictionaryGroups.put(newLocale, new DictionaryGroup(newLocale, mainDict, subDicts));
|
newDictionaryGroups[i] = new DictionaryGroup(newLocale, mainDict, subDicts);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace Dictionaries.
|
// Replace Dictionaries.
|
||||||
// TODO: use multiple locales.
|
final DictionaryGroup[] oldDictionaryGroups;
|
||||||
final DictionaryGroup newDictionaryGroup = newDictionaryGroups.get(newLocaleToUse);
|
|
||||||
final DictionaryGroup oldDictionaryGroup;
|
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
oldDictionaryGroup = mDictionaryGroup;
|
oldDictionaryGroups = mDictionaryGroups;
|
||||||
mDictionaryGroup = newDictionaryGroup;
|
mDictionaryGroups = newDictionaryGroups;
|
||||||
mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context);
|
mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context);
|
||||||
if (null == newDictionaryGroup.getDict(Dictionary.TYPE_MAIN)) {
|
if (hasAtLeastOneUninitializedMainDictionary()) {
|
||||||
asyncReloadUninitializedMainDictionaries(context, newLocales, listener);
|
asyncReloadUninitializedMainDictionaries(context, newLocales, listener);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary());
|
listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up old dictionaries.
|
// Clean up old dictionaries.
|
||||||
for (final Locale localeToCleanUp : existingDictsToCleanup.keySet()) {
|
for (final Locale localeToCleanUp : existingDictsToCleanup.keySet()) {
|
||||||
final ArrayList<String> dictTypesToCleanUp =
|
final ArrayList<String> dictTypesToCleanUp =
|
||||||
existingDictsToCleanup.get(localeToCleanUp);
|
existingDictsToCleanup.get(localeToCleanUp);
|
||||||
final DictionaryGroup dictionarySetToCleanup = oldDictionaryGroup;
|
final DictionaryGroup dictionarySetToCleanup =
|
||||||
|
findDictionaryGroupWithLocale(oldDictionaryGroups, localeToCleanUp);
|
||||||
for (final String dictType : dictTypesToCleanUp) {
|
for (final String dictType : dictTypesToCleanUp) {
|
||||||
dictionarySetToCleanup.closeDict(dictType);
|
dictionarySetToCleanup.closeDict(dictType);
|
||||||
}
|
}
|
||||||
|
@ -330,12 +346,18 @@ public class DictionaryFacilitator {
|
||||||
private void asyncReloadUninitializedMainDictionaries(final Context context,
|
private void asyncReloadUninitializedMainDictionaries(final Context context,
|
||||||
final Locale[] locales, final DictionaryInitializationListener listener) {
|
final Locale[] locales, final DictionaryInitializationListener listener) {
|
||||||
final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1);
|
final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1);
|
||||||
mLatchForWaitingLoadingMainDictionary = latchForWaitingLoadingMainDictionary;
|
mLatchForWaitingLoadingMainDictionaries = latchForWaitingLoadingMainDictionary;
|
||||||
ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
|
ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for (final Locale locale : locales) {
|
for (final Locale locale : locales) {
|
||||||
final DictionaryGroup dictionaryGroup = mDictionaryGroup;
|
final DictionaryGroup dictionaryGroup =
|
||||||
|
findDictionaryGroupWithLocale(mDictionaryGroups, locale);
|
||||||
|
if (null == dictionaryGroup) {
|
||||||
|
// This should never happen, but better safe than crashy
|
||||||
|
Log.w(TAG, "Expected a dictionary group for " + locale + " but none found");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
final Dictionary mainDict =
|
final Dictionary mainDict =
|
||||||
DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
DictionaryFactory.createMainDictionaryFromManager(context, locale);
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
|
@ -348,7 +370,8 @@ public class DictionaryFacilitator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary());
|
listener.onUpdateMainDictionaryAvailability(
|
||||||
|
hasAtLeastOneInitializedMainDictionary());
|
||||||
}
|
}
|
||||||
latchForWaitingLoadingMainDictionary.countDown();
|
latchForWaitingLoadingMainDictionary.countDown();
|
||||||
}
|
}
|
||||||
|
@ -381,17 +404,20 @@ public class DictionaryFacilitator {
|
||||||
subDicts.put(dictType, dict);
|
subDicts.put(dictType, dict);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mDictionaryGroup = new DictionaryGroup(locale, mainDictionary, subDicts);
|
mDictionaryGroups = new DictionaryGroup[] {
|
||||||
|
new DictionaryGroup(locale, mainDictionary, subDicts) };
|
||||||
}
|
}
|
||||||
|
|
||||||
public void closeDictionaries() {
|
public void closeDictionaries() {
|
||||||
final DictionaryGroup dictionaryGroup;
|
final DictionaryGroup[] dictionaryGroups;
|
||||||
synchronized (mLock) {
|
synchronized (mLock) {
|
||||||
dictionaryGroup = mDictionaryGroup;
|
dictionaryGroups = mDictionaryGroups;
|
||||||
mDictionaryGroup = new DictionaryGroup();
|
mDictionaryGroups = new DictionaryGroup[] { new DictionaryGroup() };
|
||||||
}
|
}
|
||||||
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
dictionaryGroup.closeDict(dictType);
|
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
||||||
|
dictionaryGroup.closeDict(dictType);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
mDistracterFilter.close();
|
mDistracterFilter.close();
|
||||||
if (mPersonalizationHelper != null) {
|
if (mPersonalizationHelper != null) {
|
||||||
|
@ -401,40 +427,71 @@ public class DictionaryFacilitator {
|
||||||
|
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
public ExpandableBinaryDictionary getSubDictForTesting(final String dictName) {
|
public ExpandableBinaryDictionary getSubDictForTesting(final String dictName) {
|
||||||
return mDictionaryGroup.getSubDict(dictName);
|
return mDictionaryGroups[0].getSubDict(dictName);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The main dictionary could have been loaded asynchronously. Don't cache the return value
|
// The main dictionaries are loaded asynchronously. Don't cache the return value
|
||||||
// of this method.
|
// of these methods.
|
||||||
public boolean hasInitializedMainDictionary() {
|
public boolean hasAtLeastOneInitializedMainDictionary() {
|
||||||
final Dictionary mainDict = mDictionaryGroup.getDict(Dictionary.TYPE_MAIN);
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
return mainDict != null && mainDict.isInitialized();
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
|
final Dictionary mainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN);
|
||||||
|
if (mainDict != null && mainDict.isInitialized()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean hasAtLeastOneUninitializedMainDictionary() {
|
||||||
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
|
final Dictionary mainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN);
|
||||||
|
if (mainDict == null || !mainDict.isInitialized()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasPersonalizationDictionary() {
|
public boolean hasPersonalizationDictionary() {
|
||||||
return mDictionaryGroup.hasDict(Dictionary.TYPE_PERSONALIZATION);
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
|
if (dictionaryGroup.hasDict(Dictionary.TYPE_PERSONALIZATION)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void flushPersonalizationDictionary() {
|
public void flushPersonalizationDictionary() {
|
||||||
final ExpandableBinaryDictionary personalizationDictUsedForSuggestion =
|
final HashSet<ExpandableBinaryDictionary> personalizationDictsUsedForSuggestion =
|
||||||
mDictionaryGroup.getSubDict(Dictionary.TYPE_PERSONALIZATION);
|
new HashSet<>();
|
||||||
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
|
final ExpandableBinaryDictionary personalizationDictUsedForSuggestion =
|
||||||
|
dictionaryGroup.getSubDict(Dictionary.TYPE_PERSONALIZATION);
|
||||||
|
personalizationDictsUsedForSuggestion.add(personalizationDictUsedForSuggestion);
|
||||||
|
}
|
||||||
mPersonalizationHelper.flushPersonalizationDictionariesToUpdate(
|
mPersonalizationHelper.flushPersonalizationDictionariesToUpdate(
|
||||||
personalizationDictUsedForSuggestion);
|
personalizationDictsUsedForSuggestion);
|
||||||
mDistracterFilter.close();
|
mDistracterFilter.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitForLoadingMainDictionary(final long timeout, final TimeUnit unit)
|
public void waitForLoadingMainDictionaries(final long timeout, final TimeUnit unit)
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
mLatchForWaitingLoadingMainDictionary.await(timeout, unit);
|
mLatchForWaitingLoadingMainDictionaries.await(timeout, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
@UsedForTesting
|
@UsedForTesting
|
||||||
public void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
|
public void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit)
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
waitForLoadingMainDictionary(timeout, unit);
|
waitForLoadingMainDictionaries(timeout, unit);
|
||||||
final Map<String, ExpandableBinaryDictionary> dictMap = mDictionaryGroup.mSubDictMap;
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
for (final ExpandableBinaryDictionary dict : dictMap.values()) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
dict.waitAllTasksForTests();
|
for (final ExpandableBinaryDictionary dict : dictionaryGroup.mSubDictMap.values()) {
|
||||||
|
dict.waitAllTasksForTests();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -453,7 +510,7 @@ public class DictionaryFacilitator {
|
||||||
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
public void addToUserHistory(final String suggestion, final boolean wasAutoCapitalized,
|
||||||
final PrevWordsInfo prevWordsInfo, final int timeStampInSeconds,
|
final PrevWordsInfo prevWordsInfo, final int timeStampInSeconds,
|
||||||
final boolean blockPotentiallyOffensive) {
|
final boolean blockPotentiallyOffensive) {
|
||||||
final DictionaryGroup dictionaryGroup = mDictionaryGroup;
|
final DictionaryGroup dictionaryGroup = getDictionaryGroupForActiveLanguage();
|
||||||
final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
|
final String[] words = suggestion.split(Constants.WORD_SEPARATOR);
|
||||||
PrevWordsInfo prevWordsInfoForCurrentWord = prevWordsInfo;
|
PrevWordsInfo prevWordsInfoForCurrentWord = prevWordsInfo;
|
||||||
for (int i = 0; i < words.length; i++) {
|
for (int i = 0; i < words.length; i++) {
|
||||||
|
@ -520,7 +577,8 @@ public class DictionaryFacilitator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeWord(final String dictName, final String word) {
|
private void removeWord(final String dictName, final String word) {
|
||||||
final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName);
|
final ExpandableBinaryDictionary dictionary =
|
||||||
|
getDictionaryGroupForActiveLanguage().getSubDict(dictName);
|
||||||
if (dictionary != null) {
|
if (dictionary != null) {
|
||||||
dictionary.removeUnigramEntryDynamically(word);
|
dictionary.removeUnigramEntryDynamically(word);
|
||||||
}
|
}
|
||||||
|
@ -536,20 +594,22 @@ public class DictionaryFacilitator {
|
||||||
public SuggestionResults getSuggestionResults(final WordComposer composer,
|
public SuggestionResults getSuggestionResults(final WordComposer composer,
|
||||||
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
|
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
|
||||||
final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId) {
|
final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId) {
|
||||||
final DictionaryGroup dictionaryGroup = mDictionaryGroup;
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
final SuggestionResults suggestionResults =
|
final SuggestionResults suggestionResults =
|
||||||
new SuggestionResults(SuggestedWords.MAX_SUGGESTIONS);
|
new SuggestionResults(SuggestedWords.MAX_SUGGESTIONS);
|
||||||
final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
|
final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
|
||||||
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
|
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
||||||
if (null == dictionary) continue;
|
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
|
||||||
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
|
if (null == dictionary) continue;
|
||||||
dictionary.getSuggestions(composer, prevWordsInfo, proximityInfo,
|
final ArrayList<SuggestedWordInfo> dictionarySuggestions =
|
||||||
settingsValuesForSuggestion, sessionId, languageWeight);
|
dictionary.getSuggestions(composer, prevWordsInfo, proximityInfo,
|
||||||
if (null == dictionarySuggestions) continue;
|
settingsValuesForSuggestion, sessionId, languageWeight);
|
||||||
suggestionResults.addAll(dictionarySuggestions);
|
if (null == dictionarySuggestions) continue;
|
||||||
if (null != suggestionResults.mRawSuggestions) {
|
suggestionResults.addAll(dictionarySuggestions);
|
||||||
suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
|
if (null != suggestionResults.mRawSuggestions) {
|
||||||
|
suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return suggestionResults;
|
return suggestionResults;
|
||||||
|
@ -559,20 +619,22 @@ public class DictionaryFacilitator {
|
||||||
if (TextUtils.isEmpty(word)) {
|
if (TextUtils.isEmpty(word)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
final DictionaryGroup dictionaryGroup = mDictionaryGroup;
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
if (dictionaryGroup.mLocale == null) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
return false;
|
if (dictionaryGroup.mLocale == null) {
|
||||||
}
|
continue;
|
||||||
final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale);
|
}
|
||||||
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale);
|
||||||
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
|
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
||||||
// Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
|
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
|
||||||
// would be immutable once it's finished initializing, but concretely a null test is
|
// Ideally the passed map would come out of a {@link java.util.concurrent.Future} and
|
||||||
// probably good enough for the time being.
|
// would be immutable once it's finished initializing, but concretely a null test is
|
||||||
if (null == dictionary) continue;
|
// probably good enough for the time being.
|
||||||
if (dictionary.isValidWord(word)
|
if (null == dictionary) continue;
|
||||||
|| (ignoreCase && dictionary.isValidWord(lowerCasedWord))) {
|
if (dictionary.isValidWord(word)
|
||||||
return true;
|
|| (ignoreCase && dictionary.isValidWord(lowerCasedWord))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -584,18 +646,20 @@ public class DictionaryFacilitator {
|
||||||
return Dictionary.NOT_A_PROBABILITY;
|
return Dictionary.NOT_A_PROBABILITY;
|
||||||
}
|
}
|
||||||
int maxFreq = Dictionary.NOT_A_PROBABILITY;
|
int maxFreq = Dictionary.NOT_A_PROBABILITY;
|
||||||
final DictionaryGroup dictionaryGroup = mDictionaryGroup;
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
|
for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) {
|
||||||
if (dictionary == null) continue;
|
final Dictionary dictionary = dictionaryGroup.getDict(dictType);
|
||||||
final int tempFreq;
|
if (dictionary == null) continue;
|
||||||
if (isGettingMaxFrequencyOfExactMatches) {
|
final int tempFreq;
|
||||||
tempFreq = dictionary.getMaxFrequencyOfExactMatches(word);
|
if (isGettingMaxFrequencyOfExactMatches) {
|
||||||
} else {
|
tempFreq = dictionary.getMaxFrequencyOfExactMatches(word);
|
||||||
tempFreq = dictionary.getFrequency(word);
|
} else {
|
||||||
}
|
tempFreq = dictionary.getFrequency(word);
|
||||||
if (tempFreq >= maxFreq) {
|
}
|
||||||
maxFreq = tempFreq;
|
if (tempFreq >= maxFreq) {
|
||||||
|
maxFreq = tempFreq;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return maxFreq;
|
return maxFreq;
|
||||||
|
@ -610,9 +674,12 @@ public class DictionaryFacilitator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void clearSubDictionary(final String dictName) {
|
private void clearSubDictionary(final String dictName) {
|
||||||
final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName);
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
if (dictionary != null) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
dictionary.clear();
|
final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(dictName);
|
||||||
|
if (dictionary != null) {
|
||||||
|
dictionary.clear();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -641,8 +708,10 @@ public class DictionaryFacilitator {
|
||||||
|
|
||||||
public void addPhraseToContextualDictionary(final String[] phrase, final int probability,
|
public void addPhraseToContextualDictionary(final String[] phrase, final int probability,
|
||||||
final int bigramProbabilityForWords, final int bigramProbabilityForPhrases) {
|
final int bigramProbabilityForWords, final int bigramProbabilityForPhrases) {
|
||||||
|
// TODO: we're inserting the phrase into the dictionary for the active language. Rethink
|
||||||
|
// this a bit from a theoretical point of view.
|
||||||
final ExpandableBinaryDictionary contextualDict =
|
final ExpandableBinaryDictionary contextualDict =
|
||||||
mDictionaryGroup.getSubDict(Dictionary.TYPE_CONTEXTUAL);
|
getDictionaryGroupForActiveLanguage().getSubDict(Dictionary.TYPE_CONTEXTUAL);
|
||||||
if (contextualDict == null) {
|
if (contextualDict == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -675,22 +744,27 @@ public class DictionaryFacilitator {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dumpDictionaryForDebug(final String dictName) {
|
public void dumpDictionaryForDebug(final String dictName) {
|
||||||
final ExpandableBinaryDictionary dictToDump = mDictionaryGroup.getSubDict(dictName);
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
if (dictToDump == null) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
Log.e(TAG, "Cannot dump " + dictName + ". "
|
final ExpandableBinaryDictionary dictToDump = dictionaryGroup.getSubDict(dictName);
|
||||||
+ "The dictionary is not being used for suggestion or cannot be dumped.");
|
if (dictToDump == null) {
|
||||||
return;
|
Log.e(TAG, "Cannot dump " + dictName + ". "
|
||||||
|
+ "The dictionary is not being used for suggestion or cannot be dumped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dictToDump.dumpAllWordsForDebug();
|
||||||
}
|
}
|
||||||
dictToDump.dumpAllWordsForDebug();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ArrayList<Pair<String, DictionaryStats>> getStatsOfEnabledSubDicts() {
|
public ArrayList<Pair<String, DictionaryStats>> getStatsOfEnabledSubDicts() {
|
||||||
final ArrayList<Pair<String, DictionaryStats>> statsOfEnabledSubDicts = new ArrayList<>();
|
final ArrayList<Pair<String, DictionaryStats>> statsOfEnabledSubDicts = new ArrayList<>();
|
||||||
final DictionaryGroup dictionaryGroup = mDictionaryGroup;
|
final DictionaryGroup[] dictionaryGroups = mDictionaryGroups;
|
||||||
for (final String dictType : SUB_DICT_TYPES) {
|
for (final DictionaryGroup dictionaryGroup : dictionaryGroups) {
|
||||||
final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(dictType);
|
for (final String dictType : SUB_DICT_TYPES) {
|
||||||
if (dictionary == null) continue;
|
final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(dictType);
|
||||||
statsOfEnabledSubDicts.add(new Pair<>(dictType, dictionary.getDictionaryStats()));
|
if (dictionary == null) continue;
|
||||||
|
statsOfEnabledSubDicts.add(new Pair<>(dictType, dictionary.getDictionaryStats()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return statsOfEnabledSubDicts;
|
return statsOfEnabledSubDicts;
|
||||||
}
|
}
|
||||||
|
|
|
@ -84,7 +84,7 @@ public class DictionaryFacilitatorLruCache {
|
||||||
private void waitForLoadingMainDictionary(final DictionaryFacilitator dictionaryFacilitator) {
|
private void waitForLoadingMainDictionary(final DictionaryFacilitator dictionaryFacilitator) {
|
||||||
for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) {
|
for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) {
|
||||||
try {
|
try {
|
||||||
dictionaryFacilitator.waitForLoadingMainDictionary(
|
dictionaryFacilitator.waitForLoadingMainDictionaries(
|
||||||
WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
|
WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS, TimeUnit.MILLISECONDS);
|
||||||
return;
|
return;
|
||||||
} catch (final InterruptedException e) {
|
} catch (final InterruptedException e) {
|
||||||
|
|
|
@ -156,23 +156,25 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void asyncExecuteTaskWithWriteLock(final Runnable task) {
|
private void asyncExecuteTaskWithWriteLock(final Runnable task) {
|
||||||
asyncExecuteTaskWithLock(mLock.writeLock(), task);
|
asyncExecuteTaskWithLock(mLock.writeLock(), mDictName /* executorName */, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void asyncExecuteTaskWithLock(final Lock lock, final Runnable task) {
|
private void asyncExecuteTaskWithLock(final Lock lock, final String executorName,
|
||||||
asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, task);
|
final Runnable task) {
|
||||||
|
asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, executorName, task);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void asyncPreCheckAndExecuteTaskWithWriteLock(
|
private void asyncPreCheckAndExecuteTaskWithWriteLock(
|
||||||
final Callable<Boolean> preCheckTask, final Runnable task) {
|
final Callable<Boolean> preCheckTask, final Runnable task) {
|
||||||
asyncPreCheckAndExecuteTaskWithLock(mLock.writeLock(), preCheckTask, task);
|
asyncPreCheckAndExecuteTaskWithLock(mLock.writeLock(), preCheckTask,
|
||||||
|
mDictName /* executorName */, task);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Execute task with lock when the result of preCheckTask is true or preCheckTask is null.
|
// Execute task with lock when the result of preCheckTask is true or preCheckTask is null.
|
||||||
private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
|
private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock,
|
||||||
final Callable<Boolean> preCheckTask, final Runnable task) {
|
final Callable<Boolean> preCheckTask, final String executorName, final Runnable task) {
|
||||||
ExecutorUtils.getExecutor(mDictName).execute(new Runnable() {
|
ExecutorUtils.getExecutor(executorName).execute(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
if (preCheckTask != null) {
|
if (preCheckTask != null) {
|
||||||
|
@ -676,10 +678,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
|
||||||
|
|
||||||
public void dumpAllWordsForDebug() {
|
public void dumpAllWordsForDebug() {
|
||||||
reloadDictionaryIfRequired();
|
reloadDictionaryIfRequired();
|
||||||
asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() {
|
asyncExecuteTaskWithLock(mLock.readLock(), "dumpAllWordsForDebug", new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
Log.d(TAG, "Dump dictionary: " + mDictName);
|
Log.d(TAG, "Dump dictionary: " + mDictName + " for " + mLocale);
|
||||||
try {
|
try {
|
||||||
final DictionaryHeader header = mBinaryDictionary.getHeader();
|
final DictionaryHeader header = mBinaryDictionary.getHeader();
|
||||||
Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion());
|
Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion());
|
||||||
|
|
|
@ -998,7 +998,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
|
||||||
mHandler.cancelUpdateSuggestionStrip();
|
mHandler.cancelUpdateSuggestionStrip();
|
||||||
|
|
||||||
mainKeyboardView.setMainDictionaryAvailability(
|
mainKeyboardView.setMainDictionaryAvailability(
|
||||||
mDictionaryFacilitator.hasInitializedMainDictionary());
|
mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary());
|
||||||
mainKeyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn,
|
mainKeyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn,
|
||||||
currentSettingsValues.mKeyPreviewPopupDismissDelay);
|
currentSettingsValues.mKeyPreviewPopupDismissDelay);
|
||||||
mainKeyboardView.setSlidingKeyInputPreviewEnabled(
|
mainKeyboardView.setSlidingKeyInputPreviewEnabled(
|
||||||
|
|
|
@ -88,17 +88,17 @@ public class PersonalizationHelperForDictionaryFacilitator {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flush personalization dictionaries to dictionary files. Close dictionaries after writing
|
* Flush personalization dictionaries to dictionary files. Close dictionaries after writing
|
||||||
* files except the dictionary that is used for generating suggestions.
|
* files except the dictionaries that is used for generating suggestions.
|
||||||
*
|
*
|
||||||
* @param personalizationDictUsedForSuggestion the personalization dictionary used for
|
* @param personalizationDictsUsedForSuggestion the personalization dictionaries used for
|
||||||
* generating suggestions that won't be closed.
|
* generating suggestions that won't be closed.
|
||||||
*/
|
*/
|
||||||
public void flushPersonalizationDictionariesToUpdate(
|
public void flushPersonalizationDictionariesToUpdate(
|
||||||
final ExpandableBinaryDictionary personalizationDictUsedForSuggestion) {
|
final HashSet<ExpandableBinaryDictionary> personalizationDictsUsedForSuggestion) {
|
||||||
for (final ExpandableBinaryDictionary personalizationDict :
|
for (final ExpandableBinaryDictionary personalizationDict :
|
||||||
mPersonalizationDictsToUpdate.values()) {
|
mPersonalizationDictsToUpdate.values()) {
|
||||||
personalizationDict.asyncFlushBinaryDictionary();
|
personalizationDict.asyncFlushBinaryDictionary();
|
||||||
if (personalizationDict != personalizationDictUsedForSuggestion) {
|
if (!personalizationDictsUsedForSuggestion.contains(personalizationDict)) {
|
||||||
// Close if the dictionary is not being used for suggestion.
|
// Close if the dictionary is not being used for suggestion.
|
||||||
personalizationDict.close();
|
personalizationDict.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -157,7 +157,7 @@ public final class Suggest {
|
||||||
if (!isCorrectionEnabled || !allowsToBeAutoCorrected || resultsArePredictions
|
if (!isCorrectionEnabled || !allowsToBeAutoCorrected || resultsArePredictions
|
||||||
|| suggestionResults.isEmpty() || wordComposer.hasDigits()
|
|| suggestionResults.isEmpty() || wordComposer.hasDigits()
|
||||||
|| wordComposer.isMostlyCaps() || wordComposer.isResumed()
|
|| wordComposer.isMostlyCaps() || wordComposer.isResumed()
|
||||||
|| !mDictionaryFacilitator.hasInitializedMainDictionary()
|
|| !mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary()
|
||||||
|| suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) {
|
|| suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) {
|
||||||
// If we don't have a main dictionary, we never want to auto-correct. The reason for
|
// 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
|
// this is, the user may have a contact whose name happens to match a valid word in
|
||||||
|
|
|
@ -185,7 +185,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService
|
||||||
try {
|
try {
|
||||||
final DictionaryFacilitator dictionaryFacilitator =
|
final DictionaryFacilitator dictionaryFacilitator =
|
||||||
mDictionaryFacilitatorCache.get(locale);
|
mDictionaryFacilitatorCache.get(locale);
|
||||||
return dictionaryFacilitator.hasInitializedMainDictionary();
|
return dictionaryFacilitator.hasAtLeastOneInitializedMainDictionary();
|
||||||
} finally {
|
} finally {
|
||||||
mSemaphore.release();
|
mSemaphore.release();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue