aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java12
-rw-r--r--java/src/com/android/inputmethod/latin/BinaryDictionary.java63
-rw-r--r--java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java29
-rw-r--r--java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java5
-rw-r--r--java/src/com/android/inputmethod/latin/LastComposedWord.java4
-rw-r--r--java/src/com/android/inputmethod/latin/LatinIME.java14
-rw-r--r--java/src/com/android/inputmethod/latin/WordComposer.java13
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java56
-rw-r--r--java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java3
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java2
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java15
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java86
-rw-r--r--java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java7
-rw-r--r--java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java171
14 files changed, 278 insertions, 202 deletions
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index b8d1651dc..a32d76c30 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -74,7 +74,6 @@ public final class SuggestionSpanUtils {
return pickedWord;
}
- boolean hasSuggestionFromMainDictionary = false;
final ArrayList<String> suggestionsList = CollectionUtils.newArrayList();
for (int i = 0; i < suggestedWords.size(); ++i) {
if (suggestionsList.size() >= SuggestionSpan.SUGGESTIONS_MAX_SIZE) {
@@ -84,22 +83,11 @@ public final class SuggestionSpanUtils {
if (info.mKind == SuggestedWordInfo.KIND_PREDICTION) {
continue;
}
- if (info.mSourceDict.mDictType == Dictionary.TYPE_MAIN) {
- hasSuggestionFromMainDictionary = true;
- }
final String word = suggestedWords.getWord(i);
if (!TextUtils.equals(pickedWord, word)) {
suggestionsList.add(word.toString());
}
}
- if (!hasSuggestionFromMainDictionary) {
- // If we don't have any suggestions from the dictionary, it probably looks bad
- // enough as it is already because suggestions come pretty much only from contacts.
- // Let's not embed these bad suggestions in the text view so as to avoid using
- // them with recorrection.
- return pickedWord;
- }
-
final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
suggestionsList.toArray(new String[suggestionsList.size()]), 0 /* flags */,
SuggestionSpanPickedNotificationReceiver.class);
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 708f75a06..e66cfca49 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -25,6 +25,7 @@ import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.settings.NativeSuggestOptions;
import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.JniUtils;
+import com.android.inputmethod.latin.utils.LanguageModelParam;
import com.android.inputmethod.latin.utils.StringUtils;
import com.android.inputmethod.latin.utils.UnigramProperty;
@@ -164,6 +165,7 @@ public final class BinaryDictionary extends Dictionary {
LanguageModelParam[] languageModelParams, int startIndex);
private static native int calculateProbabilityNative(long dict, int unigramProbability,
int bigramProbability);
+ private static native int setCurrentTimeForTestNative(int currentTime);
private static native String getPropertyNative(long dict, String query);
@UsedForTesting
@@ -364,51 +366,6 @@ public final class BinaryDictionary extends Dictionary {
removeBigramWordsNative(mNativeDict, codePoints0, codePoints1);
}
- public static class LanguageModelParam {
- public final String mTargetWord;
- public final int[] mWord0;
- public final int[] mWord1;
- // TODO: this needs to be a list of shortcuts
- public final int[] mShortcutTarget;
- public final int mUnigramProbability;
- public final int mBigramProbability;
- public final int mShortcutProbability;
- public final boolean mIsNotAWord;
- public final boolean mIsBlacklisted;
- public final int mTimestamp;
-
- // Constructor for unigram. TODO: support shortcuts
- public LanguageModelParam(final String word, final int unigramProbability,
- final int timestamp) {
- mTargetWord = word;
- mWord0 = null;
- mWord1 = StringUtils.toCodePointArray(word);
- mShortcutTarget = null;
- mUnigramProbability = unigramProbability;
- mBigramProbability = NOT_A_PROBABILITY;
- mShortcutProbability = NOT_A_PROBABILITY;
- mIsNotAWord = false;
- mIsBlacklisted = false;
- mTimestamp = timestamp;
- }
-
- // Constructor for unigram and bigram.
- public LanguageModelParam(final String word0, final String word1,
- final int unigramProbability, final int bigramProbability,
- final int timestamp) {
- mTargetWord = word1;
- mWord0 = StringUtils.toCodePointArray(word0);
- mWord1 = StringUtils.toCodePointArray(word1);
- mShortcutTarget = null;
- mUnigramProbability = unigramProbability;
- mBigramProbability = bigramProbability;
- mShortcutProbability = NOT_A_PROBABILITY;
- mIsNotAWord = false;
- mIsBlacklisted = false;
- mTimestamp = timestamp;
- }
- }
-
public void addMultipleDictionaryEntries(final LanguageModelParam[] languageModelParams) {
if (!isValidDictionary()) return;
int processedParamCount = 0;
@@ -464,8 +421,22 @@ public final class BinaryDictionary extends Dictionary {
return calculateProbabilityNative(mNativeDict, unigramProbability, bigramProbability);
}
+ /**
+ * Control the current time to be used in the native code. If currentTime >= 0, this method sets
+ * the current time and gets into test mode.
+ * In test mode, set timestamp is used as the current time in the native code.
+ * If currentTime < 0, quit the test mode and returns to using time() to get the current time.
+ *
+ * @param currentTime seconds since the unix epoch
+ * @return current time got in the native code.
+ */
+ @UsedForTesting
+ public static int setCurrentTimeForTest(final int currentTime) {
+ return setCurrentTimeForTestNative(currentTime);
+ }
+
@UsedForTesting
- public String getPropertyForTests(String query) {
+ public String getPropertyForTest(final String query) {
if (!isValidDictionary()) return "";
return getPropertyNative(mNativeDict, query);
}
diff --git a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
index 7e4f0e85c..fb9517220 100644
--- a/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
+++ b/java/src/com/android/inputmethod/latin/DictionaryFacilitatorForSuggest.java
@@ -28,6 +28,7 @@ import com.android.inputmethod.latin.personalization.PersonalizationHelper;
import com.android.inputmethod.latin.personalization.UserHistoryDictionary;
import com.android.inputmethod.latin.settings.SettingsValues;
import com.android.inputmethod.latin.utils.CollectionUtils;
+import com.android.inputmethod.latin.utils.LanguageModelParam;
import java.io.File;
import java.util.ArrayList;
@@ -44,7 +45,7 @@ public class DictionaryFacilitatorForSuggest {
public static final String TAG = DictionaryFacilitatorForSuggest.class.getSimpleName();
private final Context mContext;
- private final Locale mLocale;
+ public final Locale mLocale;
private final ConcurrentHashMap<String, Dictionary> mDictionaries =
CollectionUtils.newConcurrentHashMap();
@@ -223,6 +224,10 @@ public class DictionaryFacilitatorForSuggest {
return null != mMainDictionary && mMainDictionary.isInitialized();
}
+ public boolean hasPersonalizationDictionary() {
+ return null != mPersonalizationDictionary;
+ }
+
public void waitForLoadingMainDictionary(final long timeout, final TimeUnit unit)
throws InterruptedException {
mLatchForWaitingLoadingMainDictionary.await(timeout, unit);
@@ -476,4 +481,26 @@ public class DictionaryFacilitatorForSuggest {
oldDict.close();
}
}
+
+ // This method gets called only when the IME receives a notification to remove the
+ // personalization dictionary.
+ public void clearPersonalizationDictionary() {
+ if (!hasPersonalizationDictionary()) {
+ return;
+ }
+ mPersonalizationDictionary.clearAndFlushDictionary();
+ }
+
+ public void addMultipleDictionaryEntriesToPersonalizationDictionary(
+ final ArrayList<LanguageModelParam> languageModelParams,
+ final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) {
+ if (!hasPersonalizationDictionary()) {
+ if (callback != null) {
+ callback.onFinished();
+ }
+ return;
+ }
+ mPersonalizationDictionary.addMultipleDictionaryEntriesToDictionary(languageModelParams,
+ callback);
+ }
}
diff --git a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
index 7757d2910..ecef20efc 100644
--- a/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/ExpandableBinaryDictionary.java
@@ -21,12 +21,12 @@ import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.keyboard.ProximityInfo;
-import com.android.inputmethod.latin.BinaryDictionary.LanguageModelParam;
import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
import com.android.inputmethod.latin.utils.AsyncResultHolder;
import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.FileUtils;
+import com.android.inputmethod.latin.utils.LanguageModelParam;
import com.android.inputmethod.latin.utils.PrioritizedSerialExecutor;
import java.io.File;
@@ -58,6 +58,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
private static final boolean DBG_STRESS_TEST = false;
private static final int TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS = 100;
+ private static final int TIMEOUT_FOR_READ_OPS_FOR_TESTS_IN_MILLISECONDS = 1000;
/**
* The maximum length of a word in this dictionary.
@@ -761,7 +762,7 @@ abstract public class ExpandableBinaryDictionary extends Dictionary {
}
}
});
- return holder.get(false, TIMEOUT_FOR_READ_OPS_IN_MILLISECONDS);
+ return holder.get(false, TIMEOUT_FOR_READ_OPS_FOR_TESTS_IN_MILLISECONDS);
}
@UsedForTesting
diff --git a/java/src/com/android/inputmethod/latin/LastComposedWord.java b/java/src/com/android/inputmethod/latin/LastComposedWord.java
index 2e9280c77..8546cebd5 100644
--- a/java/src/com/android/inputmethod/latin/LastComposedWord.java
+++ b/java/src/com/android/inputmethod/latin/LastComposedWord.java
@@ -42,7 +42,7 @@ public final class LastComposedWord {
public final int[] mPrimaryKeyCodes;
public final String mTypedWord;
- public final String mCommittedWord;
+ public final CharSequence mCommittedWord;
public final String mSeparatorString;
public final String mPrevWord;
public final int mCapitalizedMode;
@@ -58,7 +58,7 @@ public final class LastComposedWord {
// Warning: this is using the passed objects as is and fully expects them to be
// immutable. Do not fiddle with their contents after you passed them to this constructor.
public LastComposedWord(final int[] primaryKeyCodes, final InputPointers inputPointers,
- final String typedWord, final String committedWord, final String separatorString,
+ final String typedWord, final CharSequence committedWord, final String separatorString,
final String prevWord, final int capitalizedMode) {
mPrimaryKeyCodes = primaryKeyCodes;
if (inputPointers != null) {
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 40391694c..3fca4fd19 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -213,7 +213,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
postUpdateSuggestionStrip();
break;
case MSG_ON_END_BATCH_INPUT:
- latinIme.mInputLogic.endBatchInputAsyncInternal(latinIme.mSettings.getCurrent(),
+ latinIme.mInputLogic.endBatchInputInternal(latinIme.mSettings.getCurrent(),
(SuggestedWords) msg.obj, latinIme.mKeyboardSwitcher);
break;
case MSG_RESET_CACHES:
@@ -234,6 +234,9 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
}
public void postResumeSuggestions() {
+ if (!getOwnerInstance().mSettings.getCurrent().isSuggestionStripVisible()) {
+ return;
+ }
removeMessages(MSG_RESUME_SUGGESTIONS);
sendMessageDelayed(obtainMessage(MSG_RESUME_SUGGESTIONS), mDelayUpdateSuggestions);
}
@@ -959,11 +962,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
newSelStart, newSelEnd, false /* shouldFinishComposition */);
}
- // We moved the cursor. If we are touching a word, we need to resume suggestion,
- // unless suggestions are off.
- if (isSuggestionsStripVisible()) {
- mHandler.postResumeSuggestions();
- }
+ // We moved the cursor. If we are touching a word, we need to resume suggestion.
+ mHandler.postResumeSuggestions();
// Reset the last recapitalization.
mInputLogic.mRecapitalizeStatus.deactivate();
mKeyboardSwitcher.updateShiftState();
@@ -1389,7 +1389,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
// We're checking the previous word in the text field against the memorized previous
// word. If we are composing a word we should have the second word before the cursor
// memorized, otherwise we should have the first.
- final String rereadPrevWord = mInputLogic.getNthPreviousWordForSuggestion(
+ final CharSequence rereadPrevWord = mInputLogic.getNthPreviousWordForSuggestion(
currentSettings.mSpacingAndPunctuations,
mInputLogic.mWordComposer.isComposingWord() ? 2 : 1);
if (!TextUtils.equals(previousWord, rereadPrevWord)) {
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index b4f2d1a58..ebf65630e 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -297,7 +297,7 @@ public final class WordComposer {
* the context is nil (typically, at start of text).
* @param keyboard the keyboard this is typed on, for coordinate info/proximity.
*/
- public void setComposingWord(final CharSequence word, final String previousWord,
+ public void setComposingWord(final CharSequence word, final CharSequence previousWord,
final Keyboard keyboard) {
reset();
final int length = word.length();
@@ -306,7 +306,7 @@ public final class WordComposer {
addKeyInfo(codePoint, keyboard);
}
mIsResumed = true;
- mPreviousWordForSuggestion = previousWord;
+ mPreviousWordForSuggestion = null == previousWord ? null : previousWord.toString();
}
/**
@@ -418,9 +418,9 @@ public final class WordComposer {
* @param previousWord the previous word as context for suggestions. May be null if none.
*/
public void setCapitalizedModeAndPreviousWordAtStartComposingTime(final int mode,
- final String previousWord) {
+ final CharSequence previousWord) {
mCapitalizedMode = mode;
- mPreviousWordForSuggestion = previousWord;
+ mPreviousWordForSuggestion = null == previousWord ? null : previousWord.toString();
}
/**
@@ -454,7 +454,8 @@ public final class WordComposer {
}
// `type' should be one of the LastComposedWord.COMMIT_TYPE_* constants above.
- public LastComposedWord commitWord(final int type, final String committedWord,
+ // committedWord should contain suggestion spans if applicable.
+ public LastComposedWord commitWord(final int type, final CharSequence committedWord,
final String separatorString, final String prevWord) {
// Note: currently, we come here whenever we commit a word. If it's a MANUAL_PICK
// or a DECIDED_WORD we may cancel the commit later; otherwise, we should deactivate
@@ -472,7 +473,7 @@ public final class WordComposer {
mCapsCount = 0;
mDigitsCount = 0;
mIsBatchMode = false;
- mPreviousWordForSuggestion = committedWord;
+ mPreviousWordForSuggestion = committedWord.toString();
mTypedWord.setLength(0);
mCodePointSize = 0;
mTrailingSingleQuotesCount = 0;
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 71b88703a..fcad0470a 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -17,6 +17,7 @@
package com.android.inputmethod.latin.inputlogic;
import android.os.SystemClock;
+import android.text.SpannableString;
import android.text.TextUtils;
import android.text.style.SuggestionSpan;
import android.util.Log;
@@ -1060,8 +1061,6 @@ public final class InputLogic {
// recorrection. This is a temporary, stopgap measure that will be removed later.
// TODO: remove this.
if (settingsValues.isBrokenByRecorrection()) return;
- // A simple way to test for support from the TextView.
- if (!mLatinIME.isSuggestionsStripVisible()) return;
// Recorrection is not supported in languages without spaces because we don't know
// how to segment them yet.
if (!settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) return;
@@ -1168,8 +1167,8 @@ public final class InputLogic {
// TODO: remove these arguments
final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) {
final String previousWord = mLastComposedWord.mPrevWord;
- final String originallyTypedWord = mLastComposedWord.mTypedWord;
- final String committedWord = mLastComposedWord.mCommittedWord;
+ final CharSequence originallyTypedWord = mLastComposedWord.mTypedWord;
+ final CharSequence committedWord = mLastComposedWord.mCommittedWord;
final int cancelLength = committedWord.length();
// We want java chars, not codepoints for the following.
final int separatorLength = mLastComposedWord.mSeparatorString.length();
@@ -1191,28 +1190,53 @@ public final class InputLogic {
if (!TextUtils.isEmpty(previousWord) && !TextUtils.isEmpty(committedWord)) {
if (mSuggest != null) {
mSuggest.mDictionaryFacilitator.cancelAddingUserHistory(
- previousWord, committedWord);
+ previousWord, committedWord.toString());
+ }
+ }
+ final SpannableString textToCommit =
+ new SpannableString(originallyTypedWord + mLastComposedWord.mSeparatorString);
+ if (committedWord instanceof SpannableString) {
+ final int lastCharIndex = textToCommit.length() - 1;
+ // Add the auto-correction to the list of suggestions.
+ textToCommit.setSpan(new SuggestionSpan(settingsValues.mLocale,
+ new String[] { committedWord.toString() }, 0 /* flags */),
+ 0 /* start */, lastCharIndex /* end */, 0 /* flags */);
+ final SpannableString committedWordWithSuggestionSpans = (SpannableString)committedWord;
+ final Object[] spans = committedWordWithSuggestionSpans.getSpans(0,
+ committedWord.length(), Object.class);
+ for (final Object span : spans) {
+ // Put all the spans in the original text on this new text. We could remove the
+ // typed word from the suggestions, but we'd have to make more dynamic instanceof
+ // checks, to copy the span, copy all suggestions and attributes... And there is
+ // the risk to drop the originally typed string if there is a subtle bug. There is
+ // still the committed auto-correction that we reverted from, which is not included
+ // in the suggestions, that's why we added it with another call to setSpan a few
+ // lines above.
+ // The code that re-reads these spans already knows to do the right thing whether
+ // the typed word is included or not. That should be enough.
+ textToCommit.setSpan(span, 0 /* start */, lastCharIndex /* end */,
+ committedWordWithSuggestionSpans.getSpanFlags(span));
}
}
- final String stringToCommit = originallyTypedWord + mLastComposedWord.mSeparatorString;
if (settingsValues.mSpacingAndPunctuations.mCurrentLanguageHasSpaces) {
// For languages with spaces, we revert to the typed string, but the cursor is still
// after the separator so we don't resume suggestions. If the user wants to correct
// the word, they have to press backspace again.
- mConnection.commitText(stringToCommit, 1);
+ mConnection.commitText(textToCommit, 1);
} else {
// For languages without spaces, we revert the typed string but the cursor is flush
// with the typed word, so we need to resume suggestions right away.
- mWordComposer.setComposingWord(stringToCommit, previousWord,
+ mWordComposer.setComposingWord(textToCommit, previousWord,
keyboardSwitcher.getKeyboard());
- mConnection.setComposingText(stringToCommit, 1);
+ mConnection.setComposingText(textToCommit, 1);
}
if (settingsValues.mIsInternal) {
LatinImeLoggerUtils.onSeparator(mLastComposedWord.mSeparatorString,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
}
if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
- ResearchLogger.latinIME_revertCommit(committedWord, originallyTypedWord,
+ ResearchLogger.latinIME_revertCommit(committedWord.toString(),
+ originallyTypedWord.toString(),
mWordComposer.isBatchMode(), mLastComposedWord.mSeparatorString);
}
// Don't restart suggestion yet. We'll restart if the user deletes the
@@ -1294,7 +1318,7 @@ public final class InputLogic {
* @return the nth previous word before the cursor.
*/
// TODO: Make this private
- public String getNthPreviousWordForSuggestion(
+ public CharSequence getNthPreviousWordForSuggestion(
final SpacingAndPunctuations spacingAndPunctuations, final int nthPreviousWord) {
if (spacingAndPunctuations.mCurrentLanguageHasSpaces) {
// If we are typing in a language with spaces we can just look up the previous
@@ -1510,7 +1534,7 @@ public final class InputLogic {
* @param settingsValues the current values of the settings.
* @param suggestedWords suggestedWords to use.
*/
- public void endBatchInputAsyncInternal(final SettingsValues settingsValues,
+ public void endBatchInputInternal(final SettingsValues settingsValues,
final SuggestedWords suggestedWords,
// TODO: remove this argument
final KeyboardSwitcher keyboardSwitcher) {
@@ -1645,8 +1669,10 @@ public final class InputLogic {
public void commitChosenWord(final SettingsValues settingsValues, final String chosenWord,
final int commitType, final String separatorString) {
final SuggestedWords suggestedWords = mSuggestedWords;
- mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
- suggestedWords), 1);
+ final CharSequence chosenWordWithSuggestions =
+ SuggestionSpanUtils.getTextWithSuggestionSpan(mLatinIME, chosenWord,
+ suggestedWords);
+ mConnection.commitText(chosenWordWithSuggestions, 1);
// TODO: we pass 2 here, but would it be better to move this above and pass 1 instead?
final String prevWord = mConnection.getNthPreviousWord(
settingsValues.mSpacingAndPunctuations, 2);
@@ -1657,7 +1683,7 @@ public final class InputLogic {
// LastComposedWord#didCommitTypedWord by string equality of the remembered
// strings.
mLastComposedWord = mWordComposer.commitWord(commitType,
- chosenWord, separatorString, prevWord);
+ chosenWordWithSuggestions, separatorString, prevWord);
final boolean shouldDiscardPreviousWordForSuggestion;
if (0 == StringUtils.codePointCount(separatorString)) {
// Separator is 0-length, we can keep the previous word for suggestion. Either this
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
index ea010b6f5..b09e20591 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogicHandler.java
@@ -29,8 +29,7 @@ import com.android.inputmethod.latin.Suggest.OnGetSuggestedWordsCallback;
/**
* A helper to manage deferred tasks for the input logic.
*/
-// TODO: Make this package private
-public class InputLogicHandler implements Handler.Callback {
+class InputLogicHandler implements Handler.Callback {
final Handler mNonUIThreadHandler;
// TODO: remove this reference.
final LatinIME mLatinIME;
diff --git a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
index 701c29023..cc57d13dc 100644
--- a/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
+++ b/java/src/com/android/inputmethod/latin/personalization/DecayingExpandableBinaryDictionaryBase.java
@@ -20,13 +20,13 @@ import android.content.Context;
import android.util.Log;
import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.BinaryDictionary.LanguageModelParam;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.Dictionary;
import com.android.inputmethod.latin.ExpandableBinaryDictionary;
import com.android.inputmethod.latin.makedict.DictDecoder;
import com.android.inputmethod.latin.makedict.FormatSpec;
import com.android.inputmethod.latin.makedict.UnsupportedFormatException;
+import com.android.inputmethod.latin.utils.LanguageModelParam;
import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils;
import com.android.inputmethod.latin.utils.UserHistoryDictIOUtils.OnAddWordListener;
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
index 9b2b981d5..7c9b2a169 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
@@ -18,10 +18,8 @@ package com.android.inputmethod.latin.personalization;
import com.android.inputmethod.annotations.UsedForTesting;
import com.android.inputmethod.latin.Dictionary;
-import com.android.inputmethod.latin.utils.CollectionUtils;
import java.io.File;
-import java.util.ArrayList;
import java.util.Locale;
import android.content.Context;
@@ -29,9 +27,6 @@ import android.content.Context;
public class PersonalizationDictionary extends DecayingExpandableBinaryDictionaryBase {
/* package */ static final String NAME = PersonalizationDictionary.class.getSimpleName();
- private final ArrayList<PersonalizationDictionaryUpdateSession> mSessions =
- CollectionUtils.newArrayList();
-
/* package */ PersonalizationDictionary(final Context context, final Locale locale) {
super(context, locale, Dictionary.TYPE_PERSONALIZATION,
getDictNameWithLocale(NAME, locale));
@@ -44,14 +39,4 @@ public class PersonalizationDictionary extends DecayingExpandableBinaryDictionar
super(context, locale, Dictionary.TYPE_PERSONALIZATION, getDictNameWithLocale(NAME, locale),
dictFile);
}
-
- public void registerUpdateSession(PersonalizationDictionaryUpdateSession session) {
- session.setPredictionDictionary(this);
- mSessions.add(session);
- session.onDictionaryReady();
- }
-
- public void unRegisterUpdateSession(PersonalizationDictionaryUpdateSession session) {
- mSessions.remove(session);
- }
}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
deleted file mode 100644
index 3eb8f35a9..000000000
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionaryUpdateSession.java
+++ /dev/null
@@ -1,86 +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.BinaryDictionary.LanguageModelParam;
-import com.android.inputmethod.latin.ExpandableBinaryDictionary;
-
-import java.lang.ref.WeakReference;
-import java.util.ArrayList;
-import java.util.Locale;
-
-/**
- * This class is a session where a data provider can communicate with a personalization
- * dictionary.
- */
-public abstract class PersonalizationDictionaryUpdateSession {
- public WeakReference<PersonalizationDictionary> mDictionary;
- public final Locale mSystemLocale;
-
- public PersonalizationDictionaryUpdateSession(final Locale locale) {
- mSystemLocale = locale;
- }
-
- public abstract void onDictionaryReady();
-
- public abstract void onDictionaryClosed(final Context context);
-
- public void setPredictionDictionary(final PersonalizationDictionary dictionary) {
- mDictionary = new WeakReference<PersonalizationDictionary>(dictionary);
- }
-
- protected PersonalizationDictionary getDictionary() {
- return mDictionary == null ? null : mDictionary.get();
- }
-
- private void unsetDictionary() {
- final PersonalizationDictionary dictionary = getDictionary();
- if (dictionary == null) {
- return;
- }
- dictionary.unRegisterUpdateSession(this);
- }
-
- public void clearAndFlushDictionary() {
- final PersonalizationDictionary dictionary = getDictionary();
- if (dictionary == null) {
- return;
- }
- dictionary.clearAndFlushDictionary();
- }
-
- public void closeSession(final Context context) {
- unsetDictionary();
- onDictionaryClosed(context);
- }
-
- // TODO: Support multi locale.
- public void addMultipleDictionaryEntriesToDictionary(
- final ArrayList<LanguageModelParam> languageModelParams,
- final ExpandableBinaryDictionary.AddMultipleDictionaryEntriesCallback callback) {
- final PersonalizationDictionary dictionary = getDictionary();
- if (dictionary == null) {
- if (callback != null) {
- callback.onFinished();
- }
- return;
- }
- dictionary.addMultipleDictionaryEntriesToDictionary(languageModelParams, callback);
- }
-}
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
index 38b22e5f6..df64bcec1 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationHelper.java
@@ -71,13 +71,6 @@ public class PersonalizationHelper {
}
}
- public static void registerPersonalizationDictionaryUpdateSession(final Context context,
- final PersonalizationDictionaryUpdateSession session, final Locale locale) {
- final PersonalizationDictionary personalizationDictionary =
- getPersonalizationDictionary(context, locale);
- personalizationDictionary.registerUpdateSession(session);
- }
-
public static PersonalizationDictionary getPersonalizationDictionary(
final Context context, final Locale locale) {
final String localeStr = locale.toString();
diff --git a/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
new file mode 100644
index 000000000..a1d641508
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/utils/LanguageModelParam.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) 2014 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.utils;
+
+import android.util.Log;
+
+import com.android.inputmethod.latin.Dictionary;
+import com.android.inputmethod.latin.DictionaryFacilitatorForSuggest;
+import com.android.inputmethod.latin.settings.SpacingAndPunctuations;
+
+import java.util.ArrayList;
+import java.util.Locale;
+
+// Note: this class is used as a parameter type of a native method. You should be careful when you
+// rename this class or field name. See BinaryDictionary#addMultipleDictionaryEntriesNative().
+public final class LanguageModelParam {
+ private static final String TAG = LanguageModelParam.class.getSimpleName();
+ private static final boolean DEBUG = false;
+ private static final boolean DEBUG_TOKEN = false;
+
+ // For now, these probability values are being referred to only when we add new entries to
+ // decaying dynamic binary dictionaries. When these are referred to, what matters is 0 or
+ // non-0. Thus, it's not meaningful to compare 10, 100, and so on.
+ // TODO: Revise the logic in ForgettingCurveUtils in native code.
+ private static final int UNIGRAM_PROBABILITY_FOR_VALID_WORD = 100;
+ private static final int UNIGRAM_PROBABILITY_FOR_OOV_WORD = 10;
+ private static final int BIGRAM_PROBABILITY_FOR_VALID_WORD = 0;
+ private static final int BIGRAM_PROBABILITY_FOR_OOV_WORD = 0;
+
+ public final String mTargetWord;
+ public final int[] mWord0;
+ public final int[] mWord1;
+ // TODO: this needs to be a list of shortcuts
+ public final int[] mShortcutTarget;
+ public final int mUnigramProbability;
+ public final int mBigramProbability;
+ public final int mShortcutProbability;
+ public final boolean mIsNotAWord;
+ public final boolean mIsBlacklisted;
+ // Time stamp in seconds.
+ public final int mTimestamp;
+
+ // Constructor for unigram. TODO: support shortcuts
+ public LanguageModelParam(final String word, final int unigramProbability,
+ final int timestamp) {
+ this(null /* word0 */, word, unigramProbability, Dictionary.NOT_A_PROBABILITY, timestamp);
+ }
+
+ // Constructor for unigram and bigram.
+ public LanguageModelParam(final String word0, final String word1,
+ final int unigramProbability, final int bigramProbability,
+ final int timestamp) {
+ mTargetWord = word1;
+ mWord0 = (word0 == null) ? null : StringUtils.toCodePointArray(word0);
+ mWord1 = StringUtils.toCodePointArray(word1);
+ mShortcutTarget = null;
+ mUnigramProbability = unigramProbability;
+ mBigramProbability = bigramProbability;
+ mShortcutProbability = Dictionary.NOT_A_PROBABILITY;
+ mIsNotAWord = false;
+ mIsBlacklisted = false;
+ mTimestamp = timestamp;
+ }
+
+ // Process a list of words and return a list of {@link LanguageModelParam} objects.
+ public static ArrayList<LanguageModelParam> createLanguageModelParamsFrom(
+ final ArrayList<String> tokens, final int timestamp,
+ final DictionaryFacilitatorForSuggest dictionaryFacilitator,
+ final SpacingAndPunctuations spacingAndPunctuations) {
+ final ArrayList<LanguageModelParam> languageModelParams =
+ CollectionUtils.newArrayList();
+ final int N = tokens.size();
+ String prevWord = null;
+ for (int i = 0; i < N; ++i) {
+ final String tempWord = tokens.get(i);
+ if (StringUtils.isEmptyStringOrWhiteSpaces(tempWord)) {
+ // just skip this token
+ if (DEBUG_TOKEN) {
+ Log.d(TAG, "--- isEmptyStringOrWhiteSpaces: \"" + tempWord + "\"");
+ }
+ continue;
+ }
+ if (!DictionaryInfoUtils.looksValidForDictionaryInsertion(
+ tempWord, spacingAndPunctuations)) {
+ if (DEBUG_TOKEN) {
+ Log.d(TAG, "--- not looksValidForDictionaryInsertion: \""
+ + tempWord + "\"");
+ }
+ // Sentence terminator found. Split.
+ prevWord = null;
+ continue;
+ }
+ if (DEBUG_TOKEN) {
+ Log.d(TAG, "--- word: \"" + tempWord + "\"");
+ }
+ final LanguageModelParam languageModelParam =
+ detectWhetherVaildWordOrNotAndGetLanguageModelParam(
+ prevWord, tempWord, timestamp, dictionaryFacilitator);
+ languageModelParams.add(languageModelParam);
+ prevWord = languageModelParam.mTargetWord;
+ }
+ return languageModelParams;
+ }
+
+ private static LanguageModelParam detectWhetherVaildWordOrNotAndGetLanguageModelParam(
+ final String prevWord, final String targetWord, final int timestamp,
+ final DictionaryFacilitatorForSuggest dictionaryFacilitator) {
+ final Locale locale = dictionaryFacilitator.mLocale;
+ if (!dictionaryFacilitator.isValidWord(targetWord, true /* ignoreCase */)) {
+ // OOV word.
+ return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
+ false /* isValidWord */, locale);
+ }
+ if (dictionaryFacilitator.isValidWord(targetWord, false /* ignoreCase */)) {
+ return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
+ true /* isValidWord */, locale);
+ }
+ final String lowerCaseTargetWord = targetWord.toLowerCase(locale);
+ if (dictionaryFacilitator.isValidWord(lowerCaseTargetWord, false /* ignoreCase */)) {
+ // Add the lower-cased word.
+ return createAndGetLanguageModelParamOfWord(prevWord, lowerCaseTargetWord,
+ timestamp, true /* isValidWord */, locale);
+ }
+ // Treat the word as an OOV word.
+ return createAndGetLanguageModelParamOfWord(prevWord, targetWord, timestamp,
+ false /* isValidWord */, locale);
+ }
+
+ private static LanguageModelParam createAndGetLanguageModelParamOfWord(
+ final String prevWord, final String targetWord, final int timestamp,
+ final boolean isValidWord, final Locale locale) {
+ final String word;
+ if (StringUtils.getCapitalizationType(targetWord) == StringUtils.CAPITALIZE_FIRST
+ && prevWord == null && !isValidWord) {
+ word = targetWord.toLowerCase(locale);
+ } else {
+ word = targetWord;
+ }
+ final int unigramProbability = isValidWord ?
+ UNIGRAM_PROBABILITY_FOR_VALID_WORD : UNIGRAM_PROBABILITY_FOR_OOV_WORD;
+ if (prevWord == null) {
+ if (DEBUG) {
+ Log.d(TAG, "--- add unigram: current("
+ + (isValidWord ? "Valid" : "OOV") + ") = " + word);
+ }
+ return new LanguageModelParam(word, unigramProbability, timestamp);
+ }
+ if (DEBUG) {
+ Log.d(TAG, "--- add bigram: prev = " + prevWord + ", current("
+ + (isValidWord ? "Valid" : "OOV") + ") = " + word);
+ }
+ final int bigramProbability = isValidWord ?
+ BIGRAM_PROBABILITY_FOR_VALID_WORD : BIGRAM_PROBABILITY_FOR_OOV_WORD;
+ return new LanguageModelParam(prevWord, word, unigramProbability,
+ bigramProbability, timestamp);
+ }
+}