diff options
Diffstat (limited to 'java/src')
25 files changed, 357 insertions, 456 deletions
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java index 6b939cdfe..9ea1950f5 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitator.java @@ -20,7 +20,7 @@ import android.content.Context; import android.util.Pair; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.keyboard.KeyboardLayout; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.common.ComposedData; import com.android.inputmethod.latin.settings.SettingsValuesForSuggestion; import com.android.inputmethod.latin.utils.SuggestionResults; @@ -157,9 +157,9 @@ public interface DictionaryFacilitator { // TODO: Revise the way to fusion suggestion results. SuggestionResults getSuggestionResults(final ComposedData composedData, - final NgramContext ngramContext, final long proximityInfoHandle, + final NgramContext ngramContext, @Nonnull final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int sessionId, - final int inputStyle, final KeyboardLayout keyboardLayout); + final int inputStyle); boolean isValidSpellingWord(final String word); diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java index e96300020..763cfa26d 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorImpl.java @@ -22,7 +22,7 @@ import android.util.Log; import android.util.Pair; import com.android.inputmethod.annotations.UsedForTesting; -import com.android.inputmethod.keyboard.KeyboardLayout; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.NgramContext.WordInfo; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.common.ComposedData; @@ -668,12 +668,14 @@ public class DictionaryFacilitatorImpl implements DictionaryFacilitator { // TODO: Revise the way to fusion suggestion results. @Override public SuggestionResults getSuggestionResults(ComposedData composedData, - NgramContext ngramContext, long proximityInfoHandle, + NgramContext ngramContext, @Nonnull final Keyboard keyboard, SettingsValuesForSuggestion settingsValuesForSuggestion, int sessionId, - int inputStyle, KeyboardLayout keyboardLayout) { + int inputStyle) { + long proximityInfoHandle = keyboard.getProximityInfo().getNativeProximityInfo(); final DictionaryGroup[] dictionaryGroups = mDictionaryGroups; final SuggestionResults suggestionResults = new SuggestionResults( - SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext()); + SuggestedWords.MAX_SUGGESTIONS, ngramContext.isBeginningOfSentenceContext(), + false /* firstSuggestionExceedsConfidenceThreshold */); final float[] weightOfLangModelVsSpatialModel = new float[] { Dictionary.NOT_A_WEIGHT_OF_LANG_MODEL_VS_SPATIAL_MODEL }; for (final DictionaryGroup dictionaryGroup : dictionaryGroups) { diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java index 1b3e9ca72..2a1ae3684 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorLruCache.java @@ -41,7 +41,8 @@ public class DictionaryFacilitatorLruCache { public DictionaryFacilitatorLruCache(final Context context, final String dictionaryNamePrefix) { mContext = context; mDictionaryNamePrefix = dictionaryNamePrefix; - mDictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator(); + mDictionaryFacilitator = DictionaryFacilitatorProvider.getDictionaryFacilitator( + true /* isNeededForSpellChecking */); } private static void waitForLoadingMainDictionary( diff --git a/java/src/com/android/inputmethod/latin/DictionaryFactory.java b/java/src/com/android/inputmethod/latin/DictionaryFactory.java index 781ab06c5..49608d830 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFactory.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFactory.java @@ -80,7 +80,7 @@ public final class DictionaryFactory { * @param context The context to contact the dictionary provider, if possible. * @param f A file address to the dictionary to kill. */ - private static void killDictionary(final Context context, final AssetFileAddress f) { + public static void killDictionary(final Context context, final AssetFileAddress f) { if (f.pointsToPhysicalFile()) { f.deleteUnderlyingFile(); // Warn the dictionary provider if the dictionary came from there. diff --git a/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java index 8116a4983..9b271116d 100644 --- a/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java +++ b/java/src/com/android/inputmethod/latin/EmojiAltPhysicalKeyDetector.java @@ -16,6 +16,7 @@ package com.android.inputmethod.latin; +import android.util.Log; import android.view.KeyEvent; import com.android.inputmethod.keyboard.KeyboardSwitcher; @@ -25,10 +26,18 @@ import com.android.inputmethod.latin.settings.Settings; * A class for detecting Emoji-Alt physical key. */ final class EmojiAltPhysicalKeyDetector { + private static final String TAG = "EmojiAltPhysicalKeyDetector"; + + private final RichInputConnection mRichInputConnection; + // True if the Alt key has been used as a modifier. In this case the Alt key up isn't // recognized as an emoji key. private boolean mAltHasBeenUsedAsAModifier; + public EmojiAltPhysicalKeyDetector(final RichInputConnection richInputConnection) { + mRichInputConnection = richInputConnection; + } + /** * Record a down key event. * @param keyEvent a down key event. @@ -62,9 +71,14 @@ final class EmojiAltPhysicalKeyDetector { if (!Settings.getInstance().getCurrent().mEnableEmojiAltPhysicalKey) { return; } - if (!mAltHasBeenUsedAsAModifier) { - onEmojiAltKeyDetected(); + if (mAltHasBeenUsedAsAModifier) { + return; + } + if (!mRichInputConnection.isConnected()) { + Log.w(TAG, "onKeyUp() : No connection to text view"); + return; } + onEmojiAltKeyDetected(); } private static void onEmojiAltKeyDetected() { diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index 064d79b3c..b0fb91bec 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -259,7 +259,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { /** * Check whether GC is needed and run GC if required. */ - protected void runGCIfRequired(final boolean mindsBlockByGC) { + public void runGCIfRequired(final boolean mindsBlockByGC) { asyncExecuteTaskWithWriteLock(new Runnable() { @Override public void run() { diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 550efa59f..76d4a4a8d 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -73,7 +73,6 @@ import com.android.inputmethod.latin.common.InputPointers; import com.android.inputmethod.latin.define.DebugFlags; import com.android.inputmethod.latin.define.ProductionFlags; import com.android.inputmethod.latin.inputlogic.InputLogic; -import com.android.inputmethod.latin.personalization.DictionaryDecayBroadcastReciever; import com.android.inputmethod.latin.personalization.PersonalizationHelper; import com.android.inputmethod.latin.settings.Settings; import com.android.inputmethod.latin.settings.SettingsActivity; @@ -127,7 +126,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen final Settings mSettings; private final DictionaryFacilitator mDictionaryFacilitator = - DictionaryFacilitatorProvider.getDictionaryFacilitator(); + DictionaryFacilitatorProvider.getDictionaryFacilitator( + false /* isNeededForSpellChecking */); final InputLogic mInputLogic = new InputLogic(this /* LatinIME */, this /* SuggestionStripViewAccessor */, mDictionaryFacilitator); // We expect to have only one decoder in almost all cases, hence the default capacity of 1. @@ -143,7 +143,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen @UsedForTesting final KeyboardSwitcher mKeyboardSwitcher; private final SubtypeState mSubtypeState = new SubtypeState(); private final EmojiAltPhysicalKeyDetector mEmojiAltPhysicalKeyDetector = - new EmojiAltPhysicalKeyDetector(); + new EmojiAltPhysicalKeyDetector(mInputLogic.mConnection); private StatsUtilsManager mStatsUtilsManager; // Working variable for {@link #startShowingInputView()} and // {@link #onEvaluateInputViewShown()}. @@ -584,7 +584,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen dictDumpFilter.addAction(DictionaryDumpBroadcastReceiver.DICTIONARY_DUMP_INTENT_ACTION); registerReceiver(mDictionaryDumpBroadcastReceiver, dictDumpFilter); - DictionaryDecayBroadcastReciever.setUpIntervalAlarmForDictionaryDecaying(this); StatsUtils.onCreate(mSettings.getCurrent(), mRichImm); } @@ -704,7 +703,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen unregisterReceiver(mDictionaryPackInstallReceiver); unregisterReceiver(mDictionaryDumpBroadcastReceiver); mStatsUtilsManager.onDestroy(this /* context */); - DictionaryDecayBroadcastReciever.cancelIntervalAlarmForDictionaryDecaying(this); super.onDestroy(); } @@ -1514,9 +1512,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen callback.onGetSuggestedWords(SuggestedWords.getEmptyInstance()); return; } - mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard.getProximityInfo(), - mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback, - keyboard.getKeyboardLayout()); + mInputLogic.getSuggestedWords(mSettings.getCurrent(), keyboard, + mKeyboardSwitcher.getKeyboardShiftMode(), inputStyle, sequenceNumber, callback); } @Override diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 0210d7e18..08e8fe346 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -101,12 +101,17 @@ public final class RichInputConnection implements PrivateCommandPerformer { private final InputMethodService mParent; InputConnection mIC; int mNestLevel; + public RichInputConnection(final InputMethodService parent) { mParent = parent; mIC = null; mNestLevel = 0; } + public boolean isConnected() { + return mIC != null; + } + private void checkConsistencyForDebug() { final ExtractedTextRequest r = new ExtractedTextRequest(); r.hintMaxChars = 0; @@ -142,7 +147,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { public void beginBatchEdit() { if (++mNestLevel == 1) { mIC = mParent.getCurrentInputConnection(); - if (null != mIC) { + if (isConnected()) { mIC.beginBatchEdit(); } } else { @@ -157,7 +162,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { public void endBatchEdit() { if (mNestLevel <= 0) Log.e(TAG, "Batch edit not in progress!"); // TODO: exception instead - if (--mNestLevel == 0 && null != mIC) { + if (--mNestLevel == 0 && isConnected()) { mIC.endBatchEdit(); } if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); @@ -189,7 +194,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { Log.d(TAG, "Will try to retrieve text later."); return false; } - if (null != mIC && shouldFinishComposition) { + if (isConnected() && shouldFinishComposition) { mIC.finishComposingText(); } return true; @@ -205,8 +210,9 @@ public final class RichInputConnection implements PrivateCommandPerformer { mIC = mParent.getCurrentInputConnection(); // Call upon the inputconnection directly since our own method is using the cache, and // we want to refresh it. - final CharSequence textBeforeCursor = null == mIC ? null : - mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); + final CharSequence textBeforeCursor = isConnected() + ? mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, 0) + : null; if (null == textBeforeCursor) { // For some reason the app thinks we are not connected to it. This looks like a // framework bug... Fall back to ground state and return false. @@ -235,7 +241,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { // it works, but it's wrong and should be fixed. mCommittedTextBeforeComposingText.append(mComposingText); mComposingText.setLength(0); - if (null != mIC) { + if (isConnected()) { mIC.finishComposingText(); } } @@ -256,7 +262,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { mExpectedSelStart += text.length() - mComposingText.length(); mExpectedSelEnd = mExpectedSelStart; mComposingText.setLength(0); - if (null != mIC) { + if (isConnected()) { mTempObjectForCommitText.clear(); mTempObjectForCommitText.append(text); final CharacterStyle[] spans = mTempObjectForCommitText.getSpans( @@ -283,7 +289,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { } public CharSequence getSelectedText(final int flags) { - return (null == mIC) ? null : mIC.getSelectedText(flags); + return isConnected() ? mIC.getSelectedText(flags) : null; } public boolean canDeleteCharacters() { @@ -308,7 +314,9 @@ public final class RichInputConnection implements PrivateCommandPerformer { public int getCursorCapsMode(final int inputType, final SpacingAndPunctuations spacingAndPunctuations, final boolean hasSpaceBefore) { mIC = mParent.getCurrentInputConnection(); - if (null == mIC) return Constants.TextUtils.CAP_MODE_OFF; + if (!isConnected()) { + return Constants.TextUtils.CAP_MODE_OFF; + } if (!TextUtils.isEmpty(mComposingText)) { if (hasSpaceBefore) { // If we have some composing text and a space before, then we should have @@ -368,12 +376,12 @@ public final class RichInputConnection implements PrivateCommandPerformer { return s; } mIC = mParent.getCurrentInputConnection(); - return (null == mIC) ? null : mIC.getTextBeforeCursor(n, flags); + return isConnected() ? mIC.getTextBeforeCursor(n, flags) : null; } public CharSequence getTextAfterCursor(final int n, final int flags) { mIC = mParent.getCurrentInputConnection(); - return (null == mIC) ? null : mIC.getTextAfterCursor(n, flags); + return isConnected() ? mIC.getTextAfterCursor(n, flags) : null; } public void deleteSurroundingText(final int beforeLength, final int afterLength) { @@ -400,7 +408,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { mExpectedSelEnd -= mExpectedSelStart; mExpectedSelStart = 0; } - if (null != mIC) { + if (isConnected()) { mIC.deleteSurroundingText(beforeLength, afterLength); } if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); @@ -408,7 +416,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { public void performEditorAction(final int actionId) { mIC = mParent.getCurrentInputConnection(); - if (null != mIC) { + if (isConnected()) { mIC.performEditorAction(actionId); } } @@ -460,7 +468,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { break; } } - if (null != mIC) { + if (isConnected()) { mIC.sendKeyEvent(keyEvent); } } @@ -483,7 +491,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { mCommittedTextBeforeComposingText.append( textBeforeCursor.subSequence(0, indexOfStartOfComposingText)); } - if (null != mIC) { + if (isConnected()) { mIC.setComposingRegion(start, end); } } @@ -497,7 +505,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { mComposingText.append(text); // TODO: support values of newCursorPosition != 1. At this time, this is never called with // newCursorPosition != 1. - if (null != mIC) { + if (isConnected()) { mIC.setComposingText(text, newCursorPosition); } if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); @@ -522,7 +530,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { } mExpectedSelStart = start; mExpectedSelEnd = end; - if (null != mIC) { + if (isConnected()) { final boolean isIcValid = mIC.setSelection(start, end); if (!isIcValid) { return false; @@ -536,7 +544,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); // This has no effect on the text field and does not change its content. It only makes // TextView flash the text for a second based on indices contained in the argument. - if (null != mIC) { + if (isConnected()) { mIC.commitCorrection(correctionInfo); } if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); @@ -552,7 +560,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { mExpectedSelStart += text.length() - mComposingText.length(); mExpectedSelEnd = mExpectedSelStart; mComposingText.setLength(0); - if (null != mIC) { + if (isConnected()) { mIC.commitCompletion(completionInfo); } if (DEBUG_PREVIOUS_TEXT) checkConsistencyForDebug(); @@ -563,7 +571,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { public NgramContext getNgramContextFromNthPreviousWord( final SpacingAndPunctuations spacingAndPunctuations, final int n) { mIC = mParent.getCurrentInputConnection(); - if (null == mIC) { + if (!isConnected()) { return NgramContext.EMPTY_PREV_WORDS_INFO; } final CharSequence prev = getTextBeforeCursor(LOOKBACK_CHARACTER_NUM, 0); @@ -608,7 +616,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { public TextRange getWordRangeAtCursor(final SpacingAndPunctuations spacingAndPunctuations, final int scriptId) { mIC = mParent.getCurrentInputConnection(); - if (mIC == null) { + if (!isConnected()) { return null; } final CharSequence before = mIC.getTextBeforeCursor(Constants.EDITOR_CONTENTS_CACHE_SIZE, @@ -824,7 +832,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { mIC = mParent.getCurrentInputConnection(); final CharSequence textBeforeCursor = getTextBeforeCursor( Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); - final CharSequence selectedText = null == mIC ? null : mIC.getSelectedText(0 /* flags */); + final CharSequence selectedText = isConnected() ? mIC.getSelectedText(0 /* flags */) : null; if (null == textBeforeCursor || (!TextUtils.isEmpty(selectedText) && mExpectedSelEnd == mExpectedSelStart)) { // If textBeforeCursor is null, we have no idea what kind of text field we have or if @@ -863,7 +871,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { @Override public boolean performPrivateCommand(final String action, final Bundle data) { mIC = mParent.getCurrentInputConnection(); - if (mIC == null) { + if (!isConnected()) { return false; } return mIC.performPrivateCommand(action, data); @@ -923,7 +931,7 @@ public final class RichInputConnection implements PrivateCommandPerformer { public boolean requestCursorUpdates(final boolean enableMonitor, final boolean requestImmediateCallback) { mIC = mParent.getCurrentInputConnection(); - if (mIC == null) { + if (!isConnected()) { return false; } return InputConnectionCompatUtils.requestCursorUpdates( diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java index 428956a7b..f4680fc88 100644 --- a/java/src/com/android/inputmethod/latin/Suggest.java +++ b/java/src/com/android/inputmethod/latin/Suggest.java @@ -18,8 +18,9 @@ package com.android.inputmethod.latin; import android.text.TextUtils; -import com.android.inputmethod.keyboard.KeyboardLayout; -import com.android.inputmethod.keyboard.ProximityInfo; +import static com.android.inputmethod.latin.define.DecoderSpecificConstants.SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION; + +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.common.Constants; import com.android.inputmethod.latin.common.StringUtils; @@ -95,19 +96,17 @@ public final class Suggest { } public void getSuggestedWords(final WordComposer wordComposer, - final NgramContext ngramContext, final ProximityInfo proximityInfo, + final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final boolean isCorrectionEnabled, final int inputStyle, final int sequenceNumber, - final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final OnGetSuggestedWordsCallback callback) { if (wordComposer.isBatchMode()) { - getSuggestedWordsForBatchInput(wordComposer, ngramContext, proximityInfo, - settingsValuesForSuggestion, inputStyle, sequenceNumber, callback, - keyboardLayout); + getSuggestedWordsForBatchInput(wordComposer, ngramContext, keyboard, + settingsValuesForSuggestion, inputStyle, sequenceNumber, callback); } else { - getSuggestedWordsForNonBatchInput(wordComposer, ngramContext, proximityInfo, + getSuggestedWordsForNonBatchInput(wordComposer, ngramContext, keyboard, settingsValuesForSuggestion, inputStyle, isCorrectionEnabled, - sequenceNumber, callback, keyboardLayout); + sequenceNumber, callback); } } @@ -163,11 +162,10 @@ public final class Suggest { // Retrieves suggestions for non-batch input (typing, recorrection, predictions...) // and calls the callback function with the suggestions. private void getSuggestedWordsForNonBatchInput(final WordComposer wordComposer, - final NgramContext ngramContext, final ProximityInfo proximityInfo, + final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyleIfNotPrediction, final boolean isCorrectionEnabled, - final int sequenceNumber, final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { final String typedWordString = wordComposer.getTypedWord(); final int trailingSingleQuotesCount = StringUtils.getTrailingSingleQuotesCount(typedWordString); @@ -176,9 +174,8 @@ public final class Suggest { : typedWordString; final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( - wordComposer.getComposedDataSnapshot(), ngramContext, - proximityInfo.getNativeProximityInfo(), settingsValuesForSuggestion, - SESSION_ID_TYPING, inputStyleIfNotPrediction, keyboardLayout); + wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, + settingsValuesForSuggestion, SESSION_ID_TYPING, inputStyleIfNotPrediction); final Locale mostProbableLocale = mDictionaryFacilitator.getMostProbableLocale(); final ArrayList<SuggestedWordInfo> suggestionsContainer = getTransformedSuggestedWordInfoList(wordComposer, suggestionResults, @@ -213,7 +210,8 @@ public final class Suggest { } } - SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer); + final int firstOcurrenceOfTypedWordInSuggestions = + SuggestedWordInfo.removeDups(typedWordString, suggestionsContainer); final SuggestedWordInfo whitelistedWordInfo = getWhitelistedWordInfoOrNull(suggestionsContainer); @@ -236,10 +234,11 @@ public final class Suggest { } final boolean resultsArePredictions = !wordComposer.isComposingWord(); - // We allow auto-correction if we have a whitelisted word, or if the word had more than - // one char and was not suggested. - final boolean allowsToBeAutoCorrected = (null != whitelistedWord) - || (consideredWord.length() > 1 && (null == sourceDictionaryOfRemovedWord)); + // We allow auto-correction if whitelisting is not required or the word is whitelisted, + // or if the word had more than one char and was not suggested. + final boolean allowsToBeAutoCorrected = + (SHOULD_AUTO_CORRECT_USING_NON_WHITE_LISTED_SUGGESTION || whitelistedWord != null) + || (consideredWord.length() > 1 && (sourceDictionaryOfRemovedWord == null)); final boolean hasAutoCorrection; // If correction is not enabled, we never auto-correct. This is for example for when @@ -275,7 +274,8 @@ public final class Suggest { hasAutoCorrection = false; } else { final SuggestedWordInfo firstSuggestion = suggestionResults.first(); - if (suggestionResults.mAutocorrectRecommendation) { + if (suggestionResults.mFirstSuggestionExceedsConfidenceThreshold + && firstOcurrenceOfTypedWordInSuggestions != 0) { hasAutoCorrection = true; } else if (!AutoCorrectionUtils.suggestionExceedsThreshold( firstSuggestion, consideredWord, mAutoCorrectionThreshold)) { @@ -316,12 +316,12 @@ public final class Suggest { } else { inputStyle = inputStyleIfNotPrediction; } + + final boolean isTypedWordValid = firstOcurrenceOfTypedWordInSuggestions > -1 + || (!resultsArePredictions && !allowsToBeAutoCorrected); callback.onGetSuggestedWords(new SuggestedWords(suggestionsList, suggestionResults.mRawSuggestions, typedWordInfo, - // 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. - !resultsArePredictions && !allowsToBeAutoCorrected /* typedWordValid */, + isTypedWordValid, hasAutoCorrection /* willAutoCorrect */, false /* isObsoleteSuggestions */, inputStyle, sequenceNumber)); } @@ -343,15 +343,13 @@ public final class Suggest { // Retrieves suggestions for the batch input // and calls the callback function with the suggestions. private void getSuggestedWordsForBatchInput(final WordComposer wordComposer, - final NgramContext ngramContext, final ProximityInfo proximityInfo, + final NgramContext ngramContext, final Keyboard keyboard, final SettingsValuesForSuggestion settingsValuesForSuggestion, final int inputStyle, final int sequenceNumber, - final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final OnGetSuggestedWordsCallback callback) { final SuggestionResults suggestionResults = mDictionaryFacilitator.getSuggestionResults( - wordComposer.getComposedDataSnapshot(), ngramContext, - proximityInfo.getNativeProximityInfo(), settingsValuesForSuggestion, - SESSION_ID_GESTURE, inputStyle, keyboardLayout); + wordComposer.getComposedDataSnapshot(), ngramContext, keyboard, + settingsValuesForSuggestion, SESSION_ID_GESTURE, inputStyle); // For transforming words that don't come from a dictionary, because it's our best bet final Locale defaultLocale = mDictionaryFacilitator.getMostProbableLocale(); final ArrayList<SuggestedWordInfo> suggestionsContainer = diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java index 913b63a61..3816c0870 100644 --- a/java/src/com/android/inputmethod/latin/SuggestedWords.java +++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java @@ -17,6 +17,7 @@ package com.android.inputmethod.latin; import android.text.TextUtils; +import android.util.Log; import android.view.inputmethod.CompletionInfo; import com.android.inputmethod.annotations.UsedForTesting; @@ -375,31 +376,45 @@ public class SuggestedWords { return mWord + " (" + mDebugString + ")"; } - // This will always remove the higher index if a duplicate is found. - public static void removeDups(@Nullable final String typedWord, - @Nonnull ArrayList<SuggestedWordInfo> candidates) { + /** + * This will always remove the higher index if a duplicate is found. + * + * @return position of typed word in the candidate list + */ + public static int removeDups( + @Nullable final String typedWord, + @Nonnull final ArrayList<SuggestedWordInfo> candidates) { if (candidates.isEmpty()) { - return; + return -1; } + int firstOccurrenceOfWord = -1; if (!TextUtils.isEmpty(typedWord)) { - removeSuggestedWordInfoFromList(typedWord, candidates, -1 /* startIndexExclusive */); + firstOccurrenceOfWord = removeSuggestedWordInfoFromList( + typedWord, candidates, -1 /* startIndexExclusive */); } for (int i = 0; i < candidates.size(); ++i) { - removeSuggestedWordInfoFromList(candidates.get(i).mWord, candidates, - i /* startIndexExclusive */); + removeSuggestedWordInfoFromList( + candidates.get(i).mWord, candidates, i /* startIndexExclusive */); } + return firstOccurrenceOfWord; } - private static void removeSuggestedWordInfoFromList( - @Nonnull final String word, @Nonnull final ArrayList<SuggestedWordInfo> candidates, + private static int removeSuggestedWordInfoFromList( + @Nonnull final String word, + @Nonnull final ArrayList<SuggestedWordInfo> candidates, final int startIndexExclusive) { + int firstOccurrenceOfWord = -1; for (int i = startIndexExclusive + 1; i < candidates.size(); ++i) { final SuggestedWordInfo previous = candidates.get(i); if (word.equals(previous.mWord)) { + if (firstOccurrenceOfWord == -1) { + firstOccurrenceOfWord = i; + } candidates.remove(i); --i; } } + return firstOccurrenceOfWord; } } diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java index 32ef1021d..8803edc88 100644 --- a/java/src/com/android/inputmethod/latin/WordComposer.java +++ b/java/src/com/android/inputmethod/latin/WordComposer.java @@ -232,31 +232,33 @@ public final class WordComposer { * @return true if the cursor is still inside the composing word, false otherwise. */ public boolean moveCursorByAndReturnIfInsideComposingWord(final int expectedMoveAmount) { - int actualMoveAmountWithinWord = 0; + int actualMoveAmount = 0; int cursorPos = mCursorPositionWithinWord; // TODO: Don't make that copy. We can do this directly from mTypedWordCache. final int[] codePoints = StringUtils.toCodePointArray(mTypedWordCache); if (expectedMoveAmount >= 0) { // Moving the cursor forward for the expected amount or until the end of the word has // been reached, whichever comes first. - while (actualMoveAmountWithinWord < expectedMoveAmount && cursorPos < mCodePointSize) { - actualMoveAmountWithinWord += Character.charCount(codePoints[cursorPos]); + while (actualMoveAmount < expectedMoveAmount && cursorPos < codePoints.length) { + actualMoveAmount += Character.charCount(codePoints[cursorPos]); ++cursorPos; } } else { // Moving the cursor backward for the expected amount or until the start of the word // has been reached, whichever comes first. - while (actualMoveAmountWithinWord > expectedMoveAmount && cursorPos > 0) { + while (actualMoveAmount > expectedMoveAmount && cursorPos > 0) { --cursorPos; - actualMoveAmountWithinWord -= Character.charCount(codePoints[cursorPos]); + actualMoveAmount -= Character.charCount(codePoints[cursorPos]); } } // If the actual and expected amounts differ, we crossed the start or the end of the word // so the result would not be inside the composing word. - if (actualMoveAmountWithinWord != expectedMoveAmount) return false; + if (actualMoveAmount != expectedMoveAmount) { + return false; + } mCursorPositionWithinWord = cursorPos; - mCombinerChain.applyProcessedEvent(mCombinerChain.processEvent(mEvents, - Event.createCursorMovedEvent(cursorPos))); + mCombinerChain.applyProcessedEvent(mCombinerChain.processEvent( + mEvents, Event.createCursorMovedEvent(cursorPos))); return true; } diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 57aa59190..3f1646beb 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -32,9 +32,8 @@ import android.view.inputmethod.EditorInfo; import com.android.inputmethod.compat.SuggestionSpanUtils; import com.android.inputmethod.event.Event; import com.android.inputmethod.event.InputTransaction; -import com.android.inputmethod.keyboard.KeyboardLayout; +import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardSwitcher; -import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.Dictionary; import com.android.inputmethod.latin.DictionaryFacilitator; import com.android.inputmethod.latin.LastComposedWord; @@ -926,6 +925,7 @@ public final class InputLogic { if (tryPerformDoubleSpacePeriod(event, inputTransaction)) { mSpaceState = SpaceState.DOUBLE; inputTransaction.setRequiresUpdateSuggestions(); + StatsUtils.onDoubleSpacePeriod(); } else if (swapWeakSpace && trySwapSwapperAndSpace(event, inputTransaction)) { mSpaceState = SpaceState.SWAP_PUNCTUATION; mSuggestionStripViewAccessor.setNeutralSuggestionStrip(); @@ -2165,9 +2165,8 @@ public final class InputLogic { } public void getSuggestedWords(final SettingsValues settingsValues, - final ProximityInfo proximityInfo, final int keyboardShiftMode, final int inputStyle, - final int sequenceNumber, final OnGetSuggestedWordsCallback callback, - final KeyboardLayout keyboardLayout) { + final Keyboard keyboard, final int keyboardShiftMode, final int inputStyle, + final int sequenceNumber, final OnGetSuggestedWordsCallback callback) { mWordComposer.adviseCapitalizedModeBeforeFetchingSuggestions( getActualCapsMode(settingsValues, keyboardShiftMode)); mSuggest.getSuggestedWords(mWordComposer, @@ -2177,11 +2176,11 @@ public final class InputLogic { // a word, it's whatever is *before* the half-committed word in the buffer, // hence 2; if we aren't, we should just skip whitespace if any, so 1. mWordComposer.isComposingWord() ? 2 : 1), - proximityInfo, + keyboard, new SettingsValuesForSuggestion(settingsValues.mBlockPotentiallyOffensive, settingsValues.mPhraseGestureEnabled), settingsValues.mAutoCorrectionEnabledPerUserSettings, - inputStyle, sequenceNumber, callback, keyboardLayout); + inputStyle, sequenceNumber, callback); } /** diff --git a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java index 1e9f8e47e..32a746d37 100644 --- a/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java +++ b/java/src/com/android/inputmethod/latin/makedict/FormatSpec.java @@ -172,8 +172,8 @@ public final class FormatSpec { public static final int VERSION2 = 2; public static final int VERSION201 = 201; public static final int VERSION202 = 202; - // format version for Fava - public static final int VERSION300 = 300; + // format version for Fava Dictionaries. + public static final int VERSION_DELIGHT3 = 86736212; public static final int MINIMUM_SUPPORTED_VERSION_OF_CODE_POINT_TABLE = VERSION201; // Dictionary version used for testing. public static final int VERSION4_ONLY_FOR_TESTING = 399; @@ -182,7 +182,7 @@ public final class FormatSpec { public static final int VERSION4 = VERSION403; public static final int VERSION4_DEV = VERSION403; public static final int MINIMUM_SUPPORTED_STATIC_VERSION = VERSION202; - public static final int MAXIMUM_SUPPORTED_STATIC_VERSION = VERSION300; + public static final int MAXIMUM_SUPPORTED_STATIC_VERSION = VERSION_DELIGHT3; static final int MINIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION4; static final int MAXIMUM_SUPPORTED_DYNAMIC_VERSION = VERSION4_DEV; diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java deleted file mode 100644 index 78b51d9f4..000000000 --- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin.personalization; - -import android.content.Context; - -import com.android.inputmethod.latin.Dictionary; -import com.android.inputmethod.latin.ExpandableBinaryDictionary; -import com.android.inputmethod.latin.makedict.DictionaryHeader; - -import java.io.File; -import java.util.Locale; -import java.util.Map; - -/** - * This class is a base class of a dictionary that supports decaying for the personalized language - * model. - */ -public abstract class DecayingExpandableBinaryDictionaryBase extends ExpandableBinaryDictionary { - private static final boolean DBG_DUMP_ON_CLOSE = false; - - /** Any pair being typed or picked */ - public static final int FREQUENCY_FOR_TYPED = 2; - - public static final int FREQUENCY_FOR_WORDS_IN_DICTS = FREQUENCY_FOR_TYPED; - public static final int FREQUENCY_FOR_WORDS_NOT_IN_DICTS = Dictionary.NOT_A_PROBABILITY; - - protected DecayingExpandableBinaryDictionaryBase(final Context context, - final String dictName, final Locale locale, final String dictionaryType, - final File dictFile) { - super(context, dictName, locale, dictionaryType, dictFile); - if (mLocale != null && mLocale.toString().length() > 1) { - reloadDictionaryIfRequired(); - } - } - - @Override - public void close() { - if (DBG_DUMP_ON_CLOSE) { - dumpAllWordsForDebug(); - } - // Flush pending writes. - asyncFlushBinaryDictionary(); - super.close(); - } - - @Override - protected Map<String, String> getHeaderAttributeMap() { - final Map<String, String> attributeMap = super.getHeaderAttributeMap(); - attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY, - DictionaryHeader.ATTRIBUTE_VALUE_TRUE); - attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY, - DictionaryHeader.ATTRIBUTE_VALUE_TRUE); - return attributeMap; - } - - @Override - protected void loadInitialContentsLocked() { - // No initial contents. - } - - /* package */ void runGCIfRequired() { - runGCIfRequired(false /* mindsBlockByGC */); - } - - @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/personalization/DictionaryDecayBroadcastReciever.java b/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java deleted file mode 100644 index 0c5e5d010..000000000 --- a/java/src/com/android/inputmethod/latin/personalization/DictionaryDecayBroadcastReciever.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (C) 2013 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.inputmethod.latin.personalization; - -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; - -import java.util.concurrent.TimeUnit; - -/** - * Broadcast receiver for periodically updating decaying dictionaries. - */ -public class DictionaryDecayBroadcastReciever extends BroadcastReceiver { - /** - * The root domain for the personalization. - */ - private static final String PERSONALIZATION_DOMAIN = - "com.android.inputmethod.latin.personalization"; - - /** - * The action of the intent to tell the time to decay dictionaries. - */ - private static final String DICTIONARY_DECAY_INTENT_ACTION = - PERSONALIZATION_DOMAIN + ".DICT_DECAY"; - - /** - * Interval to update for decaying dictionaries. - */ - static final long DICTIONARY_DECAY_INTERVAL_IN_MILLIS = TimeUnit.MINUTES.toMillis(60); - - private static PendingIntent getPendingIntentForDictionaryDecay(final Context context) { - final Intent updateIntent = new Intent(DICTIONARY_DECAY_INTENT_ACTION); - updateIntent.setClass(context, DictionaryDecayBroadcastReciever.class); - return PendingIntent.getBroadcast(context, 0 /* requestCode */, - updateIntent, PendingIntent.FLAG_CANCEL_CURRENT); - } - - /** - * Set up interval alarm for dynamic dictionaries. - */ - public static void setUpIntervalAlarmForDictionaryDecaying(final Context context) { - final AlarmManager alarmManager = - (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - if (null == alarmManager) { - return; - } - final long alarmTriggerTimeInMillis = - System.currentTimeMillis() + DICTIONARY_DECAY_INTERVAL_IN_MILLIS; - alarmManager.setInexactRepeating(AlarmManager.RTC, alarmTriggerTimeInMillis, - DICTIONARY_DECAY_INTERVAL_IN_MILLIS, getPendingIntentForDictionaryDecay(context)); - } - - /** - * Cancel interval alarm that has been set up. - */ - public static void cancelIntervalAlarmForDictionaryDecaying(final Context context) { - final AlarmManager alarmManager = - (AlarmManager)context.getSystemService(Context.ALARM_SERVICE); - if (null == alarmManager) { - return; - } - alarmManager.cancel(getPendingIntentForDictionaryDecay(context)); - } - - @Override - public void onReceive(final Context context, final Intent intent) { - final String action = intent.getAction(); - if (action.equals(DICTIONARY_DECAY_INTENT_ACTION)) { - PersonalizationHelper.runGCOnAllOpenedUserHistoryDictionaries(); - } - } -} diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java index 1c1cb4f95..298e46c0a 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java @@ -26,7 +26,6 @@ import java.io.FilenameFilter; import java.lang.ref.SoftReference; import java.util.Locale; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -68,60 +67,28 @@ public class PersonalizationHelper { } } - private static int sCurrentTimestampForTesting = 0; - public static void currentTimeChangedForTesting(final int currentTimestamp) { - if (TimeUnit.MILLISECONDS.toSeconds( - DictionaryDecayBroadcastReciever.DICTIONARY_DECAY_INTERVAL_IN_MILLIS) - < currentTimestamp - sCurrentTimestampForTesting) { - runGCOnAllOpenedUserHistoryDictionaries(); - } - } - - public static void runGCOnAllOpenedUserHistoryDictionaries() { - runGCOnAllDictionariesIfRequired(sLangUserHistoryDictCache); - } - - private static <T extends DecayingExpandableBinaryDictionaryBase> - void runGCOnAllDictionariesIfRequired( - final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap) { - for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry - : dictionaryMap.entrySet()) { - final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get(); - if (dict != null) { - dict.runGCIfRequired(); - } else { - dictionaryMap.remove(entry.getKey()); - } - } - } - public static void removeAllUserHistoryDictionaries(final Context context) { - removeAllDictionaries(context, sLangUserHistoryDictCache, - UserHistoryDictionary.NAME); - } - - private static <T extends DecayingExpandableBinaryDictionaryBase> void removeAllDictionaries( - final Context context, final ConcurrentHashMap<String, SoftReference<T>> dictionaryMap, - final String dictNamePrefix) { - synchronized (dictionaryMap) { - for (final ConcurrentHashMap.Entry<String, SoftReference<T>> entry - : dictionaryMap.entrySet()) { + synchronized (sLangUserHistoryDictCache) { + for (final ConcurrentHashMap.Entry<String, SoftReference<UserHistoryDictionary>> entry + : sLangUserHistoryDictCache.entrySet()) { if (entry.getValue() != null) { - final DecayingExpandableBinaryDictionaryBase dict = entry.getValue().get(); + final UserHistoryDictionary dict = entry.getValue().get(); if (dict != null) { dict.clear(); } } } - dictionaryMap.clear(); + sLangUserHistoryDictCache.clear(); final File filesDir = context.getFilesDir(); if (filesDir == null) { Log.e(TAG, "context.getFilesDir() returned null."); return; } - if (!FileUtils.deleteFilteredFiles(filesDir, new DictFilter(dictNamePrefix))) { - Log.e(TAG, "Cannot remove all existing dictionary files. filesDir: " - + filesDir.getAbsolutePath() + ", dictNamePrefix: " + dictNamePrefix); + final boolean filesDeleted = FileUtils.deleteFilteredFiles( + filesDir, new DictFilter(UserHistoryDictionary.NAME)); + if (!filesDeleted) { + Log.e(TAG, "Cannot remove dictionary files. filesDir: " + filesDir.getAbsolutePath() + + ", dictNamePrefix: " + UserHistoryDictionary.NAME); } } } diff --git a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java index b6286b203..54ee68d65 100644 --- a/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java +++ b/java/src/com/android/inputmethod/latin/personalization/UserHistoryDictionary.java @@ -25,9 +25,11 @@ import com.android.inputmethod.latin.ExpandableBinaryDictionary; import com.android.inputmethod.latin.NgramContext; import com.android.inputmethod.latin.define.DecoderSpecificConstants; import com.android.inputmethod.latin.define.ProductionFlags; +import com.android.inputmethod.latin.makedict.DictionaryHeader; import java.io.File; import java.util.Locale; +import java.util.Map; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -37,17 +39,16 @@ import javax.annotation.Nullable; * auto-correction cancellation or manual picks. This allows the keyboard to adapt to the * typist over time. */ -public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBase { +public class UserHistoryDictionary extends ExpandableBinaryDictionary { static final String NAME = UserHistoryDictionary.class.getSimpleName(); // TODO: Make this constructor private UserHistoryDictionary(final Context context, final Locale locale, @Nullable final String account) { - super(context, - getUserHistoryDictName(NAME, locale, null /* dictFile */, account), - locale, - Dictionary.TYPE_USER_HISTORY, - null /* dictFile */); + super(context, getUserHistoryDictName(NAME, locale, null /* dictFile */, account), locale, Dictionary.TYPE_USER_HISTORY, null); + if (mLocale != null && mLocale.toString().length() > 1) { + reloadDictionaryIfRequired(); + } } /** @@ -103,4 +104,32 @@ public class UserHistoryDictionary extends DecayingExpandableBinaryDictionaryBas userHistoryDictionary.updateEntriesForWord(ngramContext, word, isValid, 1 /* count */, timestamp); } + + @Override + public void close() { + // Flush pending writes. + asyncFlushBinaryDictionary(); + super.close(); + } + + @Override + protected Map<String, String> getHeaderAttributeMap() { + final Map<String, String> attributeMap = super.getHeaderAttributeMap(); + attributeMap.put(DictionaryHeader.USES_FORGETTING_CURVE_KEY, + DictionaryHeader.ATTRIBUTE_VALUE_TRUE); + attributeMap.put(DictionaryHeader.HAS_HISTORICAL_INFO_KEY, + DictionaryHeader.ATTRIBUTE_VALUE_TRUE); + return attributeMap; + } + + @Override + protected void loadInitialContentsLocked() { + // No initial contents. + } + + @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/AccountsSettingsFragment.java b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java index 10d570cbf..394ecead6 100644 --- a/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java +++ b/java/src/com/android/inputmethod/latin/settings/AccountsSettingsFragment.java @@ -23,8 +23,8 @@ import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.SharedPreferences; -import android.content.res.Resources; import android.os.Bundle; +import android.preference.CheckBoxPreference; import android.preference.Preference; import android.preference.Preference.OnPreferenceClickListener; import android.text.TextUtils; @@ -48,36 +48,50 @@ import javax.annotation.Nullable; * <li> Privacy preferences </li> */ public final class AccountsSettingsFragment extends SubScreenFragment { - private static final String PREF_SYNC_NOW = "pref_beanstalk"; - private static final String PREF_CLEAR_SYNC_DATA = "pref_beanstalk_clear_data"; + private static final String PREF_ENABLE_SYNC_NOW = "pref_enable_cloud_sync"; + private static final String PREF_SYNC_NOW = "pref_sync_now"; + private static final String PREF_CLEAR_SYNC_DATA = "pref_clear_sync_data"; static final String PREF_ACCCOUNT_SWITCHER = "account_switcher"; - private final DialogInterface.OnClickListener mAccountChangedListener = - new AccountChangedListener(); - private final Preference.OnPreferenceClickListener mSyncNowListener = new SyncNowListener(); - private final Preference.OnPreferenceClickListener mClearSyncDataListener = - new ClearSyncDataListener(); + /** + * Onclick listener for sync now pref. + */ + private final Preference.OnPreferenceClickListener mSyncNowListener = + new SyncNowListener(); + /** + * Onclick listener for delete sync pref. + */ + private final Preference.OnPreferenceClickListener mDeleteSyncDataListener = + new DeleteSyncDataListener(); + + /** + * Onclick listener for enable sync pref. + */ + private final Preference.OnPreferenceClickListener mEnableSyncClickListener = + new EnableSyncClickListener(); + + /** + * Enable sync checkbox pref. + */ + private CheckBoxPreference mEnableSyncPreference; + + /** + * Enable sync checkbox pref. + */ + private Preference mSyncNowPreference; + + /** + * Clear sync data pref. + */ + private Preference mClearSyncDataPreference; + @Override public void onCreate(final Bundle icicle) { super.onCreate(icicle); addPreferencesFromResource(R.xml.prefs_screen_accounts); - final Resources res = getResources(); - - if (ProductionFlags.IS_METRICS_LOGGING_SUPPORTED) { - final Preference enableMetricsLogging = - findPreference(Settings.PREF_ENABLE_METRICS_LOGGING); - if (enableMetricsLogging != null) { - final String enableMetricsLoggingTitle = res.getString( - R.string.enable_metrics_logging, getApplicationName()); - enableMetricsLogging.setTitle(enableMetricsLoggingTitle); - } - } else { - removePreference(Settings.PREF_ENABLE_METRICS_LOGGING); - } - if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) { removePreference(PREF_ACCCOUNT_SWITCHER); removePreference(PREF_ENABLE_CLOUD_SYNC); @@ -89,11 +103,14 @@ public final class AccountsSettingsFragment extends SubScreenFragment { removePreference(PREF_SYNC_NOW); removePreference(PREF_CLEAR_SYNC_DATA); } else { - final Preference syncNowPreference = findPreference(PREF_SYNC_NOW); - syncNowPreference.setOnPreferenceClickListener(mSyncNowListener); + mEnableSyncPreference = (CheckBoxPreference) findPreference(PREF_ENABLE_SYNC_NOW); + mEnableSyncPreference.setOnPreferenceClickListener(mEnableSyncClickListener); + + mSyncNowPreference = findPreference(PREF_SYNC_NOW); + mSyncNowPreference.setOnPreferenceClickListener(mSyncNowListener); - final Preference clearSyncDataPreference = findPreference(PREF_CLEAR_SYNC_DATA); - clearSyncDataPreference.setOnPreferenceClickListener(mClearSyncDataListener); + mClearSyncDataPreference = findPreference(PREF_CLEAR_SYNC_DATA); + mClearSyncDataPreference.setOnPreferenceClickListener(mDeleteSyncDataListener); } } @@ -106,15 +123,25 @@ public final class AccountsSettingsFragment extends SubScreenFragment { @Override public void onSharedPreferenceChanged(final SharedPreferences prefs, final String key) { if (TextUtils.equals(key, PREF_ACCOUNT_NAME)) { - refreshAccountAndDependentPreferences( - prefs.getString(PREF_ACCOUNT_NAME, null)); + refreshAccountAndDependentPreferences(prefs.getString(PREF_ACCOUNT_NAME, null)); } else if (TextUtils.equals(key, PREF_ENABLE_CLOUD_SYNC)) { final boolean syncEnabled = prefs.getBoolean(PREF_ENABLE_CLOUD_SYNC, false); - AccountStateChangedListener.onSyncPreferenceChanged( - getSignedInAccountName(), syncEnabled); + mEnableSyncPreference = (CheckBoxPreference)findPreference(PREF_ENABLE_SYNC_NOW); + mEnableSyncPreference.setChecked(syncEnabled); + if (syncEnabled) { + mEnableSyncPreference.setSummary(R.string.cloud_sync_summary); + } else { + mEnableSyncPreference.setSummary(R.string.cloud_sync_summary_disabled); + } + AccountStateChangedListener.onSyncPreferenceChanged(getSignedInAccountName(), + syncEnabled); } } + /** + * Summarizes what account is being used and turns off dependent preferences if no account + * is currently selected. + */ private void refreshAccountAndDependentPreferences(@Nullable final String currentAccount) { if (!ProductionFlags.ENABLE_ACCOUNT_SIGN_IN) { return; @@ -122,61 +149,33 @@ public final class AccountsSettingsFragment extends SubScreenFragment { final Preference accountSwitcher = findPreference(PREF_ACCCOUNT_SWITCHER); if (currentAccount == null) { - // No account is currently selected. + // No account is currently selected; switch enable sync preference off. accountSwitcher.setSummary(getString(R.string.no_accounts_selected)); - // Disable the sync preference UI. - disableSyncPreference(); + mEnableSyncPreference.setChecked(false); } else { - // Set the currently selected account. + // Set the currently selected account as the summary text. accountSwitcher.setSummary(getString(R.string.account_selected, currentAccount)); - // Enable the sync preference UI. - enableSyncPreference(); } - // Set up onClick listener for the account picker preference. - final Context context = getActivity(); - final String[] accountsForLogin = LoginAccountUtils.getAccountsForLogin(context); + + // Set up on click listener for the account picker preference. accountSwitcher.setOnPreferenceClickListener(new OnPreferenceClickListener() { - @Override - public boolean onPreferenceClick(final Preference preference) { - if (accountsForLogin.length == 0) { - // TODO: Handle account addition. - Toast.makeText(getActivity(), getString(R.string.account_select_cancel), - Toast.LENGTH_SHORT).show(); - } else { - createAccountPicker(accountsForLogin, currentAccount).show(); + @Override + public boolean onPreferenceClick(final Preference preference) { + final String[] accountsForLogin = + LoginAccountUtils.getAccountsForLogin(getActivity()); + if (accountsForLogin.length == 0) { + // TODO: Handle account addition. + Toast.makeText(getActivity(), getString(R.string.account_select_cancel), + Toast.LENGTH_SHORT).show(); + } else { + createAccountPicker(accountsForLogin, currentAccount, + new AccountChangedListener(null)).show(); + } + return true; } - return true; - } }); } - /** - * Enables the Sync preference UI and updates its summary. - */ - private void enableSyncPreference() { - if (!ProductionFlags.ENABLE_USER_HISTORY_DICTIONARY_SYNC) { - return; - } - - final Preference syncPreference = findPreference(PREF_ENABLE_CLOUD_SYNC); - syncPreference.setEnabled(true); - syncPreference.setSummary(R.string.cloud_sync_summary); - } - - /** - * Disables the Sync preference UI and updates its summary to indicate - * the fact that an account needs to be selected for sync. - */ - private void disableSyncPreference() { - if (!ProductionFlags.ENABLE_USER_HISTORY_DICTIONARY_SYNC) { - return; - } - - final Preference syncPreference = findPreference(PREF_ENABLE_CLOUD_SYNC); - syncPreference.setEnabled(false); - syncPreference.setSummary(R.string.cloud_sync_summary_disabled_signed_out); - } - @Nullable String getSignedInAccountName() { return getSharedPreferences().getString(LocalSettingsConstants.PREF_ACCOUNT_NAME, null); @@ -188,14 +187,19 @@ public final class AccountsSettingsFragment extends SubScreenFragment { /** * Creates an account picker dialog showing the given accounts in a list and selecting - * the selected account by default. - * The list of accounts must not be null/empty. + * the selected account by default. The list of accounts must not be null/empty. * * Package-private for testing. + * + * @param accounts list of accounts on the device. + * @param selectedAccount currently selected account + * @param positiveButtonClickListener listener that gets called when positive button is + * clicked */ @UsedForTesting AlertDialog createAccountPicker(final String[] accounts, - final String selectedAccount) { + final String selectedAccount, + final DialogInterface.OnClickListener positiveButtonClickListener) { if (accounts == null || accounts.length == 0) { throw new IllegalArgumentException("List of accounts must not be empty"); } @@ -216,10 +220,10 @@ public final class AccountsSettingsFragment extends SubScreenFragment { final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()) .setTitle(R.string.account_select_title) .setSingleChoiceItems(accounts, index, null) - .setPositiveButton(R.string.account_select_ok, mAccountChangedListener) + .setPositiveButton(R.string.account_select_ok, positiveButtonClickListener) .setNegativeButton(R.string.account_select_cancel, null); if (isSignedIn) { - builder.setNeutralButton(R.string.account_select_sign_out, mAccountChangedListener); + builder.setNeutralButton(R.string.account_select_sign_out, positiveButtonClickListener); } return builder.create(); } @@ -229,6 +233,15 @@ public final class AccountsSettingsFragment extends SubScreenFragment { * Persists/removes the account to/from shared preferences and sets up sync if required. */ class AccountChangedListener implements DialogInterface.OnClickListener { + /** + * Represents preference that should be changed based on account chosen. + */ + private CheckBoxPreference mDependentPreference; + + AccountChangedListener(final CheckBoxPreference dependentPreference) { + mDependentPreference = dependentPreference; + } + @Override public void onClick(final DialogInterface dialog, final int which) { final String oldAccount = getSignedInAccountName(); @@ -242,6 +255,9 @@ public final class AccountsSettingsFragment extends SubScreenFragment { .putString(PREF_ACCOUNT_NAME, newAccount) .apply(); AccountStateChangedListener.onAccountSignedIn(oldAccount, newAccount); + if (mDependentPreference != null) { + mDependentPreference.setChecked(true); + } break; case DialogInterface.BUTTON_NEUTRAL: // Signed out AccountStateChangedListener.onAccountSignedOut(oldAccount); @@ -268,7 +284,7 @@ public final class AccountsSettingsFragment extends SubScreenFragment { /** * Listener that initiates the process of deleting user's data from the cloud. */ - class ClearSyncDataListener implements Preference.OnPreferenceClickListener { + class DeleteSyncDataListener implements Preference.OnPreferenceClickListener { @Override public boolean onPreferenceClick(final Preference preference) { final AlertDialog confirmationDialog = new AlertDialog.Builder(getActivity()) @@ -284,10 +300,49 @@ public final class AccountsSettingsFragment extends SubScreenFragment { } } }) - .setNegativeButton(R.string.clear_sync_data_cancel, null /* OnClickListener */) + .setNegativeButton(R.string.cloud_sync_cancel, null /* OnClickListener */) .create(); confirmationDialog.show(); return true; } } + + /** + * Listens to events when user clicks on "Enable sync" feature. + */ + class EnableSyncClickListener implements Preference.OnPreferenceClickListener { + @Override + public boolean onPreferenceClick(final Preference preference) { + final CheckBoxPreference syncPreference = (CheckBoxPreference) preference; + if (syncPreference.isChecked()) { + // Uncheck for now. + syncPreference.setChecked(false); + + // Show opt-in. + final AlertDialog optInDialog = new AlertDialog.Builder(getActivity()) + .setTitle(R.string.cloud_sync_title) + .setMessage(R.string.cloud_sync_opt_in_text) + .setPositiveButton(R.string.account_select_ok, + new DialogInterface.OnClickListener() { + @Override + public void onClick(final DialogInterface dialog, + final int which) { + if (which == DialogInterface.BUTTON_POSITIVE) { + final Context context = getActivity(); + final String[] accountsForLogin = + LoginAccountUtils.getAccountsForLogin(context); + createAccountPicker(accountsForLogin, + getSignedInAccountName(), + new AccountChangedListener(syncPreference)) + .show(); + } + } + }) + .setNegativeButton(R.string.cloud_sync_cancel, null) + .create(); + optInDialog.show(); + } + return true; + } + } } diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java index 9822c5725..f04f093f0 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidSpellCheckerService.java @@ -28,9 +28,7 @@ import android.util.Log; import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.KeyboardId; -import com.android.inputmethod.keyboard.KeyboardLayout; import com.android.inputmethod.keyboard.KeyboardLayoutSet; -import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.DictionaryFacilitator; import com.android.inputmethod.latin.DictionaryFacilitatorLruCache; import com.android.inputmethod.latin.NgramContext; @@ -48,6 +46,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Semaphore; +import javax.annotation.Nonnull; + /** * Service for spell checking, using LatinIME's dictionaries and mechanisms. */ @@ -193,7 +193,7 @@ public final class AndroidSpellCheckerService extends SpellCheckerService public SuggestionResults getSuggestionResults(final Locale locale, final ComposedData composedData, final NgramContext ngramContext, - final ProximityInfo proximityInfo, final KeyboardLayout keyboardLayout) { + @Nonnull final Keyboard keyboard) { Integer sessionId = null; mSemaphore.acquireUninterruptibly(); try { @@ -201,8 +201,8 @@ public final class AndroidSpellCheckerService extends SpellCheckerService DictionaryFacilitator dictionaryFacilitatorForLocale = mDictionaryFacilitatorCache.get(locale); return dictionaryFacilitatorForLocale.getSuggestionResults(composedData, ngramContext, - proximityInfo.getNativeProximityInfo(), mSettingsValuesForSuggestion, - sessionId, SuggestedWords.INPUT_STYLE_TYPING, keyboardLayout); + keyboard, mSettingsValuesForSuggestion, + sessionId, SuggestedWords.INPUT_STYLE_TYPING); } finally { if (sessionId != null) { mSessionIdPool.add(sessionId); diff --git a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java index 1c43a4b71..5c1915c6c 100644 --- a/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java +++ b/java/src/com/android/inputmethod/latin/spellcheck/AndroidWordLevelSpellCheckerSession.java @@ -29,18 +29,11 @@ import android.view.textservice.TextInfo; import com.android.inputmethod.compat.SuggestionsInfoCompatUtils; import com.android.inputmethod.keyboard.Keyboard; -import com.android.inputmethod.keyboard.KeyboardLayout; -import com.android.inputmethod.keyboard.ProximityInfo; import com.android.inputmethod.latin.NgramContext; -import com.android.inputmethod.latin.SuggestedWords; import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo; import com.android.inputmethod.latin.WordComposer; -import com.android.inputmethod.latin.common.ComposedData; import com.android.inputmethod.latin.common.Constants; -import com.android.inputmethod.latin.common.CoordinateUtils; -import com.android.inputmethod.latin.common.InputPointers; import com.android.inputmethod.latin.common.LocaleUtils; -import com.android.inputmethod.latin.common.ResizableIntArray; import com.android.inputmethod.latin.common.StringUtils; import com.android.inputmethod.latin.utils.BinaryDictionaryUtils; import com.android.inputmethod.latin.utils.ScriptUtils; @@ -272,26 +265,20 @@ public abstract class AndroidWordLevelSpellCheckerSession extends Session { false /* reportAsTypo */); } final Keyboard keyboard = mService.getKeyboardForLocale(mLocale); + if (null == keyboard) { + Log.d(TAG, "No keyboard for locale: " + mLocale); + // If there is no keyboard for this locale, don't do any spell-checking. + return AndroidSpellCheckerService.getNotInDictEmptySuggestions( + false /* reportAsTypo */); + } final WordComposer composer = new WordComposer(); final int[] codePoints = StringUtils.toCodePointArray(text); final int[] coordinates; - final ProximityInfo proximityInfo; - final KeyboardLayout keyboardLayout; - if (null == keyboard) { - coordinates = CoordinateUtils.newCoordinateArray(codePoints.length, - Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE); - proximityInfo = null; - keyboardLayout = null; - } else { - coordinates = keyboard.getCoordinates(codePoints); - proximityInfo = keyboard.getProximityInfo(); - keyboardLayout = keyboard.getKeyboardLayout(); - } + coordinates = keyboard.getCoordinates(codePoints); composer.setComposingWord(codePoints, coordinates); // TODO: Don't gather suggestions if the limit is <= 0 unless necessary final SuggestionResults suggestionResults = mService.getSuggestionResults( - mLocale, composer.getComposedDataSnapshot(), ngramContext, proximityInfo, - keyboardLayout); + mLocale, composer.getComposedDataSnapshot(), ngramContext, keyboard); final Result result = getResult(capitalizeType, mLocale, suggestionsLimit, mService.getRecommendedThreshold(), text, suggestionResults); isInDict = isInDictForAnyCapitalization(text, capitalizeType); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java index a9d1207f1..d8926ffba 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripLayoutHelper.java @@ -342,8 +342,11 @@ final class SuggestionStripLayoutHelper { * @param placerView the view where the debug info will be placed. * @return the start index of more suggestions. */ - public int layoutAndReturnStartIndexOfMoreSuggestions(final SuggestedWords suggestedWords, - final ViewGroup stripView, final ViewGroup placerView) { + public int layoutAndReturnStartIndexOfMoreSuggestions( + final Context context, + final SuggestedWords suggestedWords, + final ViewGroup stripView, + final ViewGroup placerView) { if (suggestedWords.isPunctuationSuggestions()) { return layoutPunctuationsAndReturnStartIndexOfMoreSuggestions( (PunctuationSuggestions)suggestedWords, stripView); @@ -362,7 +365,7 @@ final class SuggestionStripLayoutHelper { // by consolidating all slots in the strip. final int countInStrip = 1; mMoreSuggestionsAvailable = (wordCountToShow > countInStrip); - layoutWord(mCenterPositionInStrip, stripWidth - mPadding); + layoutWord(context, mCenterPositionInStrip, stripWidth - mPadding); stripView.addView(centerWordView); setLayoutWeight(centerWordView, 1.0f, ViewGroup.LayoutParams.MATCH_PARENT); if (SuggestionStripView.DBG) { @@ -385,7 +388,7 @@ final class SuggestionStripLayoutHelper { } final int width = getSuggestionWidth(positionInStrip, stripWidth); - final TextView wordView = layoutWord(positionInStrip, width); + final TextView wordView = layoutWord(context, positionInStrip, width); stripView.addView(wordView); setLayoutWeight(wordView, getSuggestionWeight(positionInStrip), ViewGroup.LayoutParams.MATCH_PARENT); @@ -414,7 +417,7 @@ final class SuggestionStripLayoutHelper { * @param width the maximum width for layout in pixels. * @return the {@link TextView} containing the suggested word appropriately formatted. */ - private TextView layoutWord(final int positionInStrip, final int width) { + private TextView layoutWord(final Context context, final int positionInStrip, final int width) { final TextView wordView = mWordViews.get(positionInStrip); final CharSequence word = wordView.getText(); if (positionInStrip == mCenterPositionInStrip && mMoreSuggestionsAvailable) { @@ -428,7 +431,10 @@ final class SuggestionStripLayoutHelper { } // {@link StyleSpan} in a content description may cause an issue of TTS/TalkBack. // Use a simple {@link String} to avoid the issue. - wordView.setContentDescription(TextUtils.isEmpty(word) ? null : word.toString()); + wordView.setContentDescription( + TextUtils.isEmpty(word) + ? context.getResources().getString(R.string.spoken_empty_suggestion) + : word.toString()); final CharSequence text = getEllipsizedTextWithSettingScaleX( word, width, wordView.getPaint()); final float scaleX = wordView.getTextScaleX(); diff --git a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java index 4b849496c..17525f650 100644 --- a/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java +++ b/java/src/com/android/inputmethod/latin/suggestions/SuggestionStripView.java @@ -146,6 +146,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick for (int pos = 0; pos < SuggestedWords.MAX_SUGGESTIONS; pos++) { final TextView word = new TextView(context, null, R.attr.suggestionWordStyle); + word.setContentDescription(getResources().getString(R.string.spoken_empty_suggestion)); word.setOnClickListener(this); word.setOnLongClickListener(this); mWordViews.add(word); @@ -200,7 +201,7 @@ public final class SuggestionStripView extends RelativeLayout implements OnClick mStripVisibilityGroup.setLayoutDirection(isRtlLanguage); mSuggestedWords = suggestedWords; mStartIndexOfMoreSuggestions = mLayoutHelper.layoutAndReturnStartIndexOfMoreSuggestions( - mSuggestedWords, mSuggestionsStrip, this); + getContext(), mSuggestedWords, mSuggestionsStrip, this); mStripVisibilityGroup.showSuggestionsStrip(); } diff --git a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java index 23ffde2a2..892b967c4 100644 --- a/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/BinaryDictionaryUtils.java @@ -21,7 +21,6 @@ import com.android.inputmethod.latin.BinaryDictionary; import com.android.inputmethod.latin.common.StringUtils; import com.android.inputmethod.latin.makedict.DictionaryHeader; import com.android.inputmethod.latin.makedict.UnsupportedFormatException; -import com.android.inputmethod.latin.personalization.PersonalizationHelper; import java.io.File; import java.io.IOException; @@ -123,8 +122,6 @@ public final class BinaryDictionaryUtils { */ @UsedForTesting public static int setCurrentTimeForTest(final int currentTime) { - final int currentNativeTimestamp = setCurrentTimeForTestNative(currentTime); - PersonalizationHelper.currentTimeChangedForTesting(currentNativeTimestamp); - return currentNativeTimestamp; + return setCurrentTimeForTestNative(currentTime); } } diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java index 293623cae..3ed6a021e 100644 --- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java @@ -153,7 +153,7 @@ public class DictionaryInfoUtils { } /** - * Reverse escaping done by replaceFileNameDangerousCharacters. + * Reverse escaping done by {@link #replaceFileNameDangerousCharacters(String)}. */ @Nonnull public static String getWordListIdFromFileName(@Nonnull final String fname) { diff --git a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java index 10e3994b6..981355115 100644 --- a/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java +++ b/java/src/com/android/inputmethod/latin/utils/SuggestionResults.java @@ -33,21 +33,18 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> { // TODO: Instead of a boolean , we may want to include the context of this suggestion results, // such as {@link NgramContext}. public final boolean mIsBeginningOfSentence; - public final boolean mAutocorrectRecommendation; + public final boolean mFirstSuggestionExceedsConfidenceThreshold; private final int mCapacity; - public SuggestionResults(final int capacity, final boolean isBeginningOfSentence) { - this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence, false); - } - public SuggestionResults(final int capacity, final boolean isBeginningOfSentence, - final boolean autocorrectRecommendation) { + final boolean firstSuggestionExceedsConfidenceThreshold) { this(sSuggestedWordInfoComparator, capacity, isBeginningOfSentence, - autocorrectRecommendation); + firstSuggestionExceedsConfidenceThreshold); } private SuggestionResults(final Comparator<SuggestedWordInfo> comparator, final int capacity, - final boolean isBeginningOfSentence, final boolean autocorrectRecommendation) { + final boolean isBeginningOfSentence, + final boolean firstSuggestionExceedsConfidenceThreshold) { super(comparator); mCapacity = capacity; if (ProductionFlags.INCLUDE_RAW_SUGGESTIONS) { @@ -56,7 +53,7 @@ public final class SuggestionResults extends TreeSet<SuggestedWordInfo> { mRawSuggestions = null; } mIsBeginningOfSentence = isBeginningOfSentence; - mAutocorrectRecommendation = autocorrectRecommendation; + mFirstSuggestionExceedsConfidenceThreshold = firstSuggestionExceedsConfidenceThreshold; } @Override |