aboutsummaryrefslogtreecommitdiffstats
path: root/java/src/com/android/inputmethod/latin
diff options
context:
space:
mode:
Diffstat (limited to 'java/src/com/android/inputmethod/latin')
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java107
-rw-r--r--java/src/com/android/inputmethod/latin/DicTraverseSession.java15
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitator.java30
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java32
-rw-r--r--java/src/com/android/inputmethod/latin/InputAttributes.java10
-rw-r--r--java/src/com/android/inputmethod/latin/Suggest.java67
-rw-r--r--java/src/com/android/inputmethod/latin/SuggestedWords.java38
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java122
-rw-r--r--java/src/com/android/inputmethod/latin/makedict/WordProperty.java6
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java5
-rw-r--r--java/src/com/android/inputmethod/latin/settings/DebugSettings.java7
-rw-r--r--java/src/com/android/inputmethod/latin/settings/Settings.java15
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsFragment.java126
-rw-r--r--java/src/com/android/inputmethod/latin/settings/SettingsValues.java3
-rw-r--r--java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java12
-rw-r--r--java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java4
-rw-r--r--java/src/com/android/inputmethod/latin/utils/SuggestionResults.java8
17 files changed, 333 insertions, 274 deletions
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 543f74fc4..335e52fef 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -28,7 +28,6 @@ import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
import com.android.inputmethod.latin.makedict.WordProperty;
-import com.android.inputmethod.latin.settings.NativeSuggestOptions;
import com.android.inputmethod.latin.utils.BinaryDictionaryUtils;
import com.android.inputmethod.latin.utils.FileUtils;
import com.android.inputmethod.latin.utils.JniUtils;
@@ -49,10 +48,6 @@ import java.util.Map;
public final class BinaryDictionary extends Dictionary {
private static final String TAG = BinaryDictionary.class.getSimpleName();
- // Must be equal to MAX_WORD_LENGTH in native/jni/src/defines.h
- private static final int MAX_WORD_LENGTH = Constants.DICTIONARY_MAX_WORD_LENGTH;
- // Must be equal to MAX_RESULTS in native/jni/src/defines.h
- private static final int MAX_RESULTS = 18;
// The cutoff returned by native for auto-commit confidence.
// Must be equal to CONFIDENCE_TO_AUTO_COMMIT in native/jni/src/defines.h
private static final int CONFIDENCE_TO_AUTO_COMMIT = 1000000;
@@ -69,11 +64,12 @@ public final class BinaryDictionary extends Dictionary {
public static final int NOT_A_VALID_TIMESTAMP = -1;
// Format to get unigram flags from native side via getWordPropertyNative().
- private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 4;
+ private static final int FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT = 5;
private static final int FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX = 0;
private static final int FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX = 1;
private static final int FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX = 2;
private static final int FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX = 3;
+ private static final int FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX = 4;
// Format to get probability and historical info from native side via getWordPropertyNative().
public static final int FORMAT_WORD_PROPERTY_OUTPUT_PROBABILITY_INFO_COUNT = 4;
@@ -88,21 +84,10 @@ public final class BinaryDictionary extends Dictionary {
private final Locale mLocale;
private final long mDictSize;
private final String mDictFilePath;
+ private final boolean mUseFullEditDistance;
private final boolean mIsUpdatable;
private boolean mHasUpdated;
- private final int[] mInputCodePoints = new int[MAX_WORD_LENGTH];
- private final int[] mOutputSuggestionCount = new int[1];
- private final int[] mOutputCodePoints = new int[MAX_WORD_LENGTH * MAX_RESULTS];
- private final int[] mSpaceIndices = new int[MAX_RESULTS];
- private final int[] mOutputScores = new int[MAX_RESULTS];
- private final int[] mOutputTypes = new int[MAX_RESULTS];
- // Only one result is ever used
- private final int[] mOutputAutoCommitFirstWordConfidence = new int[1];
- private final float[] mInputOutputLanguageWeight = new float[1];
-
- private final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions();
-
private final SparseArray<DicTraverseSession> mDicTraverseSessions = new SparseArray<>();
// TODO: There should be a way to remove used DicTraverseSession objects from
@@ -136,7 +121,7 @@ public final class BinaryDictionary extends Dictionary {
mDictFilePath = filename;
mIsUpdatable = isUpdatable;
mHasUpdated = false;
- mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
+ mUseFullEditDistance = useFullEditDistance;
loadDictionary(filename, offset, length, isUpdatable);
}
@@ -148,7 +133,6 @@ public final class BinaryDictionary extends Dictionary {
* @param formatVersion the format version of the dictionary
* @param attributeMap the attributes of the dictionary
*/
- @UsedForTesting
public BinaryDictionary(final String filename, final boolean useFullEditDistance,
final Locale locale, final String dictType, final long formatVersion,
final Map<String, String> attributeMap) {
@@ -159,7 +143,7 @@ public final class BinaryDictionary extends Dictionary {
// On memory dictionary is always updatable.
mIsUpdatable = true;
mHasUpdated = false;
- mNativeSuggestOptions.setUseFullEditDistance(useFullEditDistance);
+ mUseFullEditDistance = useFullEditDistance;
final String[] keyArray = new String[attributeMap.size()];
final String[] valueArray = new String[attributeMap.size()];
int index = 0;
@@ -193,10 +177,12 @@ public final class BinaryDictionary extends Dictionary {
private static native int getBigramProbabilityNative(long dict, int[] word0,
boolean isBeginningOfSentence, int[] word1);
private static native void getWordPropertyNative(long dict, int[] word,
- int[] outCodePoints, boolean[] outFlags, int[] outProbabilityInfo,
- ArrayList<int[]> outBigramTargets, ArrayList<int[]> outBigramProbabilityInfo,
- ArrayList<int[]> outShortcutTargets, ArrayList<Integer> outShortcutProbabilities);
- private static native int getNextWordNative(long dict, int token, int[] outCodePoints);
+ boolean isBeginningOfSentence, int[] outCodePoints, boolean[] outFlags,
+ int[] outProbabilityInfo, ArrayList<int[]> outBigramTargets,
+ ArrayList<int[]> outBigramProbabilityInfo, ArrayList<int[]> outShortcutTargets,
+ ArrayList<Integer> outShortcutProbabilities);
+ private static native int getNextWordNative(long dict, int token, int[] outCodePoints,
+ boolean[] outIsBeginningOfSentence);
private static native void getSuggestionsNative(long dict, long proximityInfo,
long traverseSession, int[] xCoordinates, int[] yCoordinates, int[] times,
int[] pointerIds, int[] inputCodePoints, int inputSize, int[] suggestOptions,
@@ -274,8 +260,8 @@ public final class BinaryDictionary extends Dictionary {
if (!isValidDictionary()) {
return null;
}
-
- Arrays.fill(mInputCodePoints, Constants.NOT_A_CODE);
+ final DicTraverseSession session = getTraverseSession(sessionId);
+ Arrays.fill(session.mInputCodePoints, Constants.NOT_A_CODE);
// TODO: toLowerCase in the native code
final int[] prevWordCodePointArray = (null == prevWordsInfo.mPrevWord)
? null : StringUtils.toCodePointArray(prevWordsInfo.mPrevWord);
@@ -284,47 +270,50 @@ public final class BinaryDictionary extends Dictionary {
final int inputSize;
if (!isGesture) {
inputSize = composer.copyCodePointsExceptTrailingSingleQuotesAndReturnCodePointCount(
- mInputCodePoints);
+ session.mInputCodePoints);
if (inputSize < 0) {
return null;
}
} else {
inputSize = inputPointers.getPointerSize();
}
-
- mNativeSuggestOptions.setIsGesture(isGesture);
- mNativeSuggestOptions.setBlockOffensiveWords(blockOffensiveWords);
- mNativeSuggestOptions.setAdditionalFeaturesOptions(additionalFeaturesOptions);
+ session.mNativeSuggestOptions.setUseFullEditDistance(mUseFullEditDistance);
+ session.mNativeSuggestOptions.setIsGesture(isGesture);
+ session.mNativeSuggestOptions.setBlockOffensiveWords(blockOffensiveWords);
+ session.mNativeSuggestOptions.setAdditionalFeaturesOptions(additionalFeaturesOptions);
if (inOutLanguageWeight != null) {
- mInputOutputLanguageWeight[0] = inOutLanguageWeight[0];
+ session.mInputOutputLanguageWeight[0] = inOutLanguageWeight[0];
} else {
- mInputOutputLanguageWeight[0] = Dictionary.NOT_A_LANGUAGE_WEIGHT;
+ session.mInputOutputLanguageWeight[0] = Dictionary.NOT_A_LANGUAGE_WEIGHT;
}
// proximityInfo and/or prevWordForBigrams may not be null.
getSuggestionsNative(mNativeDict, proximityInfo.getNativeProximityInfo(),
getTraverseSession(sessionId).getSession(), inputPointers.getXCoordinates(),
inputPointers.getYCoordinates(), inputPointers.getTimes(),
- inputPointers.getPointerIds(), mInputCodePoints, inputSize,
- mNativeSuggestOptions.getOptions(), prevWordCodePointArray,
- prevWordsInfo.mIsBeginningOfSentence, mOutputSuggestionCount,
- mOutputCodePoints, mOutputScores, mSpaceIndices, mOutputTypes,
- mOutputAutoCommitFirstWordConfidence, mInputOutputLanguageWeight);
+ inputPointers.getPointerIds(), session.mInputCodePoints, inputSize,
+ session.mNativeSuggestOptions.getOptions(), prevWordCodePointArray,
+ prevWordsInfo.mIsBeginningOfSentence, session.mOutputSuggestionCount,
+ session.mOutputCodePoints, session.mOutputScores, session.mSpaceIndices,
+ session.mOutputTypes, session.mOutputAutoCommitFirstWordConfidence,
+ session.mInputOutputLanguageWeight);
if (inOutLanguageWeight != null) {
- inOutLanguageWeight[0] = mInputOutputLanguageWeight[0];
+ inOutLanguageWeight[0] = session.mInputOutputLanguageWeight[0];
}
- final int count = mOutputSuggestionCount[0];
+ final int count = session.mOutputSuggestionCount[0];
final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
for (int j = 0; j < count; ++j) {
- final int start = j * MAX_WORD_LENGTH;
+ final int start = j * Constants.DICTIONARY_MAX_WORD_LENGTH;
int len = 0;
- while (len < MAX_WORD_LENGTH && mOutputCodePoints[start + len] != 0) {
+ while (len < Constants.DICTIONARY_MAX_WORD_LENGTH
+ && session.mOutputCodePoints[start + len] != 0) {
++len;
}
if (len > 0) {
- suggestions.add(new SuggestedWordInfo(new String(mOutputCodePoints, start, len),
- mOutputScores[j], mOutputTypes[j], this /* sourceDict */,
- mSpaceIndices[j] /* indexOfTouchPointOfSecondWord */,
- mOutputAutoCommitFirstWordConfidence[0]));
+ suggestions.add(new SuggestedWordInfo(
+ new String(session.mOutputCodePoints, start, len),
+ session.mOutputScores[j], session.mOutputTypes[j], this /* sourceDict */,
+ session.mSpaceIndices[j] /* indexOfTouchPointOfSecondWord */,
+ session.mOutputAutoCommitFirstWordConfidence[0]));
}
}
return suggestions;
@@ -372,12 +361,12 @@ public final class BinaryDictionary extends Dictionary {
prevWordsInfo.mIsBeginningOfSentence, codePoints1);
}
- public WordProperty getWordProperty(final String word) {
- if (TextUtils.isEmpty(word)) {
+ public WordProperty getWordProperty(final String word, final boolean isBeginningOfSentence) {
+ if (word == null) {
return null;
}
final int[] codePoints = StringUtils.toCodePointArray(word);
- final int[] outCodePoints = new int[MAX_WORD_LENGTH];
+ final int[] outCodePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
final boolean[] outFlags = new boolean[FORMAT_WORD_PROPERTY_OUTPUT_FLAG_COUNT];
final int[] outProbabilityInfo =
new int[FORMAT_WORD_PROPERTY_OUTPUT_PROBABILITY_INFO_COUNT];
@@ -385,14 +374,15 @@ public final class BinaryDictionary extends Dictionary {
final ArrayList<int[]> outBigramProbabilityInfo = new ArrayList<>();
final ArrayList<int[]> outShortcutTargets = new ArrayList<>();
final ArrayList<Integer> outShortcutProbabilities = new ArrayList<>();
- getWordPropertyNative(mNativeDict, codePoints, outCodePoints, outFlags, outProbabilityInfo,
- outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
- outShortcutProbabilities);
+ getWordPropertyNative(mNativeDict, codePoints, isBeginningOfSentence, outCodePoints,
+ outFlags, outProbabilityInfo, outBigramTargets, outBigramProbabilityInfo,
+ outShortcutTargets, outShortcutProbabilities);
return new WordProperty(codePoints,
outFlags[FORMAT_WORD_PROPERTY_IS_NOT_A_WORD_INDEX],
outFlags[FORMAT_WORD_PROPERTY_IS_BLACKLISTED_INDEX],
outFlags[FORMAT_WORD_PROPERTY_HAS_BIGRAMS_INDEX],
- outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX], outProbabilityInfo,
+ outFlags[FORMAT_WORD_PROPERTY_HAS_SHORTCUTS_INDEX],
+ outFlags[FORMAT_WORD_PROPERTY_IS_BEGINNING_OF_SENTENCE_INDEX], outProbabilityInfo,
outBigramTargets, outBigramProbabilityInfo, outShortcutTargets,
outShortcutProbabilities);
}
@@ -412,10 +402,13 @@ public final class BinaryDictionary extends Dictionary {
* If token is 0, this method newly starts iterating the dictionary.
*/
public GetNextWordPropertyResult getNextWordProperty(final int token) {
- final int[] codePoints = new int[MAX_WORD_LENGTH];
- final int nextToken = getNextWordNative(mNativeDict, token, codePoints);
+ final int[] codePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
+ final boolean[] isBeginningOfSentence = new boolean[1];
+ final int nextToken = getNextWordNative(mNativeDict, token, codePoints,
+ isBeginningOfSentence);
final String word = StringUtils.getStringFromNullTerminatedCodePointArray(codePoints);
- return new GetNextWordPropertyResult(getWordProperty(word), nextToken);
+ return new GetNextWordPropertyResult(
+ getWordProperty(word, isBeginningOfSentence[0]), nextToken);
}
// Add a unigram entry to binary dictionary with unigram attributes in native code.
diff --git a/java/src/com/android/inputmethod/latin/DicTraverseSession.java b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
index 8d295adee..8bbf426e5 100644
--- a/java/src/com/android/inputmethod/latin/DicTraverseSession.java
+++ b/java/src/com/android/inputmethod/latin/DicTraverseSession.java
@@ -16,6 +16,7 @@
package com.android.inputmethod.latin;
+import com.android.inputmethod.latin.settings.NativeSuggestOptions;
import com.android.inputmethod.latin.utils.JniUtils;
import java.util.Locale;
@@ -24,6 +25,20 @@ public final class DicTraverseSession {
static {
JniUtils.loadNativeLibrary();
}
+ // Must be equal to MAX_RESULTS in native/jni/src/defines.h
+ private static final int MAX_RESULTS = 18;
+ public final int[] mInputCodePoints = new int[Constants.DICTIONARY_MAX_WORD_LENGTH];
+ public final int[] mOutputSuggestionCount = new int[1];
+ public final int[] mOutputCodePoints =
+ new int[Constants.DICTIONARY_MAX_WORD_LENGTH * MAX_RESULTS];
+ public final int[] mSpaceIndices = new int[MAX_RESULTS];
+ public final int[] mOutputScores = new int[MAX_RESULTS];
+ public final int[] mOutputTypes = new int[MAX_RESULTS];
+ // Only one result is ever used
+ public final int[] mOutputAutoCommitFirstWordConfidence = new int[1];
+ public final float[] mInputOutputLanguageWeight = new float[1];
+
+ public final NativeSuggestOptions mNativeSuggestOptions = new NativeSuggestOptions();
private static native long setDicTraverseSessionNative(String locale, long dictSize);
private static native void initDicTraverseSessionNative(long nativeDicTraverseSession,
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
index 4a28a242a..304c450ab 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java
@@ -468,20 +468,24 @@ public class DictionaryFacilitator {
isValid, timeStampInSeconds, mDistracterFilter);
}
- public void cancelAddingUserHistory(final PrevWordsInfo prevWordsInfo,
- final String committedWord) {
- final ExpandableBinaryDictionary userHistoryDictionary =
- mDictionaries.getSubDict(Dictionary.TYPE_USER_HISTORY);
- if (userHistoryDictionary != null) {
- userHistoryDictionary.removeNgramDynamically(prevWordsInfo, committedWord);
+ private void removeWord(final String dictName, final String word) {
+ final ExpandableBinaryDictionary dictionary = mDictionaries.getSubDict(dictName);
+ if (dictionary != null) {
+ dictionary.removeUnigramEntryDynamically(word);
}
}
+ public void removeWordFromPersonalizedDicts(final String word) {
+ removeWord(Dictionary.TYPE_USER_HISTORY, word);
+ removeWord(Dictionary.TYPE_PERSONALIZATION, word);
+ removeWord(Dictionary.TYPE_CONTEXTUAL, word);
+ }
+
// TODO: Revise the way to fusion suggestion results.
public SuggestionResults getSuggestionResults(final WordComposer composer,
final PrevWordsInfo prevWordsInfo, final ProximityInfo proximityInfo,
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
- final int sessionId, final ArrayList<SuggestedWordInfo> rawSuggestions) {
+ final int sessionId) {
final Dictionaries dictionaries = mDictionaries;
final SuggestionResults suggestionResults =
new SuggestionResults(dictionaries.mLocale, SuggestedWords.MAX_SUGGESTIONS);
@@ -495,21 +499,13 @@ public class DictionaryFacilitator {
languageWeight);
if (null == dictionarySuggestions) continue;
suggestionResults.addAll(dictionarySuggestions);
- if (null != rawSuggestions) {
- rawSuggestions.addAll(dictionarySuggestions);
+ if (null != suggestionResults.mRawSuggestions) {
+ suggestionResults.mRawSuggestions.addAll(dictionarySuggestions);
}
}
return suggestionResults;
}
- public boolean isValidMainDictWord(final String word) {
- final Dictionary mainDict = mDictionaries.getDict(Dictionary.TYPE_MAIN);
- if (TextUtils.isEmpty(word) || mainDict == null) {
- return false;
- }
- return mainDict.isValidWord(word);
- }
-
public boolean isValidWord(final String word, final boolean ignoreCase) {
if (TextUtils.isEmpty(word)) {
return false;
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index b1966bffc..37879cf68 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -122,12 +122,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
return mBinaryDictionary.isValidDictionary();
}
- // TODO: Remove and always enable beginning of sentence prediction. Currently, this is enabled
- // only for ContextualDictionary.
- protected boolean enableBeginningOfSentencePrediction() {
- return false;
- }
-
/**
* Creates a new expandable binary dictionary.
*
@@ -311,6 +305,27 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
/**
+ * Dynamically remove the unigram entry from the dictionary.
+ */
+ public void removeUnigramEntryDynamically(final String word) {
+ reloadDictionaryIfRequired();
+ asyncExecuteTaskWithWriteLock(new Runnable() {
+ @Override
+ public void run() {
+ if (mBinaryDictionary == null) {
+ return;
+ }
+ runGCIfRequiredLocked(true /* mindsBlockByGC */);
+ if (!mBinaryDictionary.removeUnigramEntry(word)) {
+ if (DEBUG) {
+ Log.i(TAG, "Cannot remove unigram entry: " + word);
+ }
+ }
+ }
+ });
+ }
+
+ /**
* Adds n-gram information of a word to the dictionary. May overwrite an existing entry.
*/
public void addNgramEntry(final PrevWordsInfo prevWordsInfo, final String word,
@@ -341,6 +356,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
/**
* Dynamically remove the n-gram entry in the dictionary.
*/
+ @UsedForTesting
public void removeNgramDynamically(final PrevWordsInfo prevWordsInfo, final String word) {
reloadDictionaryIfRequired();
asyncExecuteTaskWithWriteLock(new Runnable() {
@@ -404,10 +420,6 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
if (mBinaryDictionary == null) {
return null;
}
- if (composer.size() == 0 && prevWordsInfo.mIsBeginningOfSentence
- && !enableBeginningOfSentencePrediction()) {
- return null;
- }
final ArrayList<SuggestedWordInfo> suggestions =
mBinaryDictionary.getSuggestions(composer, prevWordsInfo, proximityInfo,
blockOffensiveWords, additionalFeaturesOptions, sessionId,
diff --git a/java/src/com/android/inputmethod/latin/InputAttributes.java b/java/src/com/android/inputmethod/latin/InputAttributes.java
index e1ae3dfe3..ebe436128 100644
--- a/java/src/com/android/inputmethod/latin/InputAttributes.java
+++ b/java/src/com/android/inputmethod/latin/InputAttributes.java
@@ -41,6 +41,7 @@ public final class InputAttributes {
final public boolean mShouldShowSuggestions;
final public boolean mApplicationSpecifiedCompletionOn;
final public boolean mShouldInsertSpacesAutomatically;
+ final public boolean mShouldShowVoiceInputKey;
final private int mInputType;
final private EditorInfo mEditorInfo;
final private String mPackageNameForPrivateImeOptions;
@@ -74,6 +75,7 @@ public final class InputAttributes {
mInputTypeNoAutoCorrect = false;
mApplicationSpecifiedCompletionOn = false;
mShouldInsertSpacesAutomatically = false;
+ mShouldShowVoiceInputKey = false;
return;
}
// inputClass == InputType.TYPE_CLASS_TEXT
@@ -99,6 +101,12 @@ public final class InputAttributes {
mShouldInsertSpacesAutomatically = InputTypeUtils.isAutoSpaceFriendlyType(inputType);
+ final boolean noMicrophone = mIsPasswordField
+ || InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS == variation
+ || InputType.TYPE_TEXT_VARIATION_URI == variation
+ || hasNoMicrophoneKeyOption();
+ mShouldShowVoiceInputKey = !noMicrophone;
+
// If it's a browser edit field and auto correct is not ON explicitly, then
// disable auto correction, but keep suggestions on.
// If NO_SUGGESTIONS is set, don't do prediction.
@@ -119,7 +127,7 @@ public final class InputAttributes {
return editorInfo.inputType == mInputType;
}
- public boolean hasNoMicrophoneKeyOption() {
+ private boolean hasNoMicrophoneKeyOption() {
@SuppressWarnings("deprecation")
final boolean deprecatedNoMicrophone = InputAttributes.inPrivateImeOptions(
null, NO_MICROPHONE_COMPAT, mEditorInfo);
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 670d856e3..9d03e8a43 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -100,30 +100,43 @@ public final class Suggest {
? typedWord.substring(0, typedWord.length() - trailingSingleQuotesCount)
: typedWord;
- final ArrayList<SuggestedWordInfo> rawSuggestions;
- if (ProductionFlag.INCLUDE_RAW_SUGGESTIONS) {
- rawSuggestions = new ArrayList<>();
- } else {
- rawSuggestions = null;
- }
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions, SESSION_TYPING, rawSuggestions);
+ additionalFeaturesOptions, SESSION_TYPING);
+ final boolean isPrediction = !wordComposer.isComposingWord();
+ final boolean shouldMakeSuggestionsAllUpperCase = wordComposer.isAllUpperCase()
+ && !wordComposer.isResumed();
final boolean isOnlyFirstCharCapitalized =
wordComposer.isOrWillBeOnlyFirstCharCapitalized();
+
+ final ArrayList<SuggestedWordInfo> suggestionsContainer =
+ new ArrayList<>(suggestionResults);
+ final int suggestionsCount = suggestionsContainer.size();
+ if (isOnlyFirstCharCapitalized || shouldMakeSuggestionsAllUpperCase
+ || 0 != trailingSingleQuotesCount) {
+ for (int i = 0; i < suggestionsCount; ++i) {
+ final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
+ final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
+ wordInfo, suggestionResults.mLocale, shouldMakeSuggestionsAllUpperCase,
+ isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
+ suggestionsContainer.set(i, transformedWordInfo);
+ }
+ }
+ SuggestedWordInfo.removeDups(typedWord, suggestionsContainer);
+
// If resumed, then we don't want to upcase everything: resuming on a fully-capitalized
// words is rarely done to switch to another fully-capitalized word, but usually to a
// normal, non-capitalized suggestion.
- final boolean isAllUpperCase = wordComposer.isAllUpperCase() && !wordComposer.isResumed();
final String firstSuggestion;
final String whitelistedWord;
if (suggestionResults.isEmpty()) {
whitelistedWord = firstSuggestion = null;
} else {
final SuggestedWordInfo firstSuggestedWordInfo = getTransformedSuggestedWordInfo(
- suggestionResults.first(), suggestionResults.mLocale, isAllUpperCase,
- isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
+ suggestionResults.first(), suggestionResults.mLocale,
+ shouldMakeSuggestionsAllUpperCase, isOnlyFirstCharCapitalized,
+ trailingSingleQuotesCount);
firstSuggestion = firstSuggestedWordInfo.mWord;
if (!firstSuggestedWordInfo.isKindOf(SuggestedWordInfo.KIND_WHITELIST)) {
whitelistedWord = null;
@@ -132,8 +145,6 @@ public final class Suggest {
}
}
- final boolean isPrediction = !wordComposer.isComposingWord();
-
// We allow auto-correction if we have a whitelisted word, or if the word is not a valid
// word of more than 1 char, except if the first suggestion is the same as the typed string
// because in this case if it's strong enough to auto-correct that will mistakenly designate
@@ -171,19 +182,6 @@ public final class Suggest {
suggestionResults.first(), consideredWord, mAutoCorrectionThreshold);
}
- final ArrayList<SuggestedWordInfo> suggestionsContainer =
- new ArrayList<>(suggestionResults);
- final int suggestionsCount = suggestionsContainer.size();
- if (isOnlyFirstCharCapitalized || isAllUpperCase || 0 != trailingSingleQuotesCount) {
- for (int i = 0; i < suggestionsCount; ++i) {
- final SuggestedWordInfo wordInfo = suggestionsContainer.get(i);
- final SuggestedWordInfo transformedWordInfo = getTransformedSuggestedWordInfo(
- wordInfo, suggestionResults.mLocale, isAllUpperCase,
- isOnlyFirstCharCapitalized, trailingSingleQuotesCount);
- suggestionsContainer.set(i, transformedWordInfo);
- }
- }
-
if (!TextUtils.isEmpty(typedWord)) {
suggestionsContainer.add(0, new SuggestedWordInfo(typedWord,
SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED,
@@ -191,7 +189,6 @@ public final class Suggest {
SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
}
- SuggestedWordInfo.removeDups(suggestionsContainer);
final ArrayList<SuggestedWordInfo> suggestionsList;
if (DBG && !suggestionsContainer.isEmpty()) {
@@ -200,12 +197,13 @@ public final class Suggest {
suggestionsList = suggestionsContainer;
}
- callback.onGetSuggestedWords(new SuggestedWords(suggestionsList, rawSuggestions,
+ callback.onGetSuggestedWords(new SuggestedWords(suggestionsList,
+ suggestionResults.mRawSuggestions,
// TODO: this first argument is lying. If this is a whitelisted word which is an
// actual word, it says typedWordValid = false, which looks wrong. We should either
// rename the attribute or change the value.
!isPrediction && !allowsToBeAutoCorrected /* typedWordValid */,
- hasAutoCorrection, /* willAutoCorrect */
+ hasAutoCorrection /* willAutoCorrect */,
false /* isObsoleteSuggestions */, isPrediction, sequenceNumber));
}
@@ -216,15 +214,9 @@ public final class Suggest {
final boolean blockOffensiveWords, final int[] additionalFeaturesOptions,
final int sessionId, final int sequenceNumber,
final OnGetSuggestedWordsCallback callback) {
- final ArrayList<SuggestedWordInfo> rawSuggestions;
- if (ProductionFlag.INCLUDE_RAW_SUGGESTIONS) {
- rawSuggestions = new ArrayList<>();
- } else {
- rawSuggestions = null;
- }
final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults(
wordComposer, prevWordsInfo, proximityInfo, blockOffensiveWords,
- additionalFeaturesOptions, sessionId, rawSuggestions);
+ additionalFeaturesOptions, sessionId);
final ArrayList<SuggestedWordInfo> suggestionsContainer =
new ArrayList<>(suggestionResults);
final int suggestionsCount = suggestionsContainer.size();
@@ -245,7 +237,7 @@ public final class Suggest {
final SuggestedWordInfo rejected = suggestionsContainer.remove(0);
suggestionsContainer.add(1, rejected);
}
- SuggestedWordInfo.removeDups(suggestionsContainer);
+ SuggestedWordInfo.removeDups(null /* typedWord */, suggestionsContainer);
// For some reason some suggestions with MIN_VALUE are making their way here.
// TODO: Find a more robust way to detect distractors.
@@ -257,7 +249,8 @@ public final class Suggest {
// In the batch input mode, the most relevant suggested word should act as a "typed word"
// (typedWordValid=true), not as an "auto correct word" (willAutoCorrect=false).
- callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer, rawSuggestions,
+ callback.onGetSuggestedWords(new SuggestedWords(suggestionsContainer,
+ suggestionResults.mRawSuggestions,
true /* typedWordValid */,
false /* willAutoCorrect */,
false /* isObsoleteSuggestions */,
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 72461e17a..f22af7991 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -316,10 +316,6 @@ public class SuggestedWords {
return mDebugString;
}
- public int codePointCount() {
- return mCodePointCount;
- }
-
public int codePointAt(int i) {
return mWord.codePointAt(i);
}
@@ -333,23 +329,29 @@ public class SuggestedWords {
}
}
- // TODO: Consolidate this method and StringUtils.removeDupes() in the future.
- public static void removeDups(ArrayList<SuggestedWordInfo> candidates) {
- if (candidates.size() <= 1) {
+ // This will always remove the higher index if a duplicate is found.
+ public static void removeDups(final String typedWord,
+ ArrayList<SuggestedWordInfo> candidates) {
+ if (candidates.isEmpty()) {
return;
}
- int i = 1;
- while (i < candidates.size()) {
- final SuggestedWordInfo cur = candidates.get(i);
- for (int j = 0; j < i; ++j) {
- final SuggestedWordInfo previous = candidates.get(j);
- if (cur.mWord.equals(previous.mWord)) {
- candidates.remove(cur.mScore < previous.mScore ? i : j);
- --i;
- break;
- }
+ if (!TextUtils.isEmpty(typedWord)) {
+ removeSuggestedWordInfoFrom(typedWord, candidates, -1 /* startIndexExclusive */);
+ }
+ for (int i = 0; i < candidates.size(); ++i) {
+ removeSuggestedWordInfoFrom(candidates.get(i).mWord, candidates,
+ i /* startIndexExclusive */);
+ }
+ }
+
+ private static void removeSuggestedWordInfoFrom(final String word,
+ final ArrayList<SuggestedWordInfo> candidates, final int startIndexExclusive) {
+ for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) {
+ final SuggestedWordInfo previous = candidates.get(i);
+ if (word.equals(previous.mWord)) {
+ candidates.remove(i);
+ --i;
}
- ++i;
}
}
}
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index de95b9787..4d3f5b50b 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -728,14 +728,13 @@ public final class InputLogic {
mConnection.setComposingText(getTextWithUnderline(
mWordComposer.getTypedWord()), 1);
} else {
- final boolean swapWeakSpace = maybeStripSpace(inputTransaction,
- inputTransaction.mEvent.isSuggestionStripPress());
+ final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
+ inputTransaction, inputTransaction.mEvent.isSuggestionStripPress());
- sendKeyCodePoint(settingsValues, codePoint);
-
- if (swapWeakSpace) {
- swapSwapperAndSpace(inputTransaction);
+ if (swapWeakSpace && trySwapSwapperAndSpace(inputTransaction)) {
mSpaceState = SpaceState.WEAK;
+ } else {
+ sendKeyCodePoint(settingsValues, codePoint);
}
// In case the "add to dictionary" hint was still displayed.
mSuggestionStripViewAccessor.dismissAddToDictionaryHint();
@@ -780,7 +779,8 @@ public final class InputLogic {
}
}
- final boolean swapWeakSpace = maybeStripSpace(inputTransaction, isFromSuggestionStrip);
+ final boolean swapWeakSpace = tryStripSpaceAndReturnWhetherShouldSwapInstead(
+ inputTransaction, isFromSuggestionStrip);
final boolean isInsideDoubleQuoteOrAfterDigit = Constants.CODE_DOUBLE_QUOTE == codePoint
&& mConnection.isInsideDoubleQuoteOrAfterDigit();
@@ -804,16 +804,14 @@ public final class InputLogic {
promotePhantomSpace(settingsValues);
}
- if (!shouldAvoidSendingCode) {
- sendKeyCodePoint(settingsValues, codePoint);
- }
-
- if (Constants.CODE_SPACE == codePoint) {
- if (maybeDoubleSpacePeriod(inputTransaction)) {
- inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
- inputTransaction.setRequiresUpdateSuggestions();
- mSpaceState = SpaceState.DOUBLE;
- } else if (!mSuggestedWords.isPunctuationSuggestions()) {
+ if (tryPerformDoubleSpacePeriod(inputTransaction)) {
+ mSpaceState = SpaceState.DOUBLE;
+ inputTransaction.setRequiresUpdateSuggestions();
+ } else if (swapWeakSpace && trySwapSwapperAndSpace(inputTransaction)) {
+ mSpaceState = SpaceState.SWAP_PUNCTUATION;
+ mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
+ } else if (Constants.CODE_SPACE == codePoint) {
+ if (!mSuggestedWords.isPunctuationSuggestions()) {
mSpaceState = SpaceState.WEAK;
}
@@ -821,11 +819,12 @@ public final class InputLogic {
if (wasComposingWord || mSuggestedWords.isEmpty()) {
inputTransaction.setRequiresUpdateSuggestions();
}
+
+ if (!shouldAvoidSendingCode) {
+ sendKeyCodePoint(settingsValues, codePoint);
+ }
} else {
- if (swapWeakSpace) {
- swapSwapperAndSpace(inputTransaction);
- mSpaceState = SpaceState.SWAP_PUNCTUATION;
- } else if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
+ if ((SpaceState.PHANTOM == inputTransaction.mSpaceState
&& settingsValues.isUsuallyFollowedBySpace(codePoint))
|| (Constants.CODE_DOUBLE_QUOTE == codePoint
&& isInsideDoubleQuoteOrAfterDigit)) {
@@ -843,6 +842,8 @@ public final class InputLogic {
mSpaceState = SpaceState.PHANTOM;
}
+ sendKeyCodePoint(settingsValues, codePoint);
+
// Set punctuation right away. onUpdateSelection will fire but tests whether it is
// already displayed or not, so it's okay.
mSuggestionStripViewAccessor.setNeutralSuggestionStrip();
@@ -884,6 +885,9 @@ public final class InputLogic {
final String rejectedSuggestion = mWordComposer.getTypedWord();
mWordComposer.reset();
mWordComposer.setRejectedBatchModeSuggestion(rejectedSuggestion);
+ if (!TextUtils.isEmpty(rejectedSuggestion)) {
+ mDictionaryFacilitator.removeWordFromPersonalizedDicts(rejectedSuggestion);
+ }
} else {
mWordComposer.processEvent(inputTransaction.mEvent);
}
@@ -1005,16 +1009,18 @@ public final class InputLogic {
* This method will check that there are two characters before the cursor and that the first
* one is a space before it does the actual swapping.
* @param inputTransaction The transaction in progress.
+ * @return true if the swap has been performed, false if it was prevented by preliminary checks.
*/
- private void swapSwapperAndSpace(final InputTransaction inputTransaction) {
- final CharSequence lastTwo = mConnection.getTextBeforeCursor(2, 0);
- // It is guaranteed lastTwo.charAt(1) is a swapper - else this method is not called.
- if (lastTwo != null && lastTwo.length() == 2 && lastTwo.charAt(0) == Constants.CODE_SPACE) {
- mConnection.deleteSurroundingText(2, 0);
- final String text = lastTwo.charAt(1) + " ";
- mConnection.commitText(text, 1);
- inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ private boolean trySwapSwapperAndSpace(final InputTransaction inputTransaction) {
+ final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
+ if (Constants.CODE_SPACE != codePointBeforeCursor) {
+ return false;
}
+ mConnection.deleteSurroundingText(1, 0);
+ final String text = inputTransaction.mEvent.getTextToCommit() + " ";
+ mConnection.commitText(text, 1);
+ inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ return true;
}
/*
@@ -1023,8 +1029,8 @@ public final class InputLogic {
* @param isFromSuggestionStrip Whether this code point is coming from the suggestion strip.
* @return whether we should swap the space instead of removing it.
*/
- private boolean maybeStripSpace(final InputTransaction inputTransaction,
- final boolean isFromSuggestionStrip) {
+ private boolean tryStripSpaceAndReturnWhetherShouldSwapInstead(
+ final InputTransaction inputTransaction, final boolean isFromSuggestionStrip) {
final int codePoint = inputTransaction.mEvent.mCodePoint;
if (Constants.CODE_ENTER == codePoint &&
SpaceState.SWAP_PUNCTUATION == inputTransaction.mSpaceState) {
@@ -1065,37 +1071,42 @@ public final class InputLogic {
* period-space sequence of characters. This typically happens when the user presses space
* twice in a row quickly.
* This method will check that the double-space-to-period is active in settings, that the
- * two spaces have been input close enough together, and that the previous character allows
- * for the transformation to take place. If all of these conditions are fulfilled, this
- * method applies the transformation and returns true. Otherwise, it does nothing and
- * returns false.
+ * two spaces have been input close enough together, that the typed character is a space
+ * and that the previous character allows for the transformation to take place. If all of
+ * these conditions are fulfilled, this method applies the transformation and returns true.
+ * Otherwise, it does nothing and returns false.
*
* @param inputTransaction The transaction in progress.
* @return true if we applied the double-space-to-period transformation, false otherwise.
*/
- private boolean maybeDoubleSpacePeriod(final InputTransaction inputTransaction) {
- if (!inputTransaction.mSettingsValues.mUseDoubleSpacePeriod) return false;
- if (!isDoubleSpacePeriodCountdownActive(inputTransaction)) return false;
- // We only do this when we see two spaces and an accepted code point before the cursor.
- // The code point may be a surrogate pair but the two spaces may not, so we need 4 chars.
- final CharSequence lastThree = mConnection.getTextBeforeCursor(4, 0);
- if (null == lastThree) return false;
- final int length = lastThree.length();
- if (length < 3) return false;
- if (lastThree.charAt(length - 1) != Constants.CODE_SPACE) return false;
- if (lastThree.charAt(length - 2) != Constants.CODE_SPACE) return false;
- // We know there are spaces in pos -1 and -2, and we have at least three chars.
- // If we have only three chars, isSurrogatePairs can't return true as charAt(1) is a space,
- // so this is fine.
+ private boolean tryPerformDoubleSpacePeriod(final InputTransaction inputTransaction) {
+ // Check the setting, the typed character and the countdown. If any of the conditions is
+ // not fulfilled, return false.
+ if (!inputTransaction.mSettingsValues.mUseDoubleSpacePeriod
+ || Constants.CODE_SPACE != inputTransaction.mEvent.mCodePoint
+ || !isDoubleSpacePeriodCountdownActive(inputTransaction)) {
+ return false;
+ }
+ // We only do this when we see one space and an accepted code point before the cursor.
+ // The code point may be a surrogate pair but the space may not, so we need 3 chars.
+ final CharSequence lastTwo = mConnection.getTextBeforeCursor(3, 0);
+ if (null == lastTwo) return false;
+ final int length = lastTwo.length();
+ if (length < 2) return false;
+ if (lastTwo.charAt(length - 1) != Constants.CODE_SPACE) return false;
+ // We know there is a space in pos -1, and we have at least two chars. If we have only two
+ // chars, isSurrogatePairs can't return true as charAt(1) is a space, so this is fine.
final int firstCodePoint =
- Character.isSurrogatePair(lastThree.charAt(0), lastThree.charAt(1)) ?
- Character.codePointAt(lastThree, 0) : lastThree.charAt(length - 3);
+ Character.isSurrogatePair(lastTwo.charAt(0), lastTwo.charAt(1)) ?
+ Character.codePointAt(lastTwo, length - 3) : lastTwo.charAt(length - 2);
if (canBeFollowedByDoubleSpacePeriod(firstCodePoint)) {
cancelDoubleSpacePeriodCountdown();
- mConnection.deleteSurroundingText(2, 0);
+ mConnection.deleteSurroundingText(1, 0);
final String textToInsert = inputTransaction.mSettingsValues.mSpacingAndPunctuations
.mSentenceSeparatorAndSpace;
mConnection.commitText(textToInsert, 1);
+ inputTransaction.requireShiftUpdate(InputTransaction.SHIFT_UPDATE_NOW);
+ inputTransaction.setRequiresUpdateSuggestions();
return true;
}
return false;
@@ -1187,6 +1198,8 @@ public final class InputLogic {
Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not "
+ "requested!");
}
+ // Clear the suggestions strip.
+ mSuggestionStripViewAccessor.showSuggestionStrip(SuggestedWords.EMPTY);
return;
}
@@ -1363,7 +1376,6 @@ public final class InputLogic {
* @param inputTransaction The transaction in progress.
*/
private void revertCommit(final InputTransaction inputTransaction) {
- final PrevWordsInfo prevWordsInfo = mLastComposedWord.mPrevWordsInfo;
final CharSequence originallyTypedWord = mLastComposedWord.mTypedWord;
final CharSequence committedWord = mLastComposedWord.mCommittedWord;
final String committedWordString = committedWord.toString();
@@ -1385,8 +1397,8 @@ public final class InputLogic {
}
}
mConnection.deleteSurroundingText(deleteLength, 0);
- if (!TextUtils.isEmpty(prevWordsInfo.mPrevWord) && !TextUtils.isEmpty(committedWord)) {
- mDictionaryFacilitator.cancelAddingUserHistory(prevWordsInfo, committedWordString);
+ if (!TextUtils.isEmpty(committedWord)) {
+ mDictionaryFacilitator.removeWordFromPersonalizedDicts(committedWordString);
}
final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString;
final SpannableString textToCommit = new SpannableString(stringToCommit);
diff --git a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
index 31cb59756..cd78e2235 100644
--- a/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
+++ b/java/src/com/android/inputmethod/latin/makedict/WordProperty.java
@@ -70,8 +70,8 @@ public final class WordProperty implements Comparable<WordProperty> {
// Construct word property using information from native code.
// This represents invalid word when the probability is BinaryDictionary.NOT_A_PROBABILITY.
public WordProperty(final int[] codePoints, final boolean isNotAWord,
- final boolean isBlacklisted, final boolean hasBigram,
- final boolean hasShortcuts, final int[] probabilityInfo,
+ final boolean isBlacklisted, final boolean hasBigram, final boolean hasShortcuts,
+ final boolean isBeginningOfSentence, final int[] probabilityInfo,
final ArrayList<int[]> bigramTargets, final ArrayList<int[]> bigramProbabilityInfo,
final ArrayList<int[]> shortcutTargets,
final ArrayList<Integer> shortcutProbabilities) {
@@ -79,7 +79,7 @@ public final class WordProperty implements Comparable<WordProperty> {
mProbabilityInfo = createProbabilityInfoFromArray(probabilityInfo);
mShortcutTargets = new ArrayList<>();
mBigrams = new ArrayList<>();
- mIsBeginningOfSentence = false;
+ mIsBeginningOfSentence = isBeginningOfSentence;
mIsNotAWord = isNotAWord;
mIsBlacklistEntry = isBlacklisted;
mHasShortcuts = hasShortcuts;
diff --git a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
index a96018fe9..ac55b9333 100644
--- a/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/ContextualDictionary.java
@@ -43,11 +43,6 @@ public class ContextualDictionary extends ExpandableBinaryDictionary {
}
@Override
- protected boolean enableBeginningOfSentencePrediction() {
- return true;
- }
-
- @Override
public boolean isValidWord(final String word) {
// Strings out of this dictionary should not be considered existing words.
return false;
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index 845ddb377..c17e86892 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -21,14 +21,13 @@ import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Process;
-import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceFragment;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
+import android.preference.TwoStatePreference;
-import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.DictionaryDumpBroadcastReceiver;
import com.android.inputmethod.latin.DictionaryFacilitator;
import com.android.inputmethod.latin.R;
@@ -57,7 +56,7 @@ public final class DebugSettings extends PreferenceFragment
public static final String PREF_KEY_LONGPRESS_TIMEOUT = "pref_key_longpress_timeout";
private boolean mServiceNeedsRestart = false;
- private CheckBoxPreference mDebugMode;
+ private TwoStatePreference mDebugMode;
@Override
public void onCreate(Bundle icicle) {
@@ -107,7 +106,7 @@ public final class DebugSettings extends PreferenceFragment
res, R.fraction.config_key_preview_dismiss_end_scale));
mServiceNeedsRestart = false;
- mDebugMode = (CheckBoxPreference) findPreference(PREF_DEBUG_MODE);
+ mDebugMode = (TwoStatePreference) findPreference(PREF_DEBUG_MODE);
updateDebugMode();
}
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index 235847799..fb1a210bb 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -39,8 +39,14 @@ import java.util.concurrent.locks.ReentrantLock;
public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = Settings.class.getSimpleName();
+ // Settings screens
+ public static final String SCREEN_INPUT = "screen_input";
+ public static final String SCREEN_MULTI_LINGUAL = "screen_multi_lingual";
+ public static final String SCREEN_GESTURE = "screen_gesture";
+ public static final String SCREEN_CORRECTION = "screen_correction";
+ public static final String SCREEN_ADVANCED = "screen_advanced";
+ public static final String SCREEN_DEBUG = "screen_debug";
// In the same order as xml/prefs.xml
- public static final String PREF_GENERAL_SETTINGS = "general_settings";
public static final String PREF_AUTO_CAP = "auto_cap";
public static final String PREF_VIBRATE_ON = "vibrate_on";
public static final String PREF_SOUND_ON = "sound_on";
@@ -48,13 +54,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
// PREF_VOICE_MODE_OBSOLETE is obsolete. Use PREF_VOICE_INPUT_KEY instead.
public static final String PREF_VOICE_MODE_OBSOLETE = "voice_mode";
public static final String PREF_VOICE_INPUT_KEY = "pref_voice_input_key";
- public static final String PREF_CORRECTION_SETTINGS = "correction_settings";
public static final String PREF_EDIT_PERSONAL_DICTIONARY = "edit_personal_dictionary";
public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
- public static final String PREF_MISC_SETTINGS = "misc_settings";
- public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
public static final String PREF_KEY_USE_PERSONALIZED_DICTS = "pref_key_use_personalized_dicts";
public static final String PREF_KEY_USE_DOUBLE_SPACE_PERIOD =
@@ -75,7 +78,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
"pref_key_preview_popup_dismiss_delay";
public static final String PREF_BIGRAM_PREDICTIONS = "next_word_prediction";
- public static final String PREF_GESTURE_SETTINGS = "gesture_typing_settings";
public static final String PREF_GESTURE_INPUT = "gesture_input";
public static final String PREF_VIBRATION_DURATION_SETTINGS =
"pref_vibration_duration_settings";
@@ -89,7 +91,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
public static final String PREF_INPUT_LANGUAGE = "input_language";
public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
- public static final String PREF_DEBUG_SETTINGS = "debug_settings";
public static final String PREF_KEY_IS_INTERNAL = "pref_key_is_internal";
public static final String PREF_ENABLE_METRICS_LOGGING = "pref_enable_metrics_logging";
@@ -105,8 +106,6 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang
"pref_last_used_personalization_dict_wiped_time";
private static final String PREF_CORPUS_HANDLES_FOR_PERSONALIZATION =
"pref_corpus_handles_for_personalization";
- public static final String PREF_SEND_FEEDBACK = "send_feedback";
- public static final String PREF_ABOUT_KEYBOARD = "about_keyboard";
// Emoji
public static final String PREF_EMOJI_RECENT_KEYS = "emoji_recent_keys";
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
index 5eb0377c7..689f878be 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsFragment.java
@@ -27,13 +27,15 @@ import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
-import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
-import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceGroup;
import android.preference.PreferenceScreen;
+import android.preference.TwoStatePreference;
import android.util.Log;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
import android.view.inputmethod.InputMethodSubtype;
import com.android.inputmethod.dictionarypack.DictionarySettingsActivity;
@@ -61,6 +63,10 @@ public final class SettingsFragment extends InputMethodSettingsFragment
DBG_USE_INTERNAL_PERSONAL_DICTIONARY_SETTINGS
|| Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2;
+ private static final int NO_MENU_GROUP = Menu.NONE; // We don't care about menu grouping.
+ private static final int MENU_FEEDBACK = Menu.FIRST; // The first menu item id and order.
+ private static final int MENU_ABOUT = Menu.FIRST + 1; // The second menu item id and order.
+
private void setPreferenceEnabled(final String preferenceKey, final boolean enabled) {
final Preference preference = findPreference(preferenceKey);
if (preference != null) {
@@ -93,6 +99,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
@Override
public void onCreate(final Bundle icicle) {
super.onCreate(icicle);
+ setHasOptionsMenu(true);
setInputMethodSettingsCategoryTitle(R.string.language_selection_title);
setSubtypeEnablerTitle(R.string.select_language);
addPreferencesFromResource(R.xml.prefs);
@@ -117,66 +124,48 @@ public final class SettingsFragment extends InputMethodSettingsFragment
ensureConsistencyOfAutoCorrectionSettings();
- final PreferenceGroup generalSettings =
- (PreferenceGroup) findPreference(Settings.PREF_GENERAL_SETTINGS);
- final PreferenceGroup miscSettings =
- (PreferenceGroup) findPreference(Settings.PREF_MISC_SETTINGS);
-
- final Preference debugSettings = findPreference(Settings.PREF_DEBUG_SETTINGS);
- if (debugSettings != null) {
- if (Settings.isInternal(prefs)) {
- final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
- debugSettingsIntent.setClassName(
- context.getPackageName(), DebugSettingsActivity.class.getName());
- debugSettings.setIntent(debugSettingsIntent);
- } else {
- miscSettings.removePreference(debugSettings);
- }
- }
-
- final Preference feedbackSettings = findPreference(Settings.PREF_SEND_FEEDBACK);
- final Preference aboutSettings = findPreference(Settings.PREF_ABOUT_KEYBOARD);
- if (feedbackSettings != null) {
- if (FeedbackUtils.isFeedbackFormSupported()) {
- feedbackSettings.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(final Preference pref) {
- FeedbackUtils.showFeedbackForm(getActivity());
- return true;
- }
- });
- aboutSettings.setTitle(FeedbackUtils.getAboutKeyboardTitleResId());
- aboutSettings.setIntent(FeedbackUtils.getAboutKeyboardIntent(getActivity()));
- } else {
- miscSettings.removePreference(feedbackSettings);
- miscSettings.removePreference(aboutSettings);
- }
+ final PreferenceScreen inputScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_INPUT);
+ final PreferenceScreen multiLingualScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_MULTI_LINGUAL);
+ final PreferenceScreen gestureScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_GESTURE);
+ final PreferenceScreen correctionScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_CORRECTION);
+ final PreferenceScreen advancedScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_ADVANCED);
+ final PreferenceScreen debugScreen =
+ (PreferenceScreen) findPreference(Settings.SCREEN_DEBUG);
+
+ if (Settings.isInternal(prefs)) {
+ final Intent debugSettingsIntent = new Intent(Intent.ACTION_MAIN);
+ debugSettingsIntent.setClassName(
+ context.getPackageName(), DebugSettingsActivity.class.getName());
+ debugScreen.setIntent(debugSettingsIntent);
+ } else {
+ advancedScreen.removePreference(debugScreen);
}
final boolean showVoiceKeyOption = res.getBoolean(
R.bool.config_enable_show_voice_key_option);
if (!showVoiceKeyOption) {
- removePreference(Settings.PREF_VOICE_INPUT_KEY, generalSettings);
+ removePreference(Settings.PREF_VOICE_INPUT_KEY, inputScreen);
}
- final PreferenceGroup advancedSettings =
- (PreferenceGroup) findPreference(Settings.PREF_ADVANCED_SETTINGS);
if (!AudioAndHapticFeedbackManager.getInstance().hasVibrator()) {
- removePreference(Settings.PREF_VIBRATE_ON, generalSettings);
- removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedSettings);
+ removePreference(Settings.PREF_VIBRATE_ON, inputScreen);
+ removePreference(Settings.PREF_VIBRATION_DURATION_SETTINGS, advancedScreen);
}
if (!Settings.ENABLE_SHOW_LANGUAGE_SWITCH_KEY_SETTINGS) {
+ removePreference(Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, multiLingualScreen);
removePreference(
- Settings.PREF_SHOW_LANGUAGE_SWITCH_KEY, advancedSettings);
- removePreference(
- Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, advancedSettings);
+ Settings.PREF_INCLUDE_OTHER_IMES_IN_LANGUAGE_SWITCH_LIST, multiLingualScreen);
}
-
// TODO: consolidate key preview dismiss delay with the key preview animation parameters.
if (!Settings.readFromBuildConfigIfToShowKeyPreviewPopupOption(res)) {
- removePreference(Settings.PREF_POPUP_ON, generalSettings);
- removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedSettings);
+ removePreference(Settings.PREF_POPUP_ON, inputScreen);
+ removePreference(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY, advancedScreen);
} else {
// TODO: Cleanup this setup.
final ListPreference keyPreviewPopupDismissDelay =
@@ -199,18 +188,16 @@ public final class SettingsFragment extends InputMethodSettingsFragment
}
if (!res.getBoolean(R.bool.config_setup_wizard_available)) {
- removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON, advancedSettings);
+ removePreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON, advancedScreen);
}
- final PreferenceGroup textCorrectionGroup =
- (PreferenceGroup) findPreference(Settings.PREF_CORRECTION_SETTINGS);
final PreferenceScreen dictionaryLink =
(PreferenceScreen) findPreference(Settings.PREF_CONFIGURE_DICTIONARIES_KEY);
final Intent intent = dictionaryLink.getIntent();
intent.setClassName(context.getPackageName(), DictionarySettingsActivity.class.getName());
final int number = context.getPackageManager().queryIntentActivities(intent, 0).size();
if (0 >= number) {
- textCorrectionGroup.removePreference(dictionaryLink);
+ correctionScreen.removePreference(dictionaryLink);
}
if (ProductionFlag.IS_METRICS_LOGGING_SUPPORTED) {
@@ -224,7 +211,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
enableMetricsLogging.setTitle(enableMetricsLoggingTitle);
}
} else {
- removePreference(Settings.PREF_ENABLE_METRICS_LOGGING, textCorrectionGroup);
+ removePreference(Settings.PREF_ENABLE_METRICS_LOGGING, advancedScreen);
}
final Preference editPersonalDictionary =
@@ -238,7 +225,7 @@ public final class SettingsFragment extends InputMethodSettingsFragment
}
if (!Settings.readFromBuildConfigIfGestureInputEnabled(res)) {
- removePreference(Settings.PREF_GESTURE_SETTINGS, getPreferenceScreen());
+ getPreferenceScreen().removePreference(gestureScreen);
}
AdditionalFeaturesSettingUtils.addAdditionalFeaturesPreferences(context, this);
@@ -261,8 +248,8 @@ public final class SettingsFragment extends InputMethodSettingsFragment
voiceInputKeyOption.setSummary(isShortcutImeEnabled ? null
: res.getText(R.string.voice_input_disabled_summary));
}
- final CheckBoxPreference showSetupWizardIcon =
- (CheckBoxPreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
+ final TwoStatePreference showSetupWizardIcon =
+ (TwoStatePreference)findPreference(Settings.PREF_SHOW_SETUP_WIZARD_ICON);
if (showSetupWizardIcon != null) {
showSetupWizardIcon.setChecked(Settings.readShowSetupWizardIcon(prefs, getActivity()));
}
@@ -476,4 +463,33 @@ public final class SettingsFragment extends InputMethodSettingsFragment
userDictionaryPreference.setFragment(UserDictionaryList.class.getName());
}
}
+
+ @Override
+ public void onCreateOptionsMenu(final Menu menu, final MenuInflater inflater) {
+ if (FeedbackUtils.isFeedbackFormSupported()) {
+ menu.add(NO_MENU_GROUP, MENU_FEEDBACK /* itemId */, MENU_FEEDBACK /* order */,
+ R.string.send_feedback);
+ }
+ final int aboutResId = FeedbackUtils.getAboutKeyboardTitleResId();
+ if (aboutResId != 0) {
+ menu.add(NO_MENU_GROUP, MENU_ABOUT /* itemId */, MENU_ABOUT /* order */, aboutResId);
+ }
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(final MenuItem item) {
+ final int itemId = item.getItemId();
+ if (itemId == MENU_FEEDBACK) {
+ FeedbackUtils.showFeedbackForm(getActivity());
+ return true;
+ }
+ if (itemId == MENU_ABOUT) {
+ final Intent aboutIntent = FeedbackUtils.getAboutKeyboardIntent(getActivity());
+ if (aboutIntent != null) {
+ startActivity(aboutIntent);
+ return true;
+ }
+ }
+ return super.onOptionsItemSelected(item);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 44104019b..8de5fed07 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -125,8 +125,7 @@ public final class SettingsValues {
mSlidingKeyInputPreviewEnabled = prefs.getBoolean(
DebugSettings.PREF_SLIDING_KEY_INPUT_PREVIEW, true);
mShowsVoiceInputKey = needsToShowVoiceInputKey(prefs, res)
- && !mInputAttributes.mIsPasswordField
- && !mInputAttributes.hasNoMicrophoneKeyOption()
+ && mInputAttributes.mShouldShowVoiceInputKey
&& SubtypeSwitcher.getInstance().isShortcutImeEnabled();
final String autoCorrectionThresholdRawValue = prefs.getString(
Settings.PREF_AUTO_CORRECTION_THRESHOLD,
diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
index 19b48f081..ad5aad747 100644
--- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
+++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java
@@ -44,10 +44,12 @@ import android.view.ViewGroup;
import android.widget.LinearLayout;
import android.widget.TextView;
+import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.latin.LatinImeLogger;
import com.android.inputmethod.latin.PunctuationSuggestions;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SuggestedWords;
+import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.utils.AutoCorrectionUtils;
import com.android.inputmethod.latin.utils.ResourceUtils;
import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
@@ -249,8 +251,8 @@ final class SuggestionStripLayoutHelper {
final int positionInStrip =
getPositionInSuggestionStrip(indexInSuggestedWords, suggestedWords);
// Use identity for strings, not #equals : it's the typed word if it's the same object
- final boolean isTypedWord =
- suggestedWords.getWord(indexInSuggestedWords) == suggestedWords.mTypedWord;
+ final boolean isTypedWord = suggestedWords.getInfo(indexInSuggestedWords).isKindOf(
+ SuggestedWordInfo.KIND_TYPED);
final int color;
if (positionInStrip == mCenterPositionInStrip && suggestedWords.mWillAutoCorrect) {
@@ -386,6 +388,12 @@ final class SuggestionStripLayoutHelper {
final float scaleX = getTextScaleX(word, width, wordView.getPaint());
wordView.setText(text); // TextView.setText() resets text scale x to 1.0.
wordView.setTextScaleX(Math.max(scaleX, MIN_TEXT_XSCALE));
+ // A <code>wordView</code> should be disabled when <code>word</code> is empty in order to
+ // make it unclickable.
+ // With accessibility touch exploration on, <code>wordView</code> should be enabled even
+ // when it is empty to avoid announcing as "disabled".
+ wordView.setEnabled(!TextUtils.isEmpty(word)
+ || AccessibilityUtils.getInstance().isTouchExplorationEnabled());
return wordView;
}
diff --git a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
index c66007537..34f59e8bc 100644
--- a/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CombinedFormatUtils.java
@@ -31,6 +31,7 @@ public class CombinedFormatUtils {
public static final String HISTORICAL_INFO_TAG = "historicalInfo";
public static final String HISTORICAL_INFO_SEPARATOR = ":";
public static final String WORD_TAG = "word";
+ public static final String BEGINNING_OF_SENTENCE_TAG = "beginning_of_sentence";
public static final String NOT_A_WORD_TAG = "not_a_word";
public static final String BLACKLISTED_TAG = "blacklisted";
@@ -56,6 +57,9 @@ public class CombinedFormatUtils {
builder.append(" " + WORD_TAG + "=" + wordProperty.mWord);
builder.append(",");
builder.append(formatProbabilityInfo(wordProperty.mProbabilityInfo));
+ if (wordProperty.mIsBeginningOfSentence) {
+ builder.append("," + BEGINNING_OF_SENTENCE_TAG + "=true");
+ }
if (wordProperty.mIsNotAWord) {
builder.append("," + NOT_A_WORD_TAG + "=true");
}
diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
index 0b362c48a..5c109a68c 100644
--- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
+++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java
@@ -17,7 +17,9 @@
package com.android.inputmethod.latin.utils;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
+import com.android.inputmethod.latin.define.ProductionFlag;
+import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.Locale;
@@ -29,6 +31,7 @@ import java.util.TreeSet;
*/
public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
public final Locale mLocale;
+ public final ArrayList<SuggestedWordInfo> mRawSuggestions;
private final int mCapacity;
public SuggestionResults(final Locale locale, final int capacity) {
@@ -40,6 +43,11 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> {
super(comparator);
mLocale = locale;
mCapacity = capacity;
+ if (ProductionFlag.INCLUDE_RAW_SUGGESTIONS) {
+ mRawSuggestions = new ArrayList<>();
+ } else {
+ mRawSuggestions = null;
+ }
}
@Override