aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--java/src/com/android/inputmethod/accessibility/AccessibilityUtils.java2
-rw-r--r--java/src/com/android/inputmethod/accessibility/KeyboardAccessibilityNodeProvider.java2
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java69
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitator.java4
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java12
-rw-r--r--java/src/com/android/inputmethod/latin/PrevWordsInfo.java6
-rw-r--r--java/src/com/android/inputmethod/latin/utils/DistracterFilterUsingSuggestion.java16
-rw-r--r--java/src/com/android/inputmethod/latin/utils/ExecutorUtils.java10
-rw-r--r--java/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutor.java19
-rw-r--r--native/jni/com_android_inputmethod_latin_BinaryDictionary.cpp40
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.cpp22
-rw-r--r--native/jni/src/suggest/core/dictionary/dictionary.h10
-rw-r--r--native/jni/src/suggest/core/policy/dictionary_structure_with_buffer_policy.h6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.cpp12
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/backward/v401/ver4_patricia_trie_policy.h4
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v2/patricia_trie_policy.h6
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp12
-rw-r--r--native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.h4
-rw-r--r--tests/src/com/android/inputmethod/latin/DistracterFilterTest.java29
-rw-r--r--tests/src/com/android/inputmethod/latin/makedict/Ver4DictEncoder.java39
-rw-r--r--tests/src/com/android/inputmethod/latin/utils/PrioritizedSerialExecutorTests.java7
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() {