Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit adfb2627 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi
Browse files

Remove logic related to dictionary loading from LatinIME.

Make mSuggest final and give DictionaryFacilitator the
responsibility to manage dictionary loading state.
This can simplify the logic to decide how to deal with
additional dictionaries when loading settings or language
switching.

Bug: 13273534
Change-Id: I9f3d328272f25addfa186fbeedaaf8417455ba99
parent 37b9562f
Loading
Loading
Loading
Loading
+303 −326

File changed.

Preview size limit exceeded, changes collapsed.

+51 −76
Original line number Diff line number Diff line
@@ -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);
                mInputLogic.mSuggest.mDictionaryFacilitator;
        final SettingsValues settingsValues = mSettings.getCurrent();
        dictionaryFacilitator.resetDictionaries(this /* context */, locale,
                settingsValues.mUseContactsDict, settingsValues.mUsePersonalizedDicts,
                false /* forceReloadMainDictionary */, this);
        if (settingsValues.mCorrectionEnabled) {
            newSuggest.setAutoCorrectionThreshold(settingsValues.mAutoCorrectionThreshold);
            mInputLogic.mSuggest.setAutoCorrectionThreshold(
                    settingsValues.mAutoCorrectionThreshold);
        }
        replaceSuggest(newSuggest);
    }

    /**
     * Reset suggest by loading the main dictionary of the current locale.
     */
    /* 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));
    }

    private void replaceSuggest(final Suggest newSuggest) {
        if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
            ResearchLogger.getInstance().initDictionary(newSuggest.mDictionaryFacilitator);
        }
        mInputLogic.replaceSuggest(newSuggest);
        refreshPersonalizationDictionarySession();
                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);
    }
+24 −63
Original line number Diff line number Diff line
@@ -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;
    }

    // Creates instance with new dictionary facilitator.
    public Suggest(final Suggest oldSuggst,
            final DictionaryFacilitatorForSuggest dictionaryFacilitator) {
        mLocale = oldSuggst.mLocale;
        mAutoCorrectionThreshold = oldSuggst.mAutoCorrectionThreshold;
        mDictionaryFacilitator = dictionaryFacilitator;
    public Locale getLocale() {
        return mDictionaryFacilitator.getLocale();
    }

    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();
    }
}
+10 −29

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -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,
Loading