From 8cd53266229895a3e0c6618e3765d57fc5d0b392 Mon Sep 17 00:00:00 2001 From: Jean Chalard Date: Thu, 11 Sep 2014 18:51:31 +0900 Subject: [PATCH] [ML7] Have multiple DictionaryGroup instances in facilitator This is the central change of multilingual input. Bug: 11230254 Change-Id: Id8b68fb101e837e8cf182ab4bc1e55e4da5cc49d --- .../latin/DictionaryFacilitator.java | 264 +++++++++++------- .../latin/DictionaryFacilitatorLruCache.java | 2 +- .../latin/ExpandableBinaryDictionary.java | 18 +- .../android/inputmethod/latin/LatinIME.java | 2 +- ...izationHelperForDictionaryFacilitator.java | 8 +- .../android/inputmethod/latin/Suggest.java | 2 +- .../AndroidSpellCheckerService.java | 2 +- 7 files changed, 187 insertions(+), 111 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index c20546607..eced45ea5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -61,9 +61,9 @@ public class DictionaryFacilitator { // dictionary. 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 volatile CountDownLatch mLatchForWaitingLoadingMainDictionary = new CountDownLatch(0); + private volatile CountDownLatch mLatchForWaitingLoadingMainDictionaries = new CountDownLatch(0); // To synchronize assigning mDictionaryGroup to ensure closing dictionaries. private final Object mLock = new Object(); private final DistracterFilter mDistracterFilter; @@ -193,8 +193,9 @@ public class DictionaryFacilitator { mPersonalizationHelper.setIsMonolingualUser(isMonolingualUser); } + // TODO: remove this, replace with version returning multiple locales public Locale getLocale() { - return mDictionaryGroup.mLocale; + return mDictionaryGroups[0].mLocale; } private static ExpandableBinaryDictionary getSubDict(final String dictType, @@ -226,6 +227,21 @@ public class DictionaryFacilitator { 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, final Locale newLocaleToUse, final boolean useContactsDict, final boolean usePersonalizedDicts, @@ -252,7 +268,7 @@ public class DictionaryFacilitator { final ArrayList dictsForLocale = new ArrayList<>(); existingDictsToCleanup.put(newLocale, dictsForLocale); final DictionaryGroup currentDictionaryGroupForLocale = - newLocale.equals(mDictionaryGroup.mLocale) ? mDictionaryGroup : null; + findDictionaryGroupWithLocale(mDictionaryGroups, newLocale); if (null == currentDictionaryGroupForLocale) { continue; } @@ -266,10 +282,11 @@ public class DictionaryFacilitator { } } - final HashMap newDictionaryGroups = new HashMap<>(); - for (final Locale newLocale : newLocales) { + final DictionaryGroup[] newDictionaryGroups = new DictionaryGroup[newLocales.length]; + for (int i = 0; i < newLocales.length; ++i) { + final Locale newLocale = newLocales[i]; final DictionaryGroup dictionaryGroupForLocale = - newLocale.equals(mDictionaryGroup.mLocale) ? mDictionaryGroup : null; + findDictionaryGroupWithLocale(mDictionaryGroups, newLocale); final ArrayList dictsToCleanupForLocale = existingDictsToCleanup.get(newLocale); final boolean noExistingDictsForThisLocale = (null == dictionaryGroupForLocale); @@ -297,30 +314,29 @@ public class DictionaryFacilitator { } subDicts.put(subDictType, subDict); } - newDictionaryGroups.put(newLocale, new DictionaryGroup(newLocale, mainDict, subDicts)); + newDictionaryGroups[i] = new DictionaryGroup(newLocale, mainDict, subDicts); } // Replace Dictionaries. - // TODO: use multiple locales. - final DictionaryGroup newDictionaryGroup = newDictionaryGroups.get(newLocaleToUse); - final DictionaryGroup oldDictionaryGroup; + final DictionaryGroup[] oldDictionaryGroups; synchronized (mLock) { - oldDictionaryGroup = mDictionaryGroup; - mDictionaryGroup = newDictionaryGroup; + oldDictionaryGroups = mDictionaryGroups; + mDictionaryGroups = newDictionaryGroups; mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context); - if (null == newDictionaryGroup.getDict(Dictionary.TYPE_MAIN)) { + if (hasAtLeastOneUninitializedMainDictionary()) { asyncReloadUninitializedMainDictionaries(context, newLocales, listener); } } if (listener != null) { - listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary()); + listener.onUpdateMainDictionaryAvailability(hasAtLeastOneInitializedMainDictionary()); } // Clean up old dictionaries. for (final Locale localeToCleanUp : existingDictsToCleanup.keySet()) { final ArrayList dictTypesToCleanUp = existingDictsToCleanup.get(localeToCleanUp); - final DictionaryGroup dictionarySetToCleanup = oldDictionaryGroup; + final DictionaryGroup dictionarySetToCleanup = + findDictionaryGroupWithLocale(oldDictionaryGroups, localeToCleanUp); for (final String dictType : dictTypesToCleanUp) { dictionarySetToCleanup.closeDict(dictType); } @@ -330,12 +346,18 @@ public class DictionaryFacilitator { private void asyncReloadUninitializedMainDictionaries(final Context context, final Locale[] locales, final DictionaryInitializationListener listener) { final CountDownLatch latchForWaitingLoadingMainDictionary = new CountDownLatch(1); - mLatchForWaitingLoadingMainDictionary = latchForWaitingLoadingMainDictionary; + mLatchForWaitingLoadingMainDictionaries = latchForWaitingLoadingMainDictionary; ExecutorUtils.getExecutor("InitializeBinaryDictionary").execute(new Runnable() { @Override public void run() { 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 = DictionaryFactory.createMainDictionaryFromManager(context, locale); synchronized (mLock) { @@ -348,7 +370,8 @@ public class DictionaryFacilitator { } } if (listener != null) { - listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary()); + listener.onUpdateMainDictionaryAvailability( + hasAtLeastOneInitializedMainDictionary()); } latchForWaitingLoadingMainDictionary.countDown(); } @@ -381,17 +404,20 @@ public class DictionaryFacilitator { subDicts.put(dictType, dict); } } - mDictionaryGroup = new DictionaryGroup(locale, mainDictionary, subDicts); + mDictionaryGroups = new DictionaryGroup[] { + new DictionaryGroup(locale, mainDictionary, subDicts) }; } public void closeDictionaries() { - final DictionaryGroup dictionaryGroup; + final DictionaryGroup[] dictionaryGroups; synchronized (mLock) { - dictionaryGroup = mDictionaryGroup; - mDictionaryGroup = new DictionaryGroup(); + dictionaryGroups = mDictionaryGroups; + mDictionaryGroups = new DictionaryGroup[] { new DictionaryGroup() }; } - for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { - dictionaryGroup.closeDict(dictType); + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { + dictionaryGroup.closeDict(dictType); + } } mDistracterFilter.close(); if (mPersonalizationHelper != null) { @@ -401,40 +427,71 @@ public class DictionaryFacilitator { @UsedForTesting 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 - // of this method. - public boolean hasInitializedMainDictionary() { - final Dictionary mainDict = mDictionaryGroup.getDict(Dictionary.TYPE_MAIN); - return mainDict != null && mainDict.isInitialized(); + // The main dictionaries are loaded asynchronously. Don't cache the return value + // of these methods. + public boolean hasAtLeastOneInitializedMainDictionary() { + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + final Dictionary mainDict = dictionaryGroup.getDict(Dictionary.TYPE_MAIN); + if (mainDict != null && mainDict.isInitialized()) { + return true; + } + } + 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() { - 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() { - final ExpandableBinaryDictionary personalizationDictUsedForSuggestion = - mDictionaryGroup.getSubDict(Dictionary.TYPE_PERSONALIZATION); + final HashSet personalizationDictsUsedForSuggestion = + new HashSet<>(); + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + final ExpandableBinaryDictionary personalizationDictUsedForSuggestion = + dictionaryGroup.getSubDict(Dictionary.TYPE_PERSONALIZATION); + personalizationDictsUsedForSuggestion.add(personalizationDictUsedForSuggestion); + } mPersonalizationHelper.flushPersonalizationDictionariesToUpdate( - personalizationDictUsedForSuggestion); + personalizationDictsUsedForSuggestion); mDistracterFilter.close(); } - public void waitForLoadingMainDictionary(final long timeout, final TimeUnit unit) + public void waitForLoadingMainDictionaries(final long timeout, final TimeUnit unit) throws InterruptedException { - mLatchForWaitingLoadingMainDictionary.await(timeout, unit); + mLatchForWaitingLoadingMainDictionaries.await(timeout, unit); } @UsedForTesting public void waitForLoadingDictionariesForTesting(final long timeout, final TimeUnit unit) throws InterruptedException { - waitForLoadingMainDictionary(timeout, unit); - final Map dictMap = mDictionaryGroup.mSubDictMap; - for (final ExpandableBinaryDictionary dict : dictMap.values()) { - dict.waitAllTasksForTests(); + waitForLoadingMainDictionaries(timeout, unit); + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + 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, final PrevWordsInfo prevWordsInfo, final int timeStampInSeconds, final boolean blockPotentiallyOffensive) { - final DictionaryGroup dictionaryGroup = mDictionaryGroup; + final DictionaryGroup dictionaryGroup = getDictionaryGroupForActiveLanguage(); final String[] words = suggestion.split(Constants.WORD_SEPARATOR); PrevWordsInfo prevWordsInfoForCurrentWord = prevWordsInfo; for (int i = 0; i < words.length; i++) { @@ -520,7 +577,8 @@ public class DictionaryFacilitator { } private void removeWord(final String dictName, final String word) { - final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName); + final ExpandableBinaryDictionary dictionary = + getDictionaryGroupForActiveLanguage().getSubDict(dictName); if (dictionary != null) { dictionary.removeUnigramEntryDynamically(word); } @@ -536,20 +594,22 @@ public class DictionaryFacilitator { public SuggestionResults getSuggestionResults(final WordComposer composer, final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId) { - final DictionaryGroup dictionaryGroup = mDictionaryGroup; + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; final SuggestionResults suggestionResults = new SuggestionResults(SuggestedWords.MAX_SUGGESTIONS); final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT }; - for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { - final Dictionary dictionary = dictionaryGroup.getDict(dictType); - if (null == dictionary) continue; - final ArrayList dictionarySuggestions = - dictionary.getSuggestions(composer, prevWordsInfo, proximityInfo, - settingsValuesForSuggestion, sessionId, languageWeight); - if (null == dictionarySuggestions) continue; - suggestionResults.addAll(dictionarySuggestions); - if (null != suggestionResults.mRawSuggestions) { - suggestionResults.mRawSuggestions.addAll(dictionarySuggestions); + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { + final Dictionary dictionary = dictionaryGroup.getDict(dictType); + if (null == dictionary) continue; + final ArrayList dictionarySuggestions = + dictionary.getSuggestions(composer, prevWordsInfo, proximityInfo, + settingsValuesForSuggestion, sessionId, languageWeight); + if (null == dictionarySuggestions) continue; + suggestionResults.addAll(dictionarySuggestions); + if (null != suggestionResults.mRawSuggestions) { + suggestionResults.mRawSuggestions.addAll(dictionarySuggestions); + } } } return suggestionResults; @@ -559,20 +619,22 @@ public class DictionaryFacilitator { if (TextUtils.isEmpty(word)) { return false; } - final DictionaryGroup dictionaryGroup = mDictionaryGroup; - if (dictionaryGroup.mLocale == null) { - return false; - } - final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale); - for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { - final Dictionary dictionary = dictionaryGroup.getDict(dictType); - // Ideally the passed map would come out of a {@link java.util.concurrent.Future} and - // would be immutable once it's finished initializing, but concretely a null test is - // probably good enough for the time being. - if (null == dictionary) continue; - if (dictionary.isValidWord(word) - || (ignoreCase && dictionary.isValidWord(lowerCasedWord))) { - return true; + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + if (dictionaryGroup.mLocale == null) { + continue; + } + final String lowerCasedWord = word.toLowerCase(dictionaryGroup.mLocale); + for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { + final Dictionary dictionary = dictionaryGroup.getDict(dictType); + // Ideally the passed map would come out of a {@link java.util.concurrent.Future} and + // would be immutable once it's finished initializing, but concretely a null test is + // probably good enough for the time being. + if (null == dictionary) continue; + if (dictionary.isValidWord(word) + || (ignoreCase && dictionary.isValidWord(lowerCasedWord))) { + return true; + } } } return false; @@ -584,18 +646,20 @@ public class DictionaryFacilitator { return Dictionary.NOT_A_PROBABILITY; } int maxFreq = Dictionary.NOT_A_PROBABILITY; - final DictionaryGroup dictionaryGroup = mDictionaryGroup; - for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { - final Dictionary dictionary = dictionaryGroup.getDict(dictType); - if (dictionary == null) continue; - final int tempFreq; - if (isGettingMaxFrequencyOfExactMatches) { - tempFreq = dictionary.getMaxFrequencyOfExactMatches(word); - } else { - tempFreq = dictionary.getFrequency(word); - } - if (tempFreq >= maxFreq) { - maxFreq = tempFreq; + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTIONS) { + final Dictionary dictionary = dictionaryGroup.getDict(dictType); + if (dictionary == null) continue; + final int tempFreq; + if (isGettingMaxFrequencyOfExactMatches) { + tempFreq = dictionary.getMaxFrequencyOfExactMatches(word); + } else { + tempFreq = dictionary.getFrequency(word); + } + if (tempFreq >= maxFreq) { + maxFreq = tempFreq; + } } } return maxFreq; @@ -610,9 +674,12 @@ public class DictionaryFacilitator { } private void clearSubDictionary(final String dictName) { - final ExpandableBinaryDictionary dictionary = mDictionaryGroup.getSubDict(dictName); - if (dictionary != null) { - dictionary.clear(); + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + 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, 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 = - mDictionaryGroup.getSubDict(Dictionary.TYPE_CONTEXTUAL); + getDictionaryGroupForActiveLanguage().getSubDict(Dictionary.TYPE_CONTEXTUAL); if (contextualDict == null) { return; } @@ -675,22 +744,27 @@ public class DictionaryFacilitator { } public void dumpDictionaryForDebug(final String dictName) { - final ExpandableBinaryDictionary dictToDump = mDictionaryGroup.getSubDict(dictName); - if (dictToDump == null) { - Log.e(TAG, "Cannot dump " + dictName + ". " - + "The dictionary is not being used for suggestion or cannot be dumped."); - return; + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + final ExpandableBinaryDictionary dictToDump = dictionaryGroup.getSubDict(dictName); + if (dictToDump == null) { + Log.e(TAG, "Cannot dump " + dictName + ". " + + "The dictionary is not being used for suggestion or cannot be dumped."); + return; + } + dictToDump.dumpAllWordsForDebug(); } - dictToDump.dumpAllWordsForDebug(); } public ArrayList> getStatsOfEnabledSubDicts() { final ArrayList> statsOfEnabledSubDicts = new ArrayList<>(); - final DictionaryGroup dictionaryGroup = mDictionaryGroup; - for (final String dictType : SUB_DICT_TYPES) { - final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(dictType); - if (dictionary == null) continue; - statsOfEnabledSubDicts.add(new Pair<>(dictType, dictionary.getDictionaryStats())); + final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; + for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { + for (final String dictType : SUB_DICT_TYPES) { + final ExpandableBinaryDictionary dictionary = dictionaryGroup.getSubDict(dictType); + if (dictionary == null) continue; + statsOfEnabledSubDicts.add(new Pair<>(dictType, dictionary.getDictionaryStats())); + } } return statsOfEnabledSubDicts; } diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java index fa0265d86..ff4a6bde1 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java @@ -84,7 +84,7 @@ public class DictionaryFacilitatorLruCache { private void waitForLoadingMainDictionary(final DictionaryFacilitator dictionaryFacilitator) { for (int i = 0; i < MAX_RETRY_COUNT_FOR_WAITING_FOR_LOADING_DICT; i++) { try { - dictionaryFacilitator.waitForLoadingMainDictionary( + dictionaryFacilitator.waitForLoadingMainDictionaries( WAIT_FOR_LOADING_MAIN_DICT_IN_MILLISECONDS, TimeUnit.MILLISECONDS); return; } catch (final InterruptedException e) { diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index a1dd67f27..671ba6714 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -156,23 +156,25 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } 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) { - asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, task); + private void asyncExecuteTaskWithLock(final Lock lock, final String executorName, + final Runnable task) { + asyncPreCheckAndExecuteTaskWithLock(lock, null /* preCheckTask */, executorName, task); } private void asyncPreCheckAndExecuteTaskWithWriteLock( final Callable 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. private void asyncPreCheckAndExecuteTaskWithLock(final Lock lock, - final Callable preCheckTask, final Runnable task) { - ExecutorUtils.getExecutor(mDictName).execute(new Runnable() { + final Callable preCheckTask, final String executorName, final Runnable task) { + ExecutorUtils.getExecutor(executorName).execute(new Runnable() { @Override public void run() { if (preCheckTask != null) { @@ -676,10 +678,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { public void dumpAllWordsForDebug() { reloadDictionaryIfRequired(); - asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() { + asyncExecuteTaskWithLock(mLock.readLock(), "dumpAllWordsForDebug", new Runnable() { @Override public void run() { - Log.d(TAG, "Dump dictionary: " + mDictName); + Log.d(TAG, "Dump dictionary: " + mDictName + " for " + mLocale); try { final DictionaryHeader header = mBinaryDictionary.getHeader(); Log.d(TAG, "Format version: " + mBinaryDictionary.getFormatVersion()); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index aac6276bc..66396d08c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -998,7 +998,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mHandler.cancelUpdateSuggestionStrip(); mainKeyboardView.setMainDictionaryAvailability( - mDictionaryFacilitator.hasInitializedMainDictionary()); + mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary()); mainKeyboardView.setKeyPreviewPopupEnabled(currentSettingsValues.mKeyPreviewPopupOn, currentSettingsValues.mKeyPreviewPopupDismissDelay); mainKeyboardView.setSlidingKeyInputPreviewEnabled( diff --git a/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java index 43cebdfa4..396d062f8 100644 --- a/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/PersonalizationHelperForDictionaryFacilitator.java @@ -88,17 +88,17 @@ public class PersonalizationHelperForDictionaryFacilitator { /** * 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. */ public void flushPersonalizationDictionariesToUpdate( - final ExpandableBinaryDictionary personalizationDictUsedForSuggestion) { + final HashSet personalizationDictsUsedForSuggestion) { for (final ExpandableBinaryDictionary personalizationDict : mPersonalizationDictsToUpdate.values()) { personalizationDict.asyncFlushBinaryDictionary(); - if (personalizationDict != personalizationDictUsedForSuggestion) { + if (!personalizationDictsUsedForSuggestion.contains(personalizationDict)) { // Close if the dictionary is not being used for suggestion. personalizationDict.close(); } diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 9e4aa40a2..9bf017578 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -157,7 +157,7 @@ public final class Suggest { if (!isCorrectionEnabled || !allowsToBeAutoCorrected || resultsArePredictions || suggestionResults.isEmpty() || wordComposer.hasDigits() || wordComposer.isMostlyCaps() || wordComposer.isResumed() - || !mDictionaryFacilitator.hasInitializedMainDictionary() + || !mDictionaryFacilitator.hasAtLeastOneInitializedMainDictionary() || suggestionResults.first().isKindOf(SuggestedWordInfo.KIND_SHORTCUT)) { // 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 diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 49b34d391..352391611 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -185,7 +185,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService try { final DictionaryFacilitator dictionaryFacilitator = mDictionaryFacilitatorCache.get(locale); - return dictionaryFacilitator.hasInitializedMainDictionary(); + return dictionaryFacilitator.hasAtLeastOneInitializedMainDictionary(); } finally { mSemaphore.release(); }