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

Commit 1ab6bfdc authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi
Browse files

Simplify DictionaryFacilitatorForSuggest.

Bug: 13755213
Change-Id: I9663d1d60fccd8deb1a22683fb06fe64dee06b45
parent 9ed7e475
Loading
Loading
Loading
Loading
+69 −105
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.ProximityInfo;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
import com.android.inputmethod.latin.personalization.DecayingExpandableBinaryDictionaryBase;
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
import com.android.inputmethod.latin.utils.CollectionUtils;
@@ -33,9 +33,11 @@ import com.android.inputmethod.latin.utils.SuggestionResults;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -54,7 +56,7 @@ public class DictionaryFacilitatorForSuggest {
    // To synchronize assigning mDictionaries to ensure closing dictionaries.
    private Object mLock = new Object();

    private static final String[] dictTypesOrderedToGetSuggestion =
    private static final String[] DICT_TYPES_ORDERED_TO_GET_SUGGESTION =
            new String[] {
                Dictionary.TYPE_MAIN,
                Dictionary.TYPE_USER_HISTORY,
@@ -63,6 +65,10 @@ public class DictionaryFacilitatorForSuggest {
                Dictionary.TYPE_CONTACTS
            };

    private static final String[] SUB_DICT_TYPES =
            Arrays.copyOfRange(DICT_TYPES_ORDERED_TO_GET_SUGGESTION, 1 /* start */,
                    DICT_TYPES_ORDERED_TO_GET_SUGGESTION.length);

    /**
     * Class contains dictionaries for a locale.
     */
@@ -78,17 +84,13 @@ public class DictionaryFacilitatorForSuggest {
        }

        public Dictionaries(final Locale locale, final Dictionary mainDict,
            final ExpandableBinaryDictionary contactsDict,
            final ExpandableBinaryDictionary userDict,
            final ExpandableBinaryDictionary userHistoryDict,
            final ExpandableBinaryDictionary personalizationDict) {
                final Map<String, ExpandableBinaryDictionary> subDicts) {
            mLocale = locale;
            // Main dictionary can be asynchronously loaded.
            setMainDict(mainDict);
            setSubDict(Dictionary.TYPE_CONTACTS, contactsDict);
            setSubDict(Dictionary.TYPE_USER, userDict);
            setSubDict(Dictionary.TYPE_USER_HISTORY, userHistoryDict);
            setSubDict(Dictionary.TYPE_PERSONALIZATION, personalizationDict);
            for (final Map.Entry<String, ExpandableBinaryDictionary> entry : subDicts.entrySet()) {
                setSubDict(entry.getKey(), entry.getValue());
            }
        }

        private void setSubDict(final String dictType, final ExpandableBinaryDictionary dict) {
@@ -142,6 +144,21 @@ public class DictionaryFacilitatorForSuggest {
        return mDictionaries.mLocale;
    }

    private static ExpandableBinaryDictionary getSubDict(final String dictType,
            final Context context, final Locale locale, final File dictFile) {
        if (Dictionary.TYPE_CONTACTS.equals(dictType)) {
            return new ContactsBinaryDictionary(context, locale, dictFile);
        } else if (Dictionary.TYPE_USER.equals(dictType)) {
            return new UserBinaryDictionary(context, locale, dictFile);
        } else if (Dictionary.TYPE_USER_HISTORY.equals(dictType)) {
            return PersonalizationHelper.getUserHistoryDictionary(context, locale);
        } else if (Dictionary.TYPE_PERSONALIZATION.equals(dictType)) {
            return PersonalizationHelper.getPersonalizationDictionary(context, locale);
        } else {
            return null;
        }
    }

    public void resetDictionaries(final Context context, final Locale newLocale,
            final boolean useContactsDict, final boolean usePersonalizedDicts,
            final boolean forceReloadMainDictionary,
@@ -149,11 +166,15 @@ public class DictionaryFacilitatorForSuggest {
        final boolean localeHasBeenChanged = !newLocale.equals(mDictionaries.mLocale);
        // We always try to have the main dictionary. Other dictionaries can be unused.
        final boolean reloadMainDictionary = localeHasBeenChanged || forceReloadMainDictionary;
        final boolean closeContactsDictionary = localeHasBeenChanged || !useContactsDict;
        final boolean closeUserDictionary = localeHasBeenChanged;
        final boolean closeUserHistoryDictionary = localeHasBeenChanged || !usePersonalizedDicts;
        final boolean closePersonalizationDictionary =
                localeHasBeenChanged || !usePersonalizedDicts;
        final Set<String> subDictTypesToUse = CollectionUtils.newHashSet();
        if (useContactsDict) {
            subDictTypesToUse.add(Dictionary.TYPE_USER);
        }
        subDictTypesToUse.add(Dictionary.TYPE_USER);
        if (usePersonalizedDicts) {
            subDictTypesToUse.add(Dictionary.TYPE_USER_HISTORY);
            subDictTypesToUse.add(Dictionary.TYPE_PERSONALIZATION);
        }

        final Dictionary newMainDict;
        if (reloadMainDictionary) {
@@ -163,50 +184,25 @@ public class DictionaryFacilitatorForSuggest {
            newMainDict = mDictionaries.getMainDict();
        }

        // Open or move contacts dictionary.
        final ExpandableBinaryDictionary newContactsDict;
        if (!closeContactsDictionary && mDictionaries.hasDict(Dictionary.TYPE_CONTACTS)) {
            newContactsDict = mDictionaries.getSubDict(Dictionary.TYPE_CONTACTS);
        } else if (useContactsDict) {
            newContactsDict = new ContactsBinaryDictionary(context, newLocale);
        } else {
            newContactsDict = null;
        final Map<String, ExpandableBinaryDictionary> subDicts = CollectionUtils.newHashMap();
        for (final String dictType : SUB_DICT_TYPES) {
            if (!subDictTypesToUse.contains(dictType)) {
                // This dictionary will not be used.
                continue;
            }

        // Open or move user dictionary.
        final ExpandableBinaryDictionary newUserDictionary;
        if (!closeUserDictionary && mDictionaries.hasDict(Dictionary.TYPE_USER)) {
            newUserDictionary = mDictionaries.getSubDict(Dictionary.TYPE_USER);
            final ExpandableBinaryDictionary dict;
            if (!localeHasBeenChanged && mDictionaries.hasDict(dictType)) {
                // Continue to use current dictionary.
                dict = mDictionaries.getSubDict(dictType);
            } else {
            newUserDictionary = new UserBinaryDictionary(context, newLocale);
            mIsUserDictEnabled = UserBinaryDictionary.isEnabled(context);
                // Start to use new dictionary.
                dict = getSubDict(dictType, context, newLocale, null /* dictFile */);
            }

        // Open or move user history dictionary.
        final ExpandableBinaryDictionary newUserHistoryDict;
        if (!closeUserHistoryDictionary && mDictionaries.hasDict(Dictionary.TYPE_USER_HISTORY)) {
            newUserHistoryDict = mDictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
        } else if (usePersonalizedDicts) {
            newUserHistoryDict = PersonalizationHelper.getUserHistoryDictionary(context, newLocale);
        } else {
            newUserHistoryDict = null;
        }

        // Open or move personalization dictionary.
        final ExpandableBinaryDictionary newPersonalizationDict;
        if (!closePersonalizationDictionary
                && mDictionaries.hasDict(Dictionary.TYPE_PERSONALIZATION)) {
            newPersonalizationDict = mDictionaries.getSubDict(Dictionary.TYPE_PERSONALIZATION);
        } else if (usePersonalizedDicts) {
            newPersonalizationDict =
                    PersonalizationHelper.getPersonalizationDictionary(context, newLocale);
        } else {
            newPersonalizationDict = null;
            subDicts.put(dictType, dict);
        }

        // Replace Dictionaries.
        final Dictionaries newDictionaries = new Dictionaries(newLocale, newMainDict,
                newContactsDict,  newUserDictionary, newUserHistoryDict, newPersonalizationDict);
        final Dictionaries newDictionaries = new Dictionaries(newLocale, newMainDict, subDicts);
        final Dictionaries oldDictionaries;
        synchronized (mLock) {
            oldDictionaries = mDictionaries;
@@ -218,22 +214,14 @@ public class DictionaryFacilitatorForSuggest {
        if (listener != null) {
            listener.onUpdateMainDictionaryAvailability(hasInitializedMainDictionary());
        }

        // Clean up old dictionaries.
        if (reloadMainDictionary) {
            oldDictionaries.closeDict(Dictionary.TYPE_MAIN);
        }
        if (closeContactsDictionary) {
            oldDictionaries.closeDict(Dictionary.TYPE_CONTACTS);
        for (final String dictType : SUB_DICT_TYPES) {
            if (localeHasBeenChanged || !subDictTypesToUse.contains(dictType)) {
                oldDictionaries.closeDict(dictType);
            }
        if (closeUserDictionary) {
            oldDictionaries.closeDict(Dictionary.TYPE_USER);
        }
        if (closeUserHistoryDictionary) {
            oldDictionaries.closeDict(Dictionary.TYPE_USER_HISTORY);
        }
        if (closePersonalizationDictionary) {
            oldDictionaries.closeDict(Dictionary.TYPE_PERSONALIZATION);
        }
        oldDictionaries.mDictMap.clear();
        oldDictionaries.mSubDictMap.clear();
@@ -269,52 +257,28 @@ public class DictionaryFacilitatorForSuggest {
            final ArrayList<String> dictionaryTypes, final HashMap<String, File> dictionaryFiles,
            final Map<String, Map<String, String>> additionalDictAttributes) {
        Dictionary mainDictionary = null;
        ContactsBinaryDictionary contactsDictionary = null;
        UserBinaryDictionary userDictionary = null;
        UserHistoryDictionary userHistoryDictionary = null;
        PersonalizationDictionary personalizationDictionary = null;
        final Map<String, ExpandableBinaryDictionary> subDicts = CollectionUtils.newHashMap();

        for (final String dictType : dictionaryTypes) {
            if (dictType.equals(Dictionary.TYPE_MAIN)) {
                mainDictionary = DictionaryFactory.createMainDictionaryFromManager(context, locale);
            } else if (dictType.equals(Dictionary.TYPE_USER_HISTORY)) {
                userHistoryDictionary =
                        PersonalizationHelper.getUserHistoryDictionary(context, locale);
                // Staring with an empty user history dictionary for testing.
                // Testing program may populate this dictionary before actual testing.
                userHistoryDictionary.reloadDictionaryIfRequired();
                userHistoryDictionary.waitAllTasksForTests();
                if (additionalDictAttributes.containsKey(dictType)) {
                    userHistoryDictionary.clearAndFlushDictionaryWithAdditionalAttributes(
                            additionalDictAttributes.get(dictType));
                }
            } else if (dictType.equals(Dictionary.TYPE_PERSONALIZATION)) {
                personalizationDictionary =
                        PersonalizationHelper.getPersonalizationDictionary(context, locale);
                // Staring with an empty personalization dictionary for testing.
                // Testing program may populate this dictionary before actual testing.
                personalizationDictionary.reloadDictionaryIfRequired();
                personalizationDictionary.waitAllTasksForTests();
            } else {
                final File dictFile = dictionaryFiles.get(dictType);
                final ExpandableBinaryDictionary dict = getSubDict(
                        dictType, context, locale, dictFile);
                if (additionalDictAttributes.containsKey(dictType)) {
                    personalizationDictionary.clearAndFlushDictionaryWithAdditionalAttributes(
                    dict.clearAndFlushDictionaryWithAdditionalAttributes(
                            additionalDictAttributes.get(dictType));
                }
            } else if (dictType.equals(Dictionary.TYPE_USER)) {
                final File file = dictionaryFiles.get(dictType);
                userDictionary = new UserBinaryDictionary(context, locale, file);
                userDictionary.reloadDictionaryIfRequired();
                userDictionary.waitAllTasksForTests();
            } else if (dictType.equals(Dictionary.TYPE_CONTACTS)) {
                final File file = dictionaryFiles.get(dictType);
                contactsDictionary = new ContactsBinaryDictionary(context, locale, file);
                contactsDictionary.reloadDictionaryIfRequired();
                contactsDictionary.waitAllTasksForTests();
            } else {
                if (dict == null) {
                    throw new RuntimeException("Unknown dictionary type: " + dictType);
                }
                dict.reloadDictionaryIfRequired();
                dict.waitAllTasksForTests();
                subDicts.put(dictType, dict);
            }
        }
        mDictionaries = new Dictionaries(locale, mainDictionary, contactsDictionary,
                userDictionary, userHistoryDictionary, personalizationDictionary);
        mDictionaries = new Dictionaries(locale, mainDictionary, subDicts);
    }

    public void closeDictionaries() {
@@ -443,7 +407,7 @@ public class DictionaryFacilitatorForSuggest {
        final SuggestionResults suggestionResults =
                new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS);
        final float[] languageWeight = new float[] { Dictionary.NOT_A_LANGUAGE_WEIGHT };
        for (final String dictType : dictTypesOrderedToGetSuggestion) {
        for (final String dictType : DICT_TYPES_ORDERED_TO_GET_SUGGESTION) {
            final Dictionary dictionary = dictMap.get(dictType);
            if (null == dictionary) continue;
            final ArrayList<SuggestedWordInfo> dictionarySuggestions =
+11 −0
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {

    private final ReentrantReadWriteLock mLock;

    private Map<String, String> mAdditionalAttributeMap = null;

    /* A extension for a binary dictionary file. */
    protected static final String DICT_FILE_EXTENSION = ".dict";

@@ -196,6 +198,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {

    protected Map<String, String> getHeaderAttributeMap() {
        HashMap<String, String> attributeMap = new HashMap<String, String>();
        if (mAdditionalAttributeMap != null) {
            attributeMap.putAll(mAdditionalAttributeMap);
        }
        attributeMap.put(DictionaryHeader.DICTIONARY_ID_KEY, mDictName);
        attributeMap.put(DictionaryHeader.DICTIONARY_LOCALE_KEY, mLocale.toString());
        attributeMap.put(DictionaryHeader.DICTIONARY_VERSION_KEY,
@@ -591,6 +596,12 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
    }

    @UsedForTesting
    public void clearAndFlushDictionaryWithAdditionalAttributes(
            final Map<String, String> attributeMap) {
        mAdditionalAttributeMap = attributeMap;
        clear();
    }

    public void dumpAllWordsForDebug() {
        reloadDictionaryIfRequired();
        asyncExecuteTaskWithLock(mLock.readLock(), new Runnable() {
+0 −16
Original line number Diff line number Diff line
@@ -18,15 +18,11 @@ package com.android.inputmethod.latin.personalization;

import android.content.Context;

import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.ExpandableBinaryDictionary;
import com.android.inputmethod.latin.makedict.DictionaryHeader;
import com.android.inputmethod.latin.utils.LanguageModelParam;

import java.io.File;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Map;

@@ -47,8 +43,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
    /** The locale for this dictionary. */
    public final Locale mLocale;

    private Map<String, String> mAdditionalAttributeMap = null;

    protected DecayingExpandableBinaryDictionaryBase(final Context context,
            final String dictName, final Locale locale, final String dictionaryType,
            final File dictFile) {
@@ -72,9 +66,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
    @Override
    protected Map<String, String> getHeaderAttributeMap() {
        final Map<String, String> attributeMap = super.getHeaderAttributeMap();
        if (mAdditionalAttributeMap != null) {
            attributeMap.putAll(mAdditionalAttributeMap);
        }
        attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY,
                DictionaryHeader.ATTRIBUTE_VALUE_TRUE);
        attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY,
@@ -92,13 +83,6 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB
        // No initial contents.
    }

    @UsedForTesting
    public void clearAndFlushDictionaryWithAdditionalAttributes(
            final Map<String, String> attributeMap) {
        mAdditionalAttributeMap = attributeMap;
        clear();
    }

    /* package */ void runGCIfRequired() {
        runGCIfRequired(false /* mindsBlockByGC */);
    }