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

Commit 6e04d659 authored by Keisuke Kuroyanagi's avatar Keisuke Kuroyanagi
Browse files

Make DynamicPred...Base extend ExpandableBinaryDictionary.

Bug: 6669677
Change-Id: I06afad35d3eb73510c34d10cd4116f5bcf934f7c
parent b2f586b9
Loading
Loading
Loading
Loading
+80 −4
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@ import com.android.inputmethod.latin.utils.CollectionUtils;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantReadWriteLock;

/**
@@ -92,6 +93,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
    /* A extension for a binary dictionary file. */
    public static final String DICT_FILE_EXTENSION = ".dict";

    private final AtomicReference<AsyncWriteBinaryDictionaryTask> mWaitingTask =
            new AtomicReference<AsyncWriteBinaryDictionaryTask>();

    /**
     * Abstract method for loading the unigrams and bigrams of a given dictionary in a background
     * thread.
@@ -180,6 +184,15 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
        }
    }

    protected void clear() {
        mLocalDictionaryController.writeLock().lock();
        try {
            mDictionaryWriter.clear();
        } finally {
            mLocalDictionaryController.writeLock().unlock();
        }
    }

    /**
     * Adds a word unigram to the dictionary. Used for loading a dictionary.
     */
@@ -267,7 +280,8 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
                final ArrayList<SuggestedWordInfo> inMemDictSuggestion =
                        mDictionaryWriter.getSuggestions(composer, prevWord, proximityInfo,
                                blockOffensiveWords);
                if (mBinaryDictionary != null) {
                // TODO: Remove checking mIsUpdatable and use native suggestion.
                if (mBinaryDictionary != null && !mIsUpdatable) {
                    final ArrayList<SuggestedWordInfo> binarySuggestion =
                            mBinaryDictionary.getSuggestions(composer, prevWord, proximityInfo,
                                    blockOffensiveWords);
@@ -276,7 +290,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
                    } else if (binarySuggestion == null) {
                        return inMemDictSuggestion;
                    } else {
                        binarySuggestion.addAll(binarySuggestion);
                        binarySuggestion.addAll(inMemDictSuggestion);
                        return binarySuggestion;
                    }
                } else {
@@ -402,7 +416,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
    /**
     * Reloads the dictionary if required. Reload will occur asynchronously in a separate thread.
     */
    void asyncReloadDictionaryIfRequired() {
    public void asyncReloadDictionaryIfRequired() {
        if (!isReloadRequired()) return;
        if (DEBUG) {
            Log.d(TAG, "Starting AsyncReloadDictionaryTask: " + mFilename);
@@ -413,7 +427,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
    /**
     * Reloads the dictionary if required.
     */
    protected final void syncReloadDictionaryIfRequired() {
    public final void syncReloadDictionaryIfRequired() {
        if (!isReloadRequired()) return;
        syncReloadDictionaryInternal();
    }
@@ -492,6 +506,68 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
        }
    }

    /**
     * Load the dictionary to memory.
     */
    protected void asyncLoadDictionaryToMemory() {
        new AsyncLoadDictionaryToMemoryTask().start();
    }

    /**
     * Thread class for asynchronously loading dictionary to memory.
     */
    private class AsyncLoadDictionaryToMemoryTask extends Thread {
        @Override
        public void run() {
            mLocalDictionaryController.writeLock().lock();
            try {
                mSharedDictionaryController.readLock().lock();
                try {
                    loadDictionaryAsync();
                } finally {
                    mSharedDictionaryController.readLock().unlock();
                }
            } finally {
                mLocalDictionaryController.writeLock().unlock();
            }
        }
    }

    /**
     * Generate binary dictionary using DictionaryWriter.
     */
    protected void asyncWriteBinaryDictionary() {
        final AsyncWriteBinaryDictionaryTask newTask = new AsyncWriteBinaryDictionaryTask();
        newTask.start();
        final AsyncWriteBinaryDictionaryTask oldTask = mWaitingTask.getAndSet(newTask);
        if (oldTask != null) {
            oldTask.interrupt();
        }
    }

    /**
     * Thread class for asynchronously writing the binary dictionary.
     */
    private class AsyncWriteBinaryDictionaryTask extends Thread {
        @Override
        public void run() {
            mSharedDictionaryController.writeLock().lock();
            try {
                mLocalDictionaryController.writeLock().lock();
                try {
                    if (isInterrupted()) {
                        return;
                    }
                    writeBinaryDictionary();
                } finally {
                    mLocalDictionaryController.writeLock().unlock();
                }
            } finally {
                mSharedDictionaryController.writeLock().unlock();
            }
        }
    }

    /**
     * Lock for controlling access to a given binary dictionary and for tracking whether the
     * dictionary is out of date. Can be shared across multiple dictionary instances that access the
+6 −79
Original line number Diff line number Diff line
@@ -16,7 +16,6 @@

package com.android.inputmethod.latin;

import android.content.Context;
import android.text.TextUtils;
import android.util.Log;

@@ -30,9 +29,10 @@ import java.util.ArrayList;
import java.util.LinkedList;

/**
 * Base class for an in-memory dictionary that can grow dynamically and can
 * Class for an in-memory dictionary that can grow dynamically and can
 * be searched for suggestions and valid words.
 */
// TODO: Remove after binary dictionary supports dynamic update.
public class ExpandableDictionary extends Dictionary {
    private static final String TAG = ExpandableDictionary.class.getSimpleName();
    /**
@@ -40,23 +40,11 @@ public class ExpandableDictionary extends Dictionary {
     */
    private static final int FULL_WORD_SCORE_MULTIPLIER = 2;

    // Bigram frequency is a fixed point number with 1 meaning 1.2 and 255 meaning 1.8.
    protected static final int BIGRAM_MAX_FREQUENCY = 255;

    private Context mContext;
    private char[] mWordBuilder = new char[Constants.DICTIONARY_MAX_WORD_LENGTH];
    private int mMaxDepth;
    private int mInputLength;

    private boolean mRequiresReload;

    private boolean mUpdatingDictionary;

    // Use this lock before touching mUpdatingDictionary & mRequiresDownload
    private Object mUpdatingLock = new Object();

    private static final class Node {
        Node() {}
        char mCode;
        int mFrequency;
        boolean mTerminal;
@@ -158,46 +146,12 @@ public class ExpandableDictionary extends Dictionary {

    private int[][] mCodes;

    public ExpandableDictionary(final Context context, final String dictType) {
    public ExpandableDictionary(final String dictType) {
        super(dictType);
        mContext = context;
        clearDictionary();
        mCodes = new int[Constants.DICTIONARY_MAX_WORD_LENGTH][];
    }

    public void loadDictionary() {
        synchronized (mUpdatingLock) {
            startDictionaryLoadingTaskLocked();
        }
    }

    public void startDictionaryLoadingTaskLocked() {
        if (!mUpdatingDictionary) {
            mUpdatingDictionary = true;
            mRequiresReload = false;
            new LoadDictionaryTask().start();
        }
    }

    public void setRequiresReload(final boolean reload) {
        synchronized (mUpdatingLock) {
            mRequiresReload = reload;
        }
    }

    public boolean getRequiresReload() {
        return mRequiresReload;
    }

    /** Override to load your dictionary here, on a background thread. */
    public void loadDictionaryAsync() {
        // empty base implementation
    }

    public Context getContext() {
        return mContext;
    }

    public int getMaxWordLength() {
        return Constants.DICTIONARY_MAX_WORD_LENGTH;
    }
@@ -257,7 +211,6 @@ public class ExpandableDictionary extends Dictionary {
    public ArrayList<SuggestedWordInfo> getSuggestions(final WordComposer composer,
            final String prevWord, final ProximityInfo proximityInfo,
            final boolean blockOffensiveWords) {
        if (reloadDictionaryIfRequired()) return null;
        if (composer.size() > 1) {
            if (composer.size() >= Constants.DICTIONARY_MAX_WORD_LENGTH) {
                return null;
@@ -273,17 +226,7 @@ public class ExpandableDictionary extends Dictionary {
        }
    }

    // This reloads the dictionary if required, and returns whether it's currently updating its
    // contents or not.
    private boolean reloadDictionaryIfRequired() {
        synchronized (mUpdatingLock) {
            // If we need to update, start off a background task
            if (mRequiresReload) startDictionaryLoadingTaskLocked();
            return mUpdatingDictionary;
        }
    }

    protected ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
    private ArrayList<SuggestedWordInfo> getWordsInner(final WordComposer codes,
            final String prevWordForBigrams, final ProximityInfo proximityInfo) {
        final ArrayList<SuggestedWordInfo> suggestions = CollectionUtils.newArrayList();
        mInputLength = codes.size();
@@ -313,11 +256,6 @@ public class ExpandableDictionary extends Dictionary {

    @Override
    public synchronized boolean isValidWord(final String word) {
        synchronized (mUpdatingLock) {
            // If we need to update, start off a background task
            if (mRequiresReload) startDictionaryLoadingTaskLocked();
            if (mUpdatingDictionary) return false;
        }
        final Node node = searchNode(mRoots, word, 0, word.length());
        // If node is null, we didn't find the word, so it's not valid.
        // If node.mShortcutOnly is true, then it exists as a shortcut but not as a word,
@@ -353,7 +291,7 @@ public class ExpandableDictionary extends Dictionary {
     * Returns the word's frequency or -1 if not found
     */
    @UsedForTesting
    protected int getWordFrequency(final String word) {
    public int getWordFrequency(final String word) {
        // Case-sensitive search
        final Node node = searchNode(mRoots, word, 0, word.length());
        return (node == null) ? -1 : node.mFrequency;
@@ -442,7 +380,7 @@ public class ExpandableDictionary extends Dictionary {
     * @param suggestions the list in which to add suggestions
     */
    // TODO: Share this routine with the native code for BinaryDictionary
    protected void getWordsRec(final NodeArray roots, final WordComposer codes, final char[] word,
    private void getWordsRec(final NodeArray roots, final WordComposer codes, final char[] word,
            final int depth, final boolean completion, final int snr, final int inputIndex,
            final int skipPos, final ArrayList<SuggestedWordInfo> suggestions) {
        final int count = roots.mLength;
@@ -704,17 +642,6 @@ public class ExpandableDictionary extends Dictionary {
        mRoots = new NodeArray();
    }

    private final class LoadDictionaryTask extends Thread {
        LoadDictionaryTask() {}
        @Override
        public void run() {
            loadDictionaryAsync();
            synchronized (mUpdatingLock) {
                mUpdatingDictionary = false;
            }
        }
    }

    private static char toLowerCase(final char c) {
        char baseChar = c;
        if (c < BASE_CHARS.length) {
+4 −4
Original line number Diff line number Diff line
@@ -74,8 +74,8 @@ import com.android.inputmethod.keyboard.MainKeyboardView;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.define.ProductionFlag;
import com.android.inputmethod.latin.personalization.PersonalizationDictionary;
import com.android.inputmethod.latin.personalization.PersonalizationDictionaryHelper;
import com.android.inputmethod.latin.personalization.PersonalizationDictionarySessionRegister;
import com.android.inputmethod.latin.personalization.PersonalizationHelper;
import com.android.inputmethod.latin.personalization.PersonalizationPredictionDictionary;
import com.android.inputmethod.latin.personalization.UserHistoryPredictionDictionary;
import com.android.inputmethod.latin.settings.Settings;
@@ -566,13 +566,13 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen

        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);

        mUserHistoryPredictionDictionary = PersonalizationDictionaryHelper
        mUserHistoryPredictionDictionary = PersonalizationHelper
                .getUserHistoryPredictionDictionary(this, localeStr, prefs);
        newSuggest.setUserHistoryPredictionDictionary(mUserHistoryPredictionDictionary);
        mPersonalizationDictionary = PersonalizationDictionaryHelper
        mPersonalizationDictionary = PersonalizationHelper
                .getPersonalizationDictionary(this, localeStr, prefs);
        newSuggest.setPersonalizationDictionary(mPersonalizationDictionary);
        mPersonalizationPredictionDictionary = PersonalizationDictionaryHelper
        mPersonalizationPredictionDictionary = PersonalizationHelper
                .getPersonalizationPredictionDictionary(this, localeStr, prefs);
        newSuggest.setPersonalizationPredictionDictionary(mPersonalizationPredictionDictionary);

+1 −1
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ public class DynamicPersonalizationDictionaryWriter extends AbstractDictionaryWr

    public DynamicPersonalizationDictionaryWriter(final Context context, final String dictType) {
        super(context, dictType);
        mExpandableDictionary = new ExpandableDictionary(context, dictType);
        mExpandableDictionary = new ExpandableDictionary(dictType);
    }

    @Override
+52 −247

File changed.

Preview size limit exceeded, changes collapsed.

Loading