diff options
Diffstat (limited to 'java/src/com')
9 files changed, 164 insertions, 145 deletions
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java index aa8bb2ccb..f733a9a6b 100644 --- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java +++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java @@ -410,6 +410,7 @@ public class DictionaryFacilitatorForSuggest { final int sessionId, final Set<SuggestedWordInfo> suggestionSet) { for (final String key : mDictionaries.keySet()) { final Dictionary dictionary = mDictionaries.get(key); + if (null == dictionary) continue; suggestionSet.addAll(dictionary.getSuggestionsWithSessionId(composer, prevWord, proximityInfo, blockOffensiveWords, additionalFeaturesOptions, sessionId)); } diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java index f785835b8..7757d2910 100644 --- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java +++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java @@ -282,7 +282,9 @@ abstract public class ExpandableBinaryDictionary extends Dictionary { @Override public void run() { if (mDictionaryWriter == null) { - mBinaryDictionary.close(); + if (mBinaryDictionary != null) { + mBinaryDictionary.close(); + } final File file = getDictFile(); if (file.exists() && !FileUtils.deleteRecursively(file)) { Log.e(TAG, "Can't remove a file: " + file.getName()); diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java index 3984c197a..40391694c 100644 --- a/java/src/com/android/inputmethod/latin/LatinIME.java +++ b/java/src/com/android/inputmethod/latin/LatinIME.java @@ -202,7 +202,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen break; case MSG_RESUME_SUGGESTIONS: latinIme.mInputLogic.restartSuggestionsOnWordTouchedByCursor( - latinIme.mSettings.getCurrent(), 0 /* offset */, + latinIme.mSettings.getCurrent(), false /* includeResumedWordInSuggestions */, latinIme.mKeyboardSwitcher); break; case MSG_REOPEN_DICTIONARIES: @@ -880,8 +880,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen // Notify ResearchLogger if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_onFinishInputViewInternal(finishingInput, - mInputLogic.mLastSelectionStart, - mInputLogic.mLastSelectionEnd, getCurrentInputConnection()); + // TODO[IL]: mInputLogic.mConnection should be private + mInputLogic.mConnection.getExpectedSelectionStart(), + mInputLogic.mConnection.getExpectedSelectionEnd(), getCurrentInputConnection()); } } @@ -894,22 +895,18 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen if (DEBUG) { Log.i(TAG, "onUpdateSelection: oss=" + oldSelStart + ", ose=" + oldSelEnd - + ", lss=" + mInputLogic.mLastSelectionStart - + ", lse=" + mInputLogic.mLastSelectionEnd + ", nss=" + newSelStart + ", nse=" + newSelEnd + ", cs=" + composingSpanStart + ", ce=" + composingSpanEnd); } if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { - ResearchLogger.latinIME_onUpdateSelection(mInputLogic.mLastSelectionStart, - mInputLogic.mLastSelectionEnd, + ResearchLogger.latinIME_onUpdateSelection(oldSelStart, oldSelEnd, oldSelStart, oldSelEnd, newSelStart, newSelEnd, composingSpanStart, composingSpanEnd, mInputLogic.mConnection); } - final boolean selectionChanged = mInputLogic.mLastSelectionStart != newSelStart - || mInputLogic.mLastSelectionEnd != newSelEnd; + final boolean selectionChanged = oldSelStart != newSelStart || oldSelEnd != newSelEnd; // if composingSpanStart and composingSpanEnd are -1, it means there is no composing // span in the view - we can use that to narrow down whether the cursor was moved @@ -972,9 +969,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen mKeyboardSwitcher.updateShiftState(); } - // Make a note of the cursor position - mInputLogic.mLastSelectionStart = newSelStart; - mInputLogic.mLastSelectionEnd = newSelEnd; mSubtypeState.currentSubtypeUsed(); } diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java index 67ea2991c..79d66744b 100644 --- a/java/src/com/android/inputmethod/latin/RichInputConnection.java +++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java @@ -174,13 +174,15 @@ public final class RichInputConnection { } final int lengthOfTextBeforeCursor = mCommittedTextBeforeComposingText.length(); if (lengthOfTextBeforeCursor > newSelStart - || (lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE + || (newSelStart != lengthOfTextBeforeCursor + && lengthOfTextBeforeCursor < Constants.EDITOR_CONTENTS_CACHE_SIZE && newSelStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { // newSelStart and newSelEnd may be lying -- when rotating the device (probably a - // framework bug). If we have less chars than we asked for, then we know how many chars - // we have, and if we got more than newSelStart says, then we know it was lying. In both - // cases the length is more reliable. Note that we only have to check newSelStart (not - // newSelEnd) since if newSelEnd is wrong, the newSelStart will be wrong as well. + // framework bug). If the values don't agree and we have less chars than we asked + // for, then we know how many chars we have. If we got more than newSelStart says, then + // we also know it was lying. In both cases the length is more reliable. Note that we + // only have to check newSelStart (not newSelEnd) since if newSelEnd is wrong, then + // newSelStart will be wrong as well. mExpectedSelStart = lengthOfTextBeforeCursor; mExpectedSelEnd = lengthOfTextBeforeCursor; } @@ -783,17 +785,17 @@ public final class RichInputConnection { */ public boolean isBelatedExpectedUpdate(final int oldSelStart, final int newSelStart, final int oldSelEnd, final int newSelEnd) { - // This update is "belated" if we are expecting it. That is, mExpectedSelStart and + // This update is "belated" if we are expecting it. That is, mExpectedSelStart and // mExpectedSelEnd match the new values that the TextView is updating TO. if (mExpectedSelStart == newSelStart && mExpectedSelEnd == newSelEnd) return true; - // This update is not belated if mExpectedSelStart and mExpeectedSelend match the old - // values, and one of newSelStart or newSelEnd is updated to a different value. In this - // case, there is likely something other than the IME that has moved the selection endpoint + // This update is not belated if mExpectedSelStart and mExpectedSelEnd match the old + // values, and one of newSelStart or newSelEnd is updated to a different value. In this + // case, there is likely something other than the IME has moved the selection endpoint // to the new value. if (mExpectedSelStart == oldSelStart && mExpectedSelEnd == oldSelEnd && (oldSelStart != newSelStart || oldSelEnd != newSelEnd)) return false; // If nether of the above two cases holds, then the system may be having trouble keeping up - // with updates. If 1) the selection is a cursor, 2) newSelStart is between oldSelStart + // with updates. If 1) the selection is a cursor, 2) newSelStart is between oldSelStart // and mExpectedSelStart, and 3) newSelEnd is between oldSelEnd and mExpectedSelEnd, then // assume a belated update. return (newSelStart == newSelEnd) @@ -811,4 +813,54 @@ public final class RichInputConnection { public boolean textBeforeCursorLooksLikeURL() { return StringUtils.lastPartLooksLikeURL(mCommittedTextBeforeComposingText); } + + /** + * Try to get the text from the editor to expose lies the framework may have been + * telling us. Concretely, when the device rotates, the frameworks tells us about where the + * cursor used to be initially in the editor at the time it first received the focus; this + * may be completely different from the place it is upon rotation. Since we don't have any + * means to get the real value, try at least to ask the text view for some characters and + * detect the most damaging cases: when the cursor position is declared to be much smaller + * than it really is. + */ + public void tryFixLyingCursorPosition() { + final CharSequence textBeforeCursor = getTextBeforeCursor( + Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); + if (null == textBeforeCursor) { + mExpectedSelStart = mExpectedSelEnd = Constants.NOT_A_CURSOR_POSITION; + } else { + final int textLength = textBeforeCursor.length(); + if (textLength > mExpectedSelStart + || (textLength < Constants.EDITOR_CONTENTS_CACHE_SIZE + && mExpectedSelStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { + // It should not be possible to have only one of those variables be + // NOT_A_CURSOR_POSITION, so if they are equal, either the selection is zero-sized + // (simple cursor, no selection) or there is no cursor/we don't know its pos + final boolean wasEqual = mExpectedSelStart == mExpectedSelEnd; + mExpectedSelStart = textLength; + // We can't figure out the value of mLastSelectionEnd :( + // But at least if it's smaller than mLastSelectionStart something is wrong, + // and if they used to be equal we also don't want to make it look like there is a + // selection. + if (wasEqual || mExpectedSelStart > mExpectedSelEnd) { + mExpectedSelEnd = mExpectedSelStart; + } + } + } + } + + public int getExpectedSelectionStart() { + return mExpectedSelStart; + } + + public int getExpectedSelectionEnd() { + return mExpectedSelEnd; + } + + /** + * @return whether there is a selection currently active. + */ + public boolean hasSelection() { + return mExpectedSelEnd != mExpectedSelStart; + } } diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java index 92b6a8544..55e92cc09 100644 --- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java +++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java @@ -86,10 +86,6 @@ public final class InputLogic { public final RichInputConnection mConnection; public final RecapitalizeStatus mRecapitalizeStatus = new RecapitalizeStatus(); - // Keep track of the last selection range to decide if we need to show word alternatives - public int mLastSelectionStart = Constants.NOT_A_CURSOR_POSITION; - public int mLastSelectionEnd = Constants.NOT_A_CURSOR_POSITION; - private int mDeleteCount; private long mLastKeyTime; public final TreeSet<Long> mCurrentlyPressedHardwareKeys = CollectionUtils.newTreeSet(); @@ -129,11 +125,9 @@ public final class InputLogic { mRecapitalizeStatus.deactivate(); mCurrentlyPressedHardwareKeys.clear(); mSuggestedWords = SuggestedWords.EMPTY; - mLastSelectionStart = editorInfo.initialSelStart; - mLastSelectionEnd = editorInfo.initialSelEnd; // In some cases (namely, after rotation of the device) editorInfo.initialSelStart is lying // so we try using some heuristics to find out about these and fix them. - tryFixLyingCursorPosition(); + mConnection.tryFixLyingCursorPosition(); mInputLogicHandler = new InputLogicHandler(mLatinIME, this); } @@ -337,7 +331,8 @@ public final class InputLogic { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the batch input at the current cursor position. - resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd()); } else if (wordComposerSize <= 1) { // We auto-correct the previous (typed, not gestured) string iff it's one character // long. The reason for this is, even in the middle of gesture typing, you'll still @@ -466,7 +461,8 @@ public final class InputLogic { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the character at the current cursor position. - resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd()); } else { commitTyped(settingsValues, LastComposedWord.NOT_A_SEPARATOR); } @@ -516,7 +512,8 @@ public final class InputLogic { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the character at the current cursor position. - resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd()); isComposingWord = false; } // We want to find out whether to start composing a new word with this character. If so, @@ -603,7 +600,8 @@ public final class InputLogic { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can insert the separator at the current cursor position. - resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd()); } // isComposingWord() may have changed since we stored wasComposing if (mWordComposer.isComposingWord()) { @@ -695,7 +693,8 @@ public final class InputLogic { if (mWordComposer.isCursorFrontOrMiddleOfComposingWord()) { // If we are in the middle of a recorrection, we need to commit the recorrection // first so that we can remove the character at the current cursor position. - resetEntireInputState(settingsValues, mLastSelectionStart, mLastSelectionEnd); + resetEntireInputState(settingsValues, mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd()); // When we exit this if-clause, mWordComposer.isComposingWord() will return false. } if (mWordComposer.isComposingWord()) { @@ -755,15 +754,12 @@ public final class InputLogic { // No cancelling of commit/double space/swap: we have a regular backspace. // We should backspace one char and restart suggestion if at the end of a word. - if (mLastSelectionStart != mLastSelectionEnd) { + if (mConnection.hasSelection()) { // If there is a selection, remove it. - final int numCharsDeleted = mLastSelectionEnd - mLastSelectionStart; - mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd); - // Reset mLastSelectionEnd to mLastSelectionStart. This is what is supposed to - // happen, and if it's wrong, the next call to onUpdateSelection will correct it, - // but we want to set it right away to avoid it being used with the wrong values - // later (typically, in a subsequent press on backspace). - mLastSelectionEnd = mLastSelectionStart; + final int numCharsDeleted = mConnection.getExpectedSelectionEnd() + - mConnection.getExpectedSelectionStart(); + mConnection.setSelection(mConnection.getExpectedSelectionEnd(), + mConnection.getExpectedSelectionEnd()); mConnection.deleteSurroundingText(numCharsDeleted, 0); if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) { ResearchLogger.latinIME_handleBackspace(numCharsDeleted, @@ -771,7 +767,7 @@ public final class InputLogic { } } else { // There is no selection, just delete one character. - if (Constants.NOT_A_CURSOR_POSITION == mLastSelectionEnd) { + if (Constants.NOT_A_CURSOR_POSITION == mConnection.getExpectedSelectionEnd()) { // This should never happen. Log.e(TAG, "Backspace when we don't know the selection position"); } @@ -820,7 +816,6 @@ public final class InputLogic { && settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces && !mConnection.isCursorFollowedByWordCharacter(settingsValues)) { restartSuggestionsOnWordTouchedByCursor(settingsValues, - deleteCountAtStart - mDeleteCount /* offset */, true /* includeResumedWordInSuggestions */, keyboardSwitcher); } // We just removed at least one character. We need to update the auto-caps state. @@ -960,38 +955,32 @@ public final class InputLogic { * @param settingsValues The current settings values. */ private void performRecapitalization(final SettingsValues settingsValues) { - if (mLastSelectionStart == mLastSelectionEnd) { + if (!mConnection.hasSelection()) { return; // No selection } // If we have a recapitalize in progress, use it; otherwise, create a new one. if (!mRecapitalizeStatus.isActive() - || !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) { + || !mRecapitalizeStatus.isSetAt(mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd())) { final CharSequence selectedText = mConnection.getSelectedText(0 /* flags, 0 for no styles */); if (TextUtils.isEmpty(selectedText)) return; // Race condition with the input connection - mRecapitalizeStatus.initialize(mLastSelectionStart, mLastSelectionEnd, - selectedText.toString(), + mRecapitalizeStatus.initialize(mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd(), selectedText.toString(), settingsValues.mLocale, settingsValues.mSpacingAndPunctuations.mWordSeparators); // We trim leading and trailing whitespace. mRecapitalizeStatus.trim(); - // Trimming the object may have changed the length of the string, and we need to - // reposition the selection handles accordingly. As this result in an IPC call, - // only do it if it's actually necessary, in other words if the recapitalize status - // is not set at the same place as before. - if (!mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) { - mLastSelectionStart = mRecapitalizeStatus.getNewCursorStart(); - mLastSelectionEnd = mRecapitalizeStatus.getNewCursorEnd(); - } } mConnection.finishComposingText(); mRecapitalizeStatus.rotate(); - final int numCharsDeleted = mLastSelectionEnd - mLastSelectionStart; - mConnection.setSelection(mLastSelectionEnd, mLastSelectionEnd); + final int numCharsDeleted = mConnection.getExpectedSelectionEnd() + - mConnection.getExpectedSelectionStart(); + mConnection.setSelection(mConnection.getExpectedSelectionEnd(), + mConnection.getExpectedSelectionEnd()); mConnection.deleteSurroundingText(numCharsDeleted, 0); mConnection.commitText(mRecapitalizeStatus.getRecapitalizedString(), 0); - mLastSelectionStart = mRecapitalizeStatus.getNewCursorStart(); - mLastSelectionEnd = mRecapitalizeStatus.getNewCursorEnd(); - mConnection.setSelection(mLastSelectionStart, mLastSelectionEnd); + mConnection.setSelection(mRecapitalizeStatus.getNewCursorStart(), + mRecapitalizeStatus.getNewCursorEnd()); } private void performAdditionToUserHistoryDictionary(final SettingsValues settingsValues, @@ -1053,13 +1042,12 @@ public final class InputLogic { * do nothing. * * @param settingsValues the current values of the settings. - * @param offset how much the cursor is expected to have moved since the last updateSelection. * @param includeResumedWordInSuggestions whether to include the word on which we resume * suggestions in the suggestion list. */ // TODO: make this private. public void restartSuggestionsOnWordTouchedByCursor(final SettingsValues settingsValues, - final int offset, final boolean includeResumedWordInSuggestions, + final boolean includeResumedWordInSuggestions, // TODO: Remove this argument. final KeyboardSwitcher keyboardSwitcher) { // HACK: We may want to special-case some apps that exhibit bad behavior in case of @@ -1072,10 +1060,10 @@ public final class InputLogic { // how to segment them yet. if (!settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) return; // If the cursor is not touching a word, or if there is a selection, return right away. - if (mLastSelectionStart != mLastSelectionEnd) return; + if (mConnection.hasSelection()) return; // If we don't know the cursor location, return. - if (mLastSelectionStart < 0) return; - final int expectedCursorPosition = mLastSelectionStart + offset; // We know Start == End + if (mConnection.getExpectedSelectionStart() < 0) return; + final int expectedCursorPosition = mConnection.getExpectedSelectionStart(); if (!mConnection.isCursorTouchingWord(settingsValues)) return; final TextRange range = mConnection.getWordRangeAtCursor( settingsValues.mSpacingAndPunctuations.mWordSeparators, @@ -1119,19 +1107,8 @@ public final class InputLogic { keyboardSwitcher.getKeyboard()); mWordComposer.setCursorPositionWithinWord( typedWord.codePointCount(0, numberOfCharsInWordBeforeCursor)); - // TODO: Change these lines to setComposingRegion(cursorPosition, - // cursorPosition + range.getNumberOfCharsInWordAfterCursor()); - if (0 != offset) { - // Backspace was pressed. We are at the end of a word, and we don't know the cursor - // position for sure, so use relative methods. - mConnection.deleteSurroundingText(numberOfCharsInWordBeforeCursor, 0); - mConnection.setComposingText(typedWord, 1); - } else { - // This is recorrection. The cursor position is reasonably reliable, and the cursor - // may be in the middle of a word so use setComposingRegion. - mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor, + mConnection.setComposingRegion(expectedCursorPosition - numberOfCharsInWordBeforeCursor, expectedCursorPosition + range.getNumberOfCharsInWordAfterCursor()); - } if (suggestions.isEmpty()) { // We come here if there weren't any suggestion spans on this word. We will try to // compute suggestions for it instead. @@ -1289,7 +1266,8 @@ public final class InputLogic { public int getCurrentRecapitalizeState() { if (!mRecapitalizeStatus.isActive() - || !mRecapitalizeStatus.isSetAt(mLastSelectionStart, mLastSelectionEnd)) { + || !mRecapitalizeStatus.isSetAt(mConnection.getExpectedSelectionStart(), + mConnection.getExpectedSelectionEnd())) { // Not recapitalizing at the moment return RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE; } @@ -1642,7 +1620,8 @@ public final class InputLogic { // of the auto-correction flash. At this moment, the "typedWord" argument is // ignored by TextView. mConnection.commitCorrection( - new CorrectionInfo(mLastSelectionEnd - typedWord.length(), + new CorrectionInfo( + mConnection.getExpectedSelectionEnd() - typedWord.length(), typedWord, autoCorrection)); } } @@ -1691,41 +1670,6 @@ public final class InputLogic { } /** - * Try to get the text from the editor to expose lies the framework may have been - * telling us. Concretely, when the device rotates, the frameworks tells us about where the - * cursor used to be initially in the editor at the time it first received the focus; this - * may be completely different from the place it is upon rotation. Since we don't have any - * means to get the real value, try at least to ask the text view for some characters and - * detect the most damaging cases: when the cursor position is declared to be much smaller - * than it really is. - */ - private void tryFixLyingCursorPosition() { - final CharSequence textBeforeCursor = mConnection.getTextBeforeCursor( - Constants.EDITOR_CONTENTS_CACHE_SIZE, 0); - if (null == textBeforeCursor) { - mLastSelectionStart = mLastSelectionEnd = Constants.NOT_A_CURSOR_POSITION; - } else { - final int textLength = textBeforeCursor.length(); - if (textLength > mLastSelectionStart - || (textLength < Constants.EDITOR_CONTENTS_CACHE_SIZE - && mLastSelectionStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) { - // It should not be possible to have only one of those variables be - // NOT_A_CURSOR_POSITION, so if they are equal, either the selection is zero-sized - // (simple cursor, no selection) or there is no cursor/we don't know its pos - final boolean wasEqual = mLastSelectionStart == mLastSelectionEnd; - mLastSelectionStart = textLength; - // We can't figure out the value of mLastSelectionEnd :( - // But at least if it's smaller than mLastSelectionStart something is wrong, - // and if they used to be equal we also don't want to make it look like there is a - // selection. - if (wasEqual || mLastSelectionStart > mLastSelectionEnd) { - mLastSelectionEnd = mLastSelectionStart; - } - } - } - } - - /** * Retry resetting caches in the rich input connection. * * When the editor can't be accessed we can't reset the caches, so we schedule a retry. @@ -1742,7 +1686,8 @@ public final class InputLogic { // TODO: remove these arguments final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) { if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess( - mLastSelectionStart, mLastSelectionEnd, false)) { + mConnection.getExpectedSelectionStart(), mConnection.getExpectedSelectionEnd(), + false)) { if (0 < remainingTries) { handler.postResetCaches(tryResumeSuggestions, remainingTries - 1); return; @@ -1750,7 +1695,7 @@ public final class InputLogic { // If remainingTries is 0, we should stop waiting for new tries, but it's still // better to load the keyboard (less things will be broken). } - tryFixLyingCursorPosition(); + mConnection.tryFixLyingCursorPosition(); keyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), settingsValues); if (tryResumeSuggestions) { handler.postResumeSuggestions(); diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java index 61354762b..3eb8f35a9 100644 --- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java +++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java @@ -57,7 +57,7 @@ public abstract class PersonalizationDictionaryUpdateSession { dictionary.unRegisterUpdateSession(this); } - public void clearAndFlushDictionary(final Context context) { + public void clearAndFlushDictionary() { final PersonalizationDictionary dictionary = getDictionary(); if (dictionary == null) { return; diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java index add983b3b..7db10714a 100644 --- a/java/src/com/android/inputmethod/latin/settings/Settings.java +++ b/java/src/com/android/inputmethod/latin/settings/Settings.java @@ -31,7 +31,9 @@ import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.RunInLocale; import com.android.inputmethod.latin.utils.StringUtils; +import java.util.Collections; import java.util.Locale; +import java.util.Set; import java.util.concurrent.locks.ReentrantLock; public final class Settings implements SharedPreferences.OnSharedPreferenceChangeListener { @@ -93,6 +95,10 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang private static final String PREF_LAST_USED_PERSONALIZATION_TOKEN = "pref_last_used_personalization_token"; + private static final String PREF_LAST_PERSONALIZATION_DICT_WIPED_TIME = + "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"; @@ -372,6 +378,23 @@ public final class Settings implements SharedPreferences.OnSharedPreferenceChang return StringUtils.hexStringToByteArray(tokenStr); } + public void writeLastPersonalizationDictWipedTime(final long timestamp) { + mPrefs.edit().putLong(PREF_LAST_PERSONALIZATION_DICT_WIPED_TIME, timestamp).apply(); + } + + public long readLastPersonalizationDictGeneratedTime() { + return mPrefs.getLong(PREF_LAST_PERSONALIZATION_DICT_WIPED_TIME, 0); + } + + public void writeCorpusHandlesForPersonalization(final Set<String> corpusHandles) { + mPrefs.edit().putStringSet(PREF_CORPUS_HANDLES_FOR_PERSONALIZATION, corpusHandles).apply(); + } + + public Set<String> readCorpusHandlesForPersonalization() { + final Set<String> emptySet = Collections.emptySet(); + return mPrefs.getStringSet(PREF_CORPUS_HANDLES_FOR_PERSONALIZATION, emptySet); + } + public static void writeEmojiRecentKeys(final SharedPreferences prefs, String str) { prefs.edit().putString(PREF_EMOJI_RECENT_KEYS, str).apply(); } diff --git a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java index 3daa63ff4..b3c787e44 100644 --- a/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/DictionaryInfoUtils.java @@ -20,13 +20,16 @@ import android.content.ContentValues; import android.content.Context; import android.content.res.AssetManager; import android.content.res.Resources; +import android.text.TextUtils; import android.util.Log; +import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.AssetFileAddress; import com.android.inputmethod.latin.BinaryDictionaryGetter; import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.makedict.BinaryDictIOUtils; import com.android.inputmethod.latin.makedict.FormatSpec.FileHeader; +import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import java.io.File; import java.util.ArrayList; @@ -364,4 +367,29 @@ public class DictionaryInfoUtils { return dictList; } + + @UsedForTesting + public static boolean looksValidForDictionaryInsertion(final CharSequence text, + final SpacingAndPunctuations spacingAndPunctuations) { + if (TextUtils.isEmpty(text)) return false; + final int length = text.length(); + int i = 0; + int digitCount = 0; + while (i < length) { + final int codePoint = Character.codePointAt(text, i); + final int charCount = Character.charCount(codePoint); + i += charCount; + if (Character.isDigit(codePoint)) { + // Count digits: see below + digitCount += charCount; + continue; + } + if (!spacingAndPunctuations.isWordCodePoint(codePoint)) return false; + } + // We reject strings entirely comprised of digits to avoid using PIN codes or credit + // card numbers. It would come in handy for word prediction though; a good example is + // when writing one's address where the street number is usually quite discriminative, + // as well as the postal code. + return digitCount < length; + } } diff --git a/java/src/com/android/inputmethod/latin/utils/StringUtils.java b/java/src/com/android/inputmethod/latin/utils/StringUtils.java index 0042d8b42..c5ed39310 100644 --- a/java/src/com/android/inputmethod/latin/utils/StringUtils.java +++ b/java/src/com/android/inputmethod/latin/utils/StringUtils.java @@ -20,7 +20,6 @@ import android.text.TextUtils; import com.android.inputmethod.annotations.UsedForTesting; import com.android.inputmethod.latin.Constants; -import com.android.inputmethod.latin.settings.SpacingAndPunctuations; import java.util.ArrayList; import java.util.Locale; @@ -265,31 +264,6 @@ public final class StringUtils { return true; } - @UsedForTesting - public static boolean looksValidForDictionaryInsertion(final CharSequence text, - final SpacingAndPunctuations spacingAndPunctuations) { - if (TextUtils.isEmpty(text)) return false; - final int length = text.length(); - int i = 0; - int digitCount = 0; - while (i < length) { - final int codePoint = Character.codePointAt(text, i); - final int charCount = Character.charCount(codePoint); - i += charCount; - if (Character.isDigit(codePoint)) { - // Count digits: see below - digitCount += charCount; - continue; - } - if (!spacingAndPunctuations.isWordCodePoint(codePoint)) return false; - } - // We reject strings entirely comprised of digits to avoid using PIN codes or credit - // card numbers. It would come in handy for word prediction though; a good example is - // when writing one's address where the street number is usually quite discriminative, - // as well as the postal code. - return digitCount < length; - } - public static boolean isIdenticalAfterCapitalizeEachWord(final String text, final String separators) { boolean needCapsNext = true; |