From da2ccbd4cd6855712bb172101757f51e8e1ec70d Mon Sep 17 00:00:00 2001 From: Keisuke Kuroyanagi Date: Tue, 19 Nov 2013 18:12:07 +0900 Subject: [PATCH] Create a method to add multiple dictionary entries. Bug: 11740462 Change-Id: I7903cb02fd08d649a05b8799fb3cd00c3da26e00 --- .../latin/ExpandableBinaryDictionary.java | 94 ++++++++++++++++--- ...ecayingExpandableBinaryDictionaryBase.java | 12 +++ ...ersonalizationDictionaryUpdateSession.java | 16 ++++ 3 files changed, 107 insertions(+), 15 deletions(-) diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index d059cc8a9..a0e4e5472 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -288,7 +288,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { private void runGCIfRequiredInternalLocked(final boolean mindsBlockByGC) { // Calls to needsToRunGC() need to be serialized. if (mBinaryDictionary.needsToRunGC(mindsBlockByGC)) { - if (setIsRegeneratingIfNotRegenerating()) { + if (setProcessingLargeTaskIfNot()) { // Run GC after currently existing time sensitive operations. getExecutor(mFilename).executePrioritized(new Runnable() { @Override @@ -296,7 +296,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { try { mBinaryDictionary.flushWithGC(); } finally { - mFilenameDictionaryUpdateController.mIsRegenerating.set(false); + mFilenameDictionaryUpdateController.mProcessingLargeTask.set(false); } } }); @@ -359,13 +359,76 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { }); } + public interface AddMultipleDictionaryEntriesCallback { + public void onFinished(); + } + + public static class LanguageModelParam { + public final String mWord0; + public final String mWord1; + public final boolean mIsValid; + public final int mFrequency; + public final int mBigramFrequency; + public LanguageModelParam(final String word0, final String word1, final boolean isValid, + final int frequency, final int bigramFrequency) { + mWord0 = word0; + mWord1 = word1; + mIsValid = isValid; + mFrequency = frequency; + mBigramFrequency = bigramFrequency; + } + } + + /** + * Dynamically add multiple entries to the dictionary. + */ + protected void addMultipleDictionaryEntriesDynamically( + final ArrayList languageModelParams, + final AddMultipleDictionaryEntriesCallback callback) { + if (!mIsUpdatable) { + Log.w(TAG, "addMultipleDictionaryEntriesDynamically is called for non-updatable " + + "dictionary: " + mFilename); + return; + } + getExecutor(mFilename).execute(new Runnable() { + @Override + public void run() { + final boolean locked = setProcessingLargeTaskIfNot(); + try { + for (final LanguageModelParam languageModelParam : languageModelParams) { + if (languageModelParam.mWord1 == null) { + continue; + } + if (mBinaryDictionary.needsToRunGC(true /* mindsBlockByGC */)) { + mBinaryDictionary.flushWithGC(); + } + mBinaryDictionary.addUnigramWord(languageModelParam.mWord1, + languageModelParam.mFrequency); + if (languageModelParam.mWord0 != null + && !languageModelParam.mWord0.equals(languageModelParam.mWord1)) { + mBinaryDictionary.addBigramWords(languageModelParam.mWord0, + languageModelParam.mWord1, languageModelParam.mBigramFrequency); + } + } + } finally { + if (callback != null) { + callback.onFinished(); + } + if (locked) { + mFilenameDictionaryUpdateController.mProcessingLargeTask.set(false); + } + } + } + }); + } + @Override public ArrayList getSuggestionsWithSessionId(final WordComposer composer, final String prevWord, final ProximityInfo proximityInfo, final boolean blockOffensiveWords, final int[] additionalFeaturesOptions, final int sessionId) { reloadDictionaryIfRequired(); - if (isRegenerating()) { + if (processingLargeTask()) { return null; } final AsyncResultHolder> holder = @@ -402,7 +465,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } protected boolean isValidWordInner(final String word) { - if (isRegenerating()) { + if (processingLargeTask()) { return false; } final AsyncResultHolder holder = new AsyncResultHolder(); @@ -524,7 +587,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { */ public final void reloadDictionaryIfRequired() { if (!isReloadRequired()) return; - if (setIsRegeneratingIfNotRegenerating()) { + if (setProcessingLargeTaskIfNot()) { reloadDictionary(); } } @@ -536,13 +599,14 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { return mBinaryDictionary == null || mPerInstanceDictionaryUpdateController.isOutOfDate(); } - private boolean isRegenerating() { - return mFilenameDictionaryUpdateController.mIsRegenerating.get(); + private boolean processingLargeTask() { + return mFilenameDictionaryUpdateController.mProcessingLargeTask.get(); } - // Returns whether the dictionary can be regenerated. - private boolean setIsRegeneratingIfNotRegenerating() { - return mFilenameDictionaryUpdateController.mIsRegenerating.compareAndSet( + // Returns whether the dictionary is being used for a large task. If true, we should not use + // this dictionary for latency sensitive operations. + private boolean setProcessingLargeTaskIfNot() { + return mFilenameDictionaryUpdateController.mProcessingLargeTask.compareAndSet( false /* expect */ , true /* update */); } @@ -592,7 +656,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } mPerInstanceDictionaryUpdateController.mLastUpdateTime = time; } finally { - mFilenameDictionaryUpdateController.mIsRegenerating.set(false); + mFilenameDictionaryUpdateController.mProcessingLargeTask.set(false); } } }); @@ -619,13 +683,13 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { } /** - * For tracking whether the dictionary is out of date and the dictionary is regenerating. - * Can be shared across multiple dictionary instances that access the same filename. + * For tracking whether the dictionary is out of date and the dictionary is used in a large + * task. Can be shared across multiple dictionary instances that access the same filename. */ private static class DictionaryUpdateController { public volatile long mLastUpdateTime = 0; public volatile long mLastUpdateRequestTime = 0; - public volatile AtomicBoolean mIsRegenerating = new AtomicBoolean(); + public volatile AtomicBoolean mProcessingLargeTask = new AtomicBoolean(); public boolean isOutOfDate() { return (mLastUpdateRequestTime > mLastUpdateTime); @@ -666,7 +730,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { mBinaryDictionary.flushWithGC(); r.run(); } finally { - mFilenameDictionaryUpdateController.mIsRegenerating.set(false); + mFilenameDictionaryUpdateController.mProcessingLargeTask.set(false); } } }); diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java index e7a25d216..42bd7600e 100644 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java @@ -113,6 +113,18 @@ public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableB return false; } + public void addMultipleDictionaryEntriesToDictionary( + final ArrayList languageModelParams, + final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) { + if (languageModelParams == null || languageModelParams.isEmpty()) { + if (callback != null) { + callback.onFinished(); + } + return; + } + addMultipleDictionaryEntriesDynamically(languageModelParams, callback); + } + /** * Pair will be added to the decaying dictionary. * diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java index a86f6e584..1f46f5b1c 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java @@ -18,6 +18,8 @@ package com.android.inputmethod.latin.personalization; import android.content.Context; +import com.android.inputmethod.latin.ExpandableBinaryDictionary; + import java.lang.ref.WeakReference; import java.util.ArrayList; @@ -113,6 +115,20 @@ public abstract class PersonalizationDictionaryUpdateSession { dictionary.addToDictionary(word0, word1, isValid); } + // TODO: Support multi locale. + public void addMultipleDictionaryEntriesToPersonalizationDictionary( + final ArrayList languageModelParams, + final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) { + final DecayingExpandableBinaryDictionaryBase dictionary = getPredictionDictionary(); + if (dictionary == null) { + if (callback != null) { + callback.onFinished(); + } + return; + } + dictionary.addMultipleDictionaryEntriesToDictionary(languageModelParams, callback); + } + // Bulk import // TODO: Support multi locale to add bigram public void addBigramsToPersonalizationDictionary(