diff options
21 files changed, 223 insertions, 108 deletions
diff --git a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java index d50dd3ee6..27896fd11 100644 --- a/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java +++ b/java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java @@ -114,7 +114,7 @@ public final class AccessibilityUtils { * @param event The event to check. * @return {@true} is the event is a touch exploration event */ - public boolean isTouchExplorationEvent(final MotionEvent event) { + public static boolean isTouchExplorationEvent(final MotionEvent event) { final int action = event.getAction(); return action == MotionEvent.ACTION_HOVER_ENTER || action == MotionEvent.ACTION_HOVER_EXIT diff --git a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java index d6ae698cc..a6997e2f9 100644 --- a/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java +++ b/java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java @@ -134,7 +134,7 @@ public final class KeyboardAccessibilityNodeProvider extends AccessibilityNodePr event.setClassName(key.getClass().getName()); event.setContentDescription(keyDescription); event.setEnabled(true); - final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event); + final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event); record.setSource(mKeyboardView, virtualViewId); return event; } diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java index 97f262989..fd34b98f4 100644 --- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java @@ -183,9 +183,9 @@ public final class BinaryDictionary extends Dictionary { private static native void getHeaderInfoNative(long dict, int[] outHeaderSize, int[] outFormatVersion, ArrayList<int[]> outAttributeKeys, ArrayList<int[]> outAttributeValues); - private static native void flushNative(long dict, String filePath); + private static native boolean flushNative(long dict, String filePath); private static native boolean needsToRunGCNative(long dict, boolean mindsBlockByGC); - private static native void flushWithGCNative(long dict, String filePath); + private static native boolean flushWithGCNative(long dict, String filePath); private static native void closeNative(long dict); private static native int getFormatVersionNative(long dict); private static native int getProbabilityNative(long dict, int[] word); @@ -203,12 +203,12 @@ public final class BinaryDictionary extends Dictionary { int[] outputSuggestionCount, int[] outputCodePoints, int[] outputScores, int[] outputIndices, int[] outputTypes, int[] outputAutoCommitFirstWordConfidence, float[] inOutLanguageWeight); - private static native void addUnigramWordNative(long dict, int[] word, int probability, + private static native boolean addUnigramWordNative(long dict, int[] word, int probability, int[] shortcutTarget, int shortcutProbability, boolean isBeginningOfSentence, boolean isNotAWord, boolean isBlacklisted, int timestamp); - private static native void addBigramWordsNative(long dict, int[] word0, + private static native boolean addBigramWordsNative(long dict, int[] word0, boolean isBeginningOfSentence, int[] word1, int probability, int timestamp); - private static native void removeBigramWordsNative(long dict, int[] word0, + private static native boolean removeBigramWordsNative(long dict, int[] word0, boolean isBeginningOfSentence, int[] word1); private static native int addMultipleDictionaryEntriesNative(long dict, LanguageModelParam[] languageModelParams, int startIndex); @@ -417,45 +417,53 @@ public final class BinaryDictionary extends Dictionary { } // Add a unigram entry to binary dictionary with unigram attributes in native code. - public void addUnigramEntry(final String word, final int probability, + public boolean addUnigramEntry(final String word, final int probability, final String shortcutTarget, final int shortcutProbability, final boolean isBeginningOfSentence, final boolean isNotAWord, final boolean isBlacklisted, final int timestamp) { if (word == null || (word.isEmpty() && !isBeginningOfSentence)) { - return; + return false; } final int[] codePoints = StringUtils.toCodePointArray(word); final int[] shortcutTargetCodePoints = (shortcutTarget != null) ? StringUtils.toCodePointArray(shortcutTarget) : null; - addUnigramWordNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints, - shortcutProbability, isBeginningOfSentence, isNotAWord, isBlacklisted, timestamp); + if (!addUnigramWordNative(mNativeDict, codePoints, probability, shortcutTargetCodePoints, + shortcutProbability, isBeginningOfSentence, isNotAWord, isBlacklisted, timestamp)) { + return false; + } mHasUpdated = true; + return true; } // Add an n-gram entry to the binary dictionary with timestamp in native code. - public void addNgramEntry(final PrevWordsInfo prevWordsInfo, final String word, - final int probability, - final int timestamp) { + public boolean addNgramEntry(final PrevWordsInfo prevWordsInfo, final String word, + final int probability, final int timestamp) { if (!prevWordsInfo.isValid() || TextUtils.isEmpty(word)) { - return; + return false; } final int[] codePoints0 = StringUtils.toCodePointArray(prevWordsInfo.mPrevWord); final int[] codePoints1 = StringUtils.toCodePointArray(word); - addBigramWordsNative(mNativeDict, codePoints0, prevWordsInfo.mIsBeginningOfSentence, - codePoints1, probability, timestamp); + if (!addBigramWordsNative(mNativeDict, codePoints0, prevWordsInfo.mIsBeginningOfSentence, + codePoints1, probability, timestamp)) { + return false; + } mHasUpdated = true; + return true; } // Remove an n-gram entry from the binary dictionary in native code. - public void removeNgramEntry(final PrevWordsInfo prevWordsInfo, final String word) { + public boolean removeNgramEntry(final PrevWordsInfo prevWordsInfo, final String word) { if (!prevWordsInfo.isValid() || TextUtils.isEmpty(word)) { - return; + return false; } final int[] codePoints0 = StringUtils.toCodePointArray(prevWordsInfo.mPrevWord); final int[] codePoints1 = StringUtils.toCodePointArray(word); - removeBigramWordsNative(mNativeDict, codePoints0, prevWordsInfo.mIsBeginningOfSentence, - codePoints1); + if (!removeBigramWordsNative(mNativeDict, codePoints0, prevWordsInfo.mIsBeginningOfSentence, + codePoints1)) { + return false; + } mHasUpdated = true; + return true; } public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) { @@ -485,26 +493,33 @@ public final class BinaryDictionary extends Dictionary { } // Flush to dict file if the dictionary has been updated. - public void flush() { - if (!isValidDictionary()) return; + public boolean flush() { + if (!isValidDictionary()) return false; if (mHasUpdated) { - flushNative(mNativeDict, mDictFilePath); + if (!flushNative(mNativeDict, mDictFilePath)) { + return false; + } reopen(); } + return true; } // Run GC and flush to dict file if the dictionary has been updated. - public void flushWithGCIfHasUpdated() { + public boolean flushWithGCIfHasUpdated() { if (mHasUpdated) { - flushWithGC(); + return flushWithGC(); } + return true; } // Run GC and flush to dict file. - public void flushWithGC() { - if (!isValidDictionary()) return; - flushWithGCNative(mNativeDict, mDictFilePath); + public boolean flushWithGC() { + if (!isValidDictionary()) return false; + if (!flushWithGCNative(mNativeDict, mDictFilePath)) { + return false; + } reopen(); + return true; } /** diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 4cb920f37..7fa3d0479 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -408,7 +408,7 @@ public class DictionaryFacilitator { if (userHistoryDictionary == null) { return; } - final int maxFreq = getMaxFrequency(word); + final int maxFreq = getFrequency(word); if (maxFreq == 0 && blockPotentiallyOffensive) { return; } @@ -516,7 +516,7 @@ public class DictionaryFacilitator { return false; } - private int getMaxFrequency(final String word) { + public int getFrequency(final String word) { if (TextUtils.isEmpty(word)) { return Dictionary.NOT_A_PROBABILITY; } diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 95ff8c6e3..b10bae01a 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -298,8 +298,10 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected void addUnigramLocked(final String word, final int frequency, final String shortcutTarget, final int shortcutFreq, final boolean isNotAWord, final boolean isBlacklisted, final int timestamp) { - mBinaryDictionary.addUnigramEntry(word, frequency, shortcutTarget, shortcutFreq, - false /* isBeginningOfSentence */, isNotAWord, isBlacklisted, timestamp); + if (!mBinaryDictionary.addUnigramEntry(word, frequency, shortcutTarget, shortcutFreq, + false /* isBeginningOfSentence */, isNotAWord, isBlacklisted, timestamp)) { + Log.e(TAG, "Cannot add unigram entry. word: " + word); + } } /** @@ -322,7 +324,11 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { protected void addNgramEntryLocked(final PrevWordsInfo prevWordsInfo, final String word, final int frequency, final int timestamp) { - mBinaryDictionary.addNgramEntry(prevWordsInfo, word, frequency, timestamp); + if (!mBinaryDictionary.addNgramEntry(prevWordsInfo, word, frequency, timestamp)) { + Log.e(TAG, "Cannot add n-gram entry."); + Log.e(TAG, " PrevWordsInfo: " + prevWordsInfo); + Log.e(TAG, " word: " + word); + } } /** diff --git a/java/src/com/android/inputmethod/latin/PrevWordsInfo.java b/java/src/com/android/inputmethod/latin/PrevWordsInfo.java index e44239f1d..42b311c69 100644 --- a/java/src/com/android/inputmethod/latin/PrevWordsInfo.java +++ b/java/src/com/android/inputmethod/latin/PrevWordsInfo.java @@ -53,4 +53,10 @@ public class PrevWordsInfo { public boolean isValid() { return mPrevWord != null; } + + @Override + public String toString() { + return "PrevWord: " + mPrevWord + ", isBeginningOfSentence: " + + mIsBeginningOfSentence + "."; + } } diff --git a/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java index 1c93a9105..ac0ab28bf 100644 --- a/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java +++ b/java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java @@ -33,6 +33,7 @@ import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardLayoutSet; import com.android.inputmethod.latin.Constants; +import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.DictionaryFacilitator; import com.android.inputmethod.latin.PrevWordsInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; @@ -98,10 +99,12 @@ public class DistracterFilterUsingSuggestion implements DistracterFilter { } } - private static boolean isDistracter( + private boolean isDistracter( final SuggestionResults suggestionResults, final String consideredWord) { + int perfectMatchProbability = Dictionary.NOT_A_PROBABILITY; for (final SuggestedWordInfo suggestedWordInfo : suggestionResults) { if (suggestedWordInfo.mWord.equals(consideredWord)) { + perfectMatchProbability = mDictionaryFacilitator.getFrequency(consideredWord); continue; } // Exact match can include case errors, accent errors, digraph conversions. @@ -121,6 +124,17 @@ public class DistracterFilterUsingSuggestion implements DistracterFilter { Log.d(TAG, "isExactMatchWithIntentionalOmission: " + isExactMatchWithIntentionalOmission); } + if (perfectMatchProbability != Dictionary.NOT_A_PROBABILITY) { + final int topNonPerfectProbability = mDictionaryFacilitator.getFrequency( + suggestedWordInfo.mWord); + if (DEBUG) { + Log.d(TAG, "perfectMatchProbability: " + perfectMatchProbability); + Log.d(TAG, "topNonPerfectProbability: " + topNonPerfectProbability); + } + if (perfectMatchProbability > topNonPerfectProbability) { + return false; + } + } return isExactMatch || isExactMatchWithIntentionalOmission; } return false; diff --git a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java index 7b678e175..c08697c4b 100644 --- a/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java @@ -28,14 +28,14 @@ public class ExecutorUtils { new ConcurrentHashMap<>(); /** - * Gets the executor for the given dictionary name. + * Gets the executor for the given id. */ - public static PrioritizedSerialExecutor getExecutor(final String dictName) { - PrioritizedSerialExecutor executor = sExecutorMap.get(dictName); + public static PrioritizedSerialExecutor getExecutor(final String id) { + PrioritizedSerialExecutor executor = sExecutorMap.get(id); if (executor == null) { synchronized(sExecutorMap) { - executor = new PrioritizedSerialExecutor(); - sExecutorMap.put(dictName, executor); + executor = new PrioritizedSerialExecutor(id); + sExecutorMap.put(id, executor); } } return executor; diff --git a/java/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutor.java b/java/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutor.java index 148f3bce6..21949ffbd 100644 --- a/java/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutor.java +++ b/java/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutor.java @@ -21,6 +21,7 @@ import com.android.inputmethod.annotations.UsedForTesting; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; @@ -40,12 +41,26 @@ public class PrioritizedSerialExecutor { // The task which is running now. private Runnable mActive; - public PrioritizedSerialExecutor() { + private static class ThreadFactoryWithId implements ThreadFactory { + private final String mId; + + public ThreadFactoryWithId(final String id) { + mId = id; + } + + @Override + public Thread newThread(final Runnable r) { + return new Thread(r, TAG + " - " + mId); + } + } + + public PrioritizedSerialExecutor(final String id) { mTasks = new ConcurrentLinkedQueue<>(); mPrioritizedTasks = new ConcurrentLinkedQueue<>(); mIsShutdown = false; mThreadPoolExecutor = new ThreadPoolExecutor(1 /* corePoolSize */, 1 /* maximumPoolSize */, - 0 /* keepAliveTime */, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1)); + 0 /* keepAliveTime */, TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(1), + new ThreadFactoryWithId(id)); } /** diff --git a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp index e41fe1d43..d6a6196d2 100644 --- a/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp +++ b/native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp @@ -95,15 +95,15 @@ static jlong latinime_BinaryDictionary_createOnMemory(JNIEnv *env, jclass clazz, return reinterpret_cast<jlong>(dictionary); } -static void latinime_BinaryDictionary_flush(JNIEnv *env, jclass clazz, jlong dict, +static bool latinime_BinaryDictionary_flush(JNIEnv *env, jclass clazz, jlong dict, jstring filePath) { Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); - if (!dictionary) return; + if (!dictionary) return false; const jsize filePathUtf8Length = env->GetStringUTFLength(filePath); char filePathChars[filePathUtf8Length + 1]; env->GetStringUTFRegion(filePath, 0, env->GetStringLength(filePath), filePathChars); filePathChars[filePathUtf8Length] = '\0'; - dictionary->flush(filePathChars); + return dictionary->flush(filePathChars); } static bool latinime_BinaryDictionary_needsToRunGC(JNIEnv *env, jclass clazz, @@ -113,15 +113,15 @@ static bool latinime_BinaryDictionary_needsToRunGC(JNIEnv *env, jclass clazz, return dictionary->needsToRunGC(mindsBlockByGC == JNI_TRUE); } -static void latinime_BinaryDictionary_flushWithGC(JNIEnv *env, jclass clazz, jlong dict, +static bool latinime_BinaryDictionary_flushWithGC(JNIEnv *env, jclass clazz, jlong dict, jstring filePath) { Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); - if (!dictionary) return; + if (!dictionary) return false; const jsize filePathUtf8Length = env->GetStringUTFLength(filePath); char filePathChars[filePathUtf8Length + 1]; env->GetStringUTFRegion(filePath, 0, env->GetStringLength(filePath), filePathChars); filePathChars[filePathUtf8Length] = '\0'; - dictionary->flushWithGC(filePathChars); + return dictionary->flushWithGC(filePathChars); } static void latinime_BinaryDictionary_close(JNIEnv *env, jclass clazz, jlong dict) { @@ -324,13 +324,13 @@ static void latinime_BinaryDictionary_getWordProperty(JNIEnv *env, jclass clazz, outShortcutProbabilities); } -static void latinime_BinaryDictionary_addUnigramWord(JNIEnv *env, jclass clazz, jlong dict, +static bool latinime_BinaryDictionary_addUnigramWord(JNIEnv *env, jclass clazz, jlong dict, jintArray word, jint probability, jintArray shortcutTarget, jint shortcutProbability, jboolean isBeginningOfSentence, jboolean isNotAWord, jboolean isBlacklisted, jint timestamp) { Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); if (!dictionary) { - return; + return false; } jsize codePointCount = env->GetArrayLength(word); int codePoints[codePointCount]; @@ -344,15 +344,15 @@ static void latinime_BinaryDictionary_addUnigramWord(JNIEnv *env, jclass clazz, // Use 1 for count to indicate the word has inputted. const UnigramProperty unigramProperty(isBeginningOfSentence, isNotAWord, isBlacklisted, probability, timestamp, 0 /* level */, 1 /* count */, &shortcuts); - dictionary->addUnigramEntry(codePoints, codePointCount, &unigramProperty); + return dictionary->addUnigramEntry(codePoints, codePointCount, &unigramProperty); } -static void latinime_BinaryDictionary_addBigramWords(JNIEnv *env, jclass clazz, jlong dict, +static bool latinime_BinaryDictionary_addBigramWords(JNIEnv *env, jclass clazz, jlong dict, jintArray word0, jboolean isBeginningOfSentence, jintArray word1, jint probability, jint timestamp) { Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); if (!dictionary) { - return; + return false; } jsize word0Length = env->GetArrayLength(word0); int word0CodePoints[word0Length]; @@ -366,14 +366,14 @@ static void latinime_BinaryDictionary_addBigramWords(JNIEnv *env, jclass clazz, const BigramProperty bigramProperty(&bigramTargetCodePoints, probability, timestamp, 0 /* level */, 1 /* count */); const PrevWordsInfo prevWordsInfo(word0CodePoints, word0Length, isBeginningOfSentence); - dictionary->addNgramEntry(&prevWordsInfo, &bigramProperty); + return dictionary->addNgramEntry(&prevWordsInfo, &bigramProperty); } -static void latinime_BinaryDictionary_removeBigramWords(JNIEnv *env, jclass clazz, jlong dict, +static bool latinime_BinaryDictionary_removeBigramWords(JNIEnv *env, jclass clazz, jlong dict, jintArray word0, jboolean isBeginningOfSentence, jintArray word1) { Dictionary *dictionary = reinterpret_cast<Dictionary *>(dict); if (!dictionary) { - return; + return false; } jsize word0Length = env->GetArrayLength(word0); int word0CodePoints[word0Length]; @@ -382,7 +382,7 @@ static void latinime_BinaryDictionary_removeBigramWords(JNIEnv *env, jclass claz int word1CodePoints[word1Length]; env->GetIntArrayRegion(word1, 0, word1Length, word1CodePoints); const PrevWordsInfo prevWordsInfo(word0CodePoints, word0Length, isBeginningOfSentence); - dictionary->removeNgramEntry(&prevWordsInfo, word1CodePoints, word1Length); + return dictionary->removeNgramEntry(&prevWordsInfo, word1CodePoints, word1Length); } // Returns how many language model params are processed. @@ -610,7 +610,7 @@ static const JNINativeMethod sMethods[] = { }, { const_cast<char *>("flushNative"), - const_cast<char *>("(JLjava/lang/String;)V"), + const_cast<char *>("(JLjava/lang/String;)Z"), reinterpret_cast<void *>(latinime_BinaryDictionary_flush) }, { @@ -620,7 +620,7 @@ static const JNINativeMethod sMethods[] = { }, { const_cast<char *>("flushWithGCNative"), - const_cast<char *>("(JLjava/lang/String;)V"), + const_cast<char *>("(JLjava/lang/String;)Z"), reinterpret_cast<void *>(latinime_BinaryDictionary_flushWithGC) }, { @@ -651,17 +651,17 @@ static const JNINativeMethod sMethods[] = { }, { const_cast<char *>("addUnigramWordNative"), - const_cast<char *>("(J[II[IIZZZI)V"), + const_cast<char *>("(J[II[IIZZZI)Z"), reinterpret_cast<void *>(latinime_BinaryDictionary_addUnigramWord) }, { const_cast<char *>("addBigramWordsNative"), - const_cast<char *>("(J[IZ[III)V"), + const_cast<char *>("(J[IZ[III)Z"), reinterpret_cast<void *>(latinime_BinaryDictionary_addBigramWords) }, { const_cast<char *>("removeBigramWordsNative"), - const_cast<char *>("(J[IZ[I)V"), + const_cast<char *>("(J[IZ[I)Z"), reinterpret_cast<void *>(latinime_BinaryDictionary_removeBigramWords) }, { diff --git a/native/jni/src/suggest/core/dictionary/dictionary.cpp b/native/jni/src/suggest/core/dictionary/dictionary.cpp index bcf7d5905..898b44f44 100644 --- a/native/jni/src/suggest/core/dictionary/dictionary.cpp +++ b/native/jni/src/suggest/core/dictionary/dictionary.cpp @@ -80,38 +80,38 @@ int Dictionary::getBigramProbability(const PrevWordsInfo *const prevWordsInfo, c return mBigramDictionary.getBigramProbability(prevWordsInfo, word, length); } -void Dictionary::addUnigramEntry(const int *const word, const int length, +bool Dictionary::addUnigramEntry(const int *const word, const int length, const UnigramProperty *const unigramProperty) { if (unigramProperty->representsBeginningOfSentence() && !mDictionaryStructureWithBufferPolicy->getHeaderStructurePolicy() ->supportsBeginningOfSentence()) { AKLOGE("The dictionary doesn't support Beginning-of-Sentence."); - return; + return false; } TimeKeeper::setCurrentTime(); - mDictionaryStructureWithBufferPolicy->addUnigramEntry(word, length, unigramProperty); + return mDictionaryStructureWithBufferPolicy->addUnigramEntry(word, length, unigramProperty); } -void Dictionary::addNgramEntry(const PrevWordsInfo *const prevWordsInfo, +bool Dictionary::addNgramEntry(const PrevWordsInfo *const prevWordsInfo, const BigramProperty *const bigramProperty) { TimeKeeper::setCurrentTime(); - mDictionaryStructureWithBufferPolicy->addNgramEntry(prevWordsInfo, bigramProperty); + return mDictionaryStructureWithBufferPolicy->addNgramEntry(prevWordsInfo, bigramProperty); } -void Dictionary::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, +bool Dictionary::removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word, const int length) { TimeKeeper::setCurrentTime(); - mDictionaryStructureWithBufferPolicy->removeNgramEntry(prevWordsInfo, word, length); + return mDictionaryStructureWithBufferPolicy->removeNgramEntry(prevWordsInfo, word, length); } -void Dictionary::flush(const char *const filePath) { +bool Dictionary::flush(const char *const filePath) { TimeKeeper::setCurrentTime(); - mDictionaryStructureWithBufferPolicy->flush(filePath); + return mDictionaryStructureWithBufferPolicy->flush(filePath); } -void Dictionary::flushWithGC(const char *const filePath) { +bool Dictionary::flushWithGC(const char *const filePath) { TimeKeeper::setCurrentTime(); - mDictionaryStructureWithBufferPolicy->flushWithGC(filePath); + return mDictionaryStructureWithBufferPolicy->flushWithGC(filePath); } bool Dictionary::needsToRunGC(const bool mindsBlockByGC) { diff --git a/native/jni/src/suggest/core/dictionary/dictionary.h b/native/jni/src/suggest/core/dictionary/dictionary.h index e665f7bea..f6d406fbd 100644 --- a/native/jni/src/suggest/core/dictionary/dictionary.h +++ b/native/jni/src/suggest/core/dictionary/dictionary.h @@ -76,18 +76,18 @@ class Dictionary { int getBigramProbability(const PrevWordsInfo *const prevWordsInfo, const int *word, int length) const; - void addUnigramEntry(const int *const codePoints, const int codePointCount, + bool addUnigramEntry(const int *const codePoints, const int codePointCount, const UnigramProperty *const unigramProperty); - void addNgramEntry(const PrevWordsInfo *const prevWordsInfo, + bool addNgramEntry(const PrevWordsInfo *const prevWordsInfo, const BigramProperty *const bigramProperty); - void removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word, + bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word, const int length); - void flush(const char *const filePath); + bool flush(const char *const filePath); - void flushWithGC(const char *const filePath); + bool flushWithGC(const char *const filePath); bool needsToRunGC(const bool mindsBlockByGC); diff --git a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h index 3fd815f98..cda89406c 100644 --- a/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h +++ b/native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h @@ -81,9 +81,11 @@ class DictionaryStructureWithBufferPolicy { virtual bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word, const int length) = 0; - virtual void flush(const char *const filePath) = 0; + // Returns whether the flush was success or not. + virtual bool flush(const char *const filePath) = 0; - virtual void flushWithGC(const char *const filePath) = 0; + // Returns whether the GC and flush were success or not. + virtual bool flushWithGC(const char *const filePath) = 0; virtual bool needsToRunGC(const bool mindsBlockByGC) const = 0; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp index 557a0b4c8..0f60a898d 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp @@ -296,26 +296,30 @@ bool Ver4PatriciaTriePolicy::removeNgramEntry(const PrevWordsInfo *const prevWor } } -void Ver4PatriciaTriePolicy::flush(const char *const filePath) { +bool Ver4PatriciaTriePolicy::flush(const char *const filePath) { if (!mBuffers->isUpdatable()) { AKLOGI("Warning: flush() is called for non-updatable dictionary. filePath: %s", filePath); - return; + return false; } if (!mWritingHelper.writeToDictFile(filePath, mUnigramCount, mBigramCount)) { AKLOGE("Cannot flush the dictionary to file."); mIsCorrupted = true; + return false; } + return true; } -void Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) { +bool Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) { if (!mBuffers->isUpdatable()) { AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary."); - return; + return false; } if (!mWritingHelper.writeToDictFileWithGC(getRootPosition(), filePath)) { AKLOGE("Cannot flush the dictionary to file with GC."); mIsCorrupted = true; + return false; } + return true; } bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const { diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h index 95813881d..b064aaf33 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h @@ -117,9 +117,9 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word, const int length); - void flush(const char *const filePath); + bool flush(const char *const filePath); - void flushWithGC(const char *const filePath); + bool flushWithGC(const char *const filePath); bool needsToRunGC(const bool mindsBlockByGC) const; diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h index 6240d46aa..88bbfd966 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h @@ -102,14 +102,16 @@ class PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { return false; } - void flush(const char *const filePath) { + bool flush(const char *const filePath) { // This method should not be called for non-updatable dictionary. AKLOGI("Warning: flush() is called for non-updatable dictionary."); + return false; } - void flushWithGC(const char *const filePath) { + bool flushWithGC(const char *const filePath) { // This method should not be called for non-updatable dictionary. AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary."); + return false; } bool needsToRunGC(const bool mindsBlockByGC) const { diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp index 02478700a..09c7b7d85 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp @@ -304,26 +304,30 @@ bool Ver4PatriciaTriePolicy::removeNgramEntry(const PrevWordsInfo *const prevWor } } -void Ver4PatriciaTriePolicy::flush(const char *const filePath) { +bool Ver4PatriciaTriePolicy::flush(const char *const filePath) { if (!mBuffers->isUpdatable()) { AKLOGI("Warning: flush() is called for non-updatable dictionary. filePath: %s", filePath); - return; + return false; } if (!mWritingHelper.writeToDictFile(filePath, mUnigramCount, mBigramCount)) { AKLOGE("Cannot flush the dictionary to file."); mIsCorrupted = true; + return false; } + return true; } -void Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) { +bool Ver4PatriciaTriePolicy::flushWithGC(const char *const filePath) { if (!mBuffers->isUpdatable()) { AKLOGI("Warning: flushWithGC() is called for non-updatable dictionary."); - return; + return false; } if (!mWritingHelper.writeToDictFileWithGC(getRootPosition(), filePath)) { AKLOGE("Cannot flush the dictionary to file with GC."); mIsCorrupted = true; + return false; } + return true; } bool Ver4PatriciaTriePolicy::needsToRunGC(const bool mindsBlockByGC) const { diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h index 008f2e423..d198c97fd 100644 --- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h +++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h @@ -99,9 +99,9 @@ class Ver4PatriciaTriePolicy : public DictionaryStructureWithBufferPolicy { bool removeNgramEntry(const PrevWordsInfo *const prevWordsInfo, const int *const word1, const int length1); - void flush(const char *const filePath); + bool flush(const char *const filePath); - void flushWithGC(const char *const filePath); + bool flushWithGC(const char *const filePath); bool needsToRunGC(const bool mindsBlockByGC) const; diff --git a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java index a4dbfaa6b..406e9a9b8 100644 --- a/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java +++ b/tests/src/com/android/inputmethod/latin/DistracterFilterTest.java @@ -57,11 +57,36 @@ public class DistracterFilterTest extends InputTestsBase { assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries( EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs)); - typedWord = "were"; - // For this test case, we consider "were" is a distracter to "we're". + typedWord = "youre"; + // For this test case, we consider "youre" is a distracter to "you're". assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries( EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs)); + typedWord = "Banana"; + // For this test case, we consider "Banana" is a distracter to "banana". + assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries( + EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs)); + + typedWord = "orange"; + // For this test case, we consider "orange" is not a distracter to any word in dictionaries. + assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries( + EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs)); + + typedWord = "Orange"; + // For this test case, we consider "Orange" is a distracter to "orange". + assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries( + EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs)); + + typedWord = "café"; + // For this test case, we consider "café" is a distracter to "cafe". + assertTrue(mDistracterFilter.isDistracterToWordsInDictionaries( + EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs)); + + typedWord = "cafe"; + // For this test case, we consider "café" is not a distracter to any word in dictionaries. + assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries( + EMPTY_PREV_WORDS_INFO, typedWord, localeEnUs)); + typedWord = "ill"; // For this test case, we consider "ill" is not a distracter to any word in dictionaries. assertFalse(mDistracterFilter.isDistracterToWordsInDictionaries( diff --git a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java index 0528e341e..8f32e5336 100644 --- a/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java +++ b/tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java @@ -75,33 +75,54 @@ public class Ver4DictEncoder implements DictEncoder { for (final WordProperty wordProperty : dict) { // TODO: switch to addMultipleDictionaryEntries when they support shortcuts if (null == wordProperty.mShortcutTargets || wordProperty.mShortcutTargets.isEmpty()) { - binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(), + if (!binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(), null /* shortcutTarget */, 0 /* shortcutProbability */, wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord, - wordProperty.mIsBlacklistEntry, 0 /* timestamp */); + wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) { + MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord); + } } else { for (final WeightedString shortcutTarget : wordProperty.mShortcutTargets) { - binaryDict.addUnigramEntry(wordProperty.mWord, wordProperty.getProbability(), + if (!binaryDict.addUnigramEntry(wordProperty.mWord, + wordProperty.getProbability(), shortcutTarget.mWord, shortcutTarget.getProbability(), wordProperty.mIsBeginningOfSentence, wordProperty.mIsNotAWord, - wordProperty.mIsBlacklistEntry, 0 /* timestamp */); + wordProperty.mIsBlacklistEntry, 0 /* timestamp */)) { + MakedictLog.e("Cannot add unigram entry for " + wordProperty.mWord + + ", shortcutTarget: " + shortcutTarget.mWord); + return; + } } } if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) { - binaryDict.flushWithGC(); + if (!binaryDict.flushWithGC()) { + MakedictLog.e("Cannot flush dict with GC."); + return; + } } } for (final WordProperty word0Property : dict) { if (null == word0Property.mBigrams) continue; for (final WeightedString word1 : word0Property.mBigrams) { - binaryDict.addNgramEntry(new PrevWordsInfo(word0Property.mWord), word1.mWord, - word1.getProbability(), 0 /* timestamp */); + final PrevWordsInfo prevWordsInfo = new PrevWordsInfo(word0Property.mWord); + if (!binaryDict.addNgramEntry(prevWordsInfo, word1.mWord, + word1.getProbability(), 0 /* timestamp */)) { + MakedictLog.e("Cannot add n-gram entry for " + + prevWordsInfo + " -> " + word1.mWord); + return; + } if (binaryDict.needsToRunGC(true /* mindsBlockByGC */)) { - binaryDict.flushWithGC(); + if (!binaryDict.flushWithGC()) { + MakedictLog.e("Cannot flush dict with GC."); + return; + } } } } - binaryDict.flushWithGC(); + if (!binaryDict.flushWithGC()) { + MakedictLog.e("Cannot flush dict with GC."); + return; + } binaryDict.close(); } diff --git a/tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java b/tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java index e0755483c..8b78816ce 100644 --- a/tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java +++ b/tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java @@ -30,11 +30,12 @@ import java.util.concurrent.atomic.AtomicInteger; public class PrioritizedSerialExecutorTests extends AndroidTestCase { private static final String TAG = PrioritizedSerialExecutorTests.class.getSimpleName(); + private static final String TEST_EXECUTOR_ID = "test"; private static final int NUM_OF_TASKS = 10; private static final int DELAY_FOR_WAITING_TASKS_MILLISECONDS = 500; public void testExecute() { - final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor(); + final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor(TEST_EXECUTOR_ID); final AtomicInteger v = new AtomicInteger(0); for (int i = 0; i < NUM_OF_TASKS; ++i) { executor.execute(new Runnable() { @@ -54,7 +55,7 @@ public class PrioritizedSerialExecutorTests extends AndroidTestCase { } public void testExecutePrioritized() { - final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor(); + final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor(TEST_EXECUTOR_ID); final AtomicInteger v = new AtomicInteger(0); for (int i = 0; i < NUM_OF_TASKS; ++i) { executor.executePrioritized(new Runnable() { @@ -74,7 +75,7 @@ public class PrioritizedSerialExecutorTests extends AndroidTestCase { } public void testExecuteCombined() { - final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor(); + final PrioritizedSerialExecutor executor = new PrioritizedSerialExecutor(TEST_EXECUTOR_ID); final AtomicInteger v = new AtomicInteger(0); for (int i = 0; i < NUM_OF_TASKS; ++i) { executor.execute(new Runnable() { |