Add prev words context to the SuggestedWordInfo.

Bug: 19712589
Bug: 19715579
Change-Id: Ie06665cab8405455c1b0a2ff034e0bb0731c9156
diff --git a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
index b8f835e..c069a0f 100644
--- a/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/utils/StatsUtils.java
@@ -72,7 +72,8 @@
     }
 
     public static void onAutoCorrection(final String typedWord, final String autoCorrectionWord,
-            final boolean isBatchInput, final DictionaryFacilitator dictionaryType) {
+            final boolean isBatchInput, final DictionaryFacilitator dictionaryFacilitator,
+            final String prevWordsContext) {
     }
 
     public static void onWordCommitUserTyped(final String commitWord, final boolean isBatchMode) {
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionary.java b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
index 7f4631b..9a3ac67 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionary.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionary.java
@@ -27,7 +27,6 @@
 import com.android.inputmethod.latin.common.FileUtils;
 import com.android.inputmethod.latin.common.InputPointers;
 import com.android.inputmethod.latin.common.StringUtils;
-import com.android.inputmethod.latin.define.DecoderSpecificConstants;
 import com.android.inputmethod.latin.makedict.DictionaryHeader;
 import com.android.inputmethod.latin.makedict.FormatSpec;
 import com.android.inputmethod.latin.makedict.FormatSpec.DictionaryOptions;
@@ -330,7 +329,9 @@
             if (len > 0) {
                 suggestions.add(new SuggestedWordInfo(
                         new String(session.mOutputCodePoints, start, len),
-                        (int)(session.mOutputScores[j] * weightForLocale), session.mOutputTypes[j],
+                        "" /* prevWordsContext */,
+                        (int)(session.mOutputScores[j] * weightForLocale),
+                        session.mOutputTypes[j],
                         this /* sourceDict */,
                         session.mSpaceIndices[j] /* indexOfTouchPointOfSecondWord */,
                         session.mOutputAutoCommitFirstWordConfidence[0]));
diff --git a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
index c9b6d6b..e2c5621 100644
--- a/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
+++ b/java/src/com/android/inputmethod/latin/PunctuationSuggestions.java
@@ -114,7 +114,8 @@
     }
 
     private static SuggestedWordInfo newHardCodedWordInfo(final String keySpec) {
-        return new SuggestedWordInfo(keySpec, SuggestedWordInfo.MAX_SCORE,
+        return new SuggestedWordInfo(keySpec, "" /* prevWordsContext */,
+                SuggestedWordInfo.MAX_SCORE,
                 SuggestedWordInfo.KIND_HARDCODED,
                 Dictionary.DICTIONARY_HARDCODED,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index 8562acd..7ccefd2 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -36,7 +36,6 @@
 import java.util.Locale;
 
 import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
 
 /**
  * This class loads a dictionary and provides a list of suggestions for a given sequence of
@@ -249,7 +248,8 @@
         }
 
         final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(typedWordString,
-                SuggestedWordInfo.MAX_SCORE, SuggestedWordInfo.KIND_TYPED,
+                "" /* prevWordsContext */, SuggestedWordInfo.MAX_SCORE,
+                SuggestedWordInfo.KIND_TYPED,
                 null == sourceDictionaryOfRemovedWord ? Dictionary.DICTIONARY_USER_TYPED
                         : sourceDictionaryOfRemovedWord,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
@@ -426,7 +426,8 @@
         for (int i = quotesToAppend - 1; i >= 0; --i) {
             sb.appendCodePoint(Constants.CODE_SINGLE_QUOTE);
         }
-        return new SuggestedWordInfo(sb.toString(), wordInfo.mScore, wordInfo.mKindAndFlags,
+        return new SuggestedWordInfo(sb.toString(), wordInfo.mPrevWordsContext,
+                wordInfo.mScore, wordInfo.mKindAndFlags,
                 wordInfo.mSourceDict, wordInfo.mIndexOfTouchPointOfSecondWord,
                 wordInfo.mAutoCommitFirstWordConfidence);
     }
diff --git a/java/src/com/android/inputmethod/latin/SuggestedWords.java b/java/src/com/android/inputmethod/latin/SuggestedWords.java
index 87fe291..bcd4d5f 100644
--- a/java/src/com/android/inputmethod/latin/SuggestedWords.java
+++ b/java/src/com/android/inputmethod/latin/SuggestedWords.java
@@ -17,11 +17,9 @@
 package com.android.inputmethod.latin;
 
 import android.text.TextUtils;
-import android.util.Log;
 import android.view.inputmethod.CompletionInfo;
 
 import com.android.inputmethod.annotations.UsedForTesting;
-import com.android.inputmethod.latin.common.Constants;
 import com.android.inputmethod.latin.common.StringUtils;
 import com.android.inputmethod.latin.define.DebugFlags;
 
@@ -264,6 +262,7 @@
         public static final int KIND_FLAG_APPROPRIATE_FOR_AUTO_CORRECTION = 0x10000000;
 
         public final String mWord;
+        public final String mPrevWordsContext;
         // The completion info from the application. Null for suggestions that don't come from
         // the application (including keyboard-computed ones, so this is almost always null)
         public final CompletionInfo mApplicationSpecifiedCompletionInfo;
@@ -284,6 +283,7 @@
         /**
          * Create a new suggested word info.
          * @param word The string to suggest.
+         * @param prevWordsContext previous words context.
          * @param score A measure of how likely this suggestion is.
          * @param kindAndFlags The kind of suggestion, as one of the above KIND_* constants with
          * flags.
@@ -291,10 +291,12 @@
          * @param indexOfTouchPointOfSecondWord See mIndexOfTouchPointOfSecondWord.
          * @param autoCommitFirstWordConfidence See mAutoCommitFirstWordConfidence.
          */
-        public SuggestedWordInfo(final String word, final int score, final int kindAndFlags,
+        public SuggestedWordInfo(final String word, final String prevWordsContext,
+                final int score, final int kindAndFlags,
                 final Dictionary sourceDict, final int indexOfTouchPointOfSecondWord,
                 final int autoCommitFirstWordConfidence) {
             mWord = word;
+            mPrevWordsContext = prevWordsContext;
             mApplicationSpecifiedCompletionInfo = null;
             mScore = score;
             mKindAndFlags = kindAndFlags;
@@ -311,6 +313,7 @@
          */
         public SuggestedWordInfo(final CompletionInfo applicationSpecifiedCompletion) {
             mWord = applicationSpecifiedCompletion.getText().toString();
+            mPrevWordsContext = "";
             mApplicationSpecifiedCompletionInfo = applicationSpecifiedCompletion;
             mScore = SuggestedWordInfo.MAX_SCORE;
             mKindAndFlags = SuggestedWordInfo.KIND_APP_DEFINED;
@@ -429,27 +432,6 @@
         return isPrediction(mInputStyle);
     }
 
-    // Creates a new SuggestedWordInfo from the currently suggested words that removes all but the
-    // last word of all suggestions, separated by a space. This is necessary because when we commit
-    // a multiple-word suggestion, the IME only retains the last word as the composing word, and
-    // we should only suggest replacements for this last word.
-    // TODO: make this work with languages without spaces.
-    public SuggestedWords getSuggestedWordsForLastWordOfPhraseGesture() {
-        final ArrayList<SuggestedWordInfo> newSuggestions = new ArrayList<>();
-        for (int i = 0; i < mSuggestedWordInfoList.size(); ++i) {
-            final SuggestedWordInfo info = mSuggestedWordInfoList.get(i);
-            final int indexOfLastSpace = info.mWord.lastIndexOf(Constants.CODE_SPACE) + 1;
-            final String lastWord = info.mWord.substring(indexOfLastSpace);
-            newSuggestions.add(new SuggestedWordInfo(lastWord, info.mScore, info.mKindAndFlags,
-                    info.mSourceDict, SuggestedWordInfo.NOT_AN_INDEX,
-                    SuggestedWordInfo.NOT_A_CONFIDENCE));
-        }
-        return new SuggestedWords(newSuggestions, null /* rawSuggestions */,
-                newSuggestions.isEmpty() ? null : newSuggestions.get(0) /* typedWordInfo */,
-                mTypedWordValid, mWillAutoCorrect, mIsObsoleteSuggestions, INPUT_STYLE_TAIL_BATCH,
-                NOT_A_SEQUENCE_NUMBER);
-    }
-
     /**
      * @return the {@link SuggestedWordInfo} which corresponds to the word that is originally
      * typed by the user. Otherwise returns {@code null}. Note that gesture input is not
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 00175f0..5e4e02f 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -1408,7 +1408,8 @@
                     public void onGetSuggestedWords(final SuggestedWords suggestedWords) {
                         final String typedWordString = mWordComposer.getTypedWord();
                         final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(
-                                typedWordString, SuggestedWordInfo.MAX_SCORE,
+                                typedWordString, "" /* prevWordsContext */,
+                                SuggestedWordInfo.MAX_SCORE,
                                 SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
                                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                                 SuggestedWordInfo.NOT_A_CONFIDENCE);
@@ -1492,7 +1493,7 @@
         final ArrayList<SuggestedWordInfo> suggestions = new ArrayList<>();
         final String typedWordString = range.mWord.toString();
         final SuggestedWordInfo typedWordInfo = new SuggestedWordInfo(typedWordString,
-                SuggestedWords.MAX_SUGGESTIONS + 1,
+                "" /* prevWordsContext */, SuggestedWords.MAX_SUGGESTIONS + 1,
                 SuggestedWordInfo.KIND_TYPED, Dictionary.DICTIONARY_USER_TYPED,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                 SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
@@ -1507,7 +1508,7 @@
                 ++i;
                 if (!TextUtils.equals(s, typedWordString)) {
                     suggestions.add(new SuggestedWordInfo(s,
-                            SuggestedWords.MAX_SUGGESTIONS - i,
+                            "" /* prevWordsContext */, SuggestedWords.MAX_SUGGESTIONS - i,
                             SuggestedWordInfo.KIND_RESUMED, Dictionary.DICTIONARY_RESUMED,
                             SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                             SuggestedWordInfo.NOT_A_CONFIDENCE
@@ -2053,8 +2054,11 @@
                 mConnection.commitCorrection(new CorrectionInfo(
                         mConnection.getExpectedSelectionEnd() - stringToCommit.length(),
                         typedWord, stringToCommit));
+                String prevWordsContext = (autoCorrectionOrNull != null)
+                        ? autoCorrectionOrNull.mPrevWordsContext
+                        : "";
                 StatsUtils.onAutoCorrection(typedWord, stringToCommit, isBatchMode,
-                        mDictionaryFacilitator);
+                        mDictionaryFacilitator, prevWordsContext);
                 StatsUtils.onWordCommitAutoCorrect(stringToCommit, isBatchMode);
             } else {
                 StatsUtils.onWordCommitUserTyped(stringToCommit, isBatchMode);
diff --git a/tests/src/com/android/inputmethod/compat/SuggestionSpanUtilsTest.java b/tests/src/com/android/inputmethod/compat/SuggestionSpanUtilsTest.java
index 7bbf965..daf412c 100644
--- a/tests/src/com/android/inputmethod/compat/SuggestionSpanUtilsTest.java
+++ b/tests/src/com/android/inputmethod/compat/SuggestionSpanUtilsTest.java
@@ -42,7 +42,8 @@
      * @return a new instance of {@link SuggestedWordInfo}.
      */
     private static SuggestedWordInfo createWordInfo(final String word, final int kindAndFlags) {
-        return new SuggestedWordInfo(word, 1 /* score */, kindAndFlags, null /* sourceDict */,
+        return new SuggestedWordInfo(word, "" /* prevWordsContext */, 1 /* score */, kindAndFlags,
+                null /* sourceDict */,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                 SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */);
     }
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index ab4060a..0d9b36a 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -409,7 +409,8 @@
     }
 
     protected void pickSuggestionManually(final String suggestion) {
-        mLatinIME.pickSuggestionManually(new SuggestedWordInfo(suggestion, 1,
+        mLatinIME.pickSuggestionManually(new SuggestedWordInfo(suggestion,
+                "" /* prevWordsContext */, 1 /* score */,
                 SuggestedWordInfo.KIND_CORRECTION, DICTIONARY_TEST,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
                 SuggestedWordInfo.NOT_A_CONFIDENCE /* autoCommitFirstWordConfidence */));
diff --git a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
index 657cec8..d465ce6 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestedWordsTests.java
@@ -37,7 +37,7 @@
     private static SuggestedWordInfo createTypedWordInfo(final String word) {
         // Use 100 as the frequency because the numerical value does not matter as
         // long as it's > 1 and < INT_MAX.
-        return new SuggestedWordInfo(word, 100 /* score */,
+        return new SuggestedWordInfo(word, "" /* prevWordsContext */, 100 /* score */,
                 SuggestedWordInfo.KIND_TYPED,
                 null /* sourceDict */,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,
@@ -52,7 +52,7 @@
      * @return a new instance of {@link SuggestedWordInfo}.
      */
     private static SuggestedWordInfo createCorrectionWordInfo(final String word) {
-        return new SuggestedWordInfo(word, 1 /* score */,
+        return new SuggestedWordInfo(word, "" /* prevWordsContext */, 1 /* score */,
                 SuggestedWordInfo.KIND_CORRECTION,
                 null /* sourceDict */,
                 SuggestedWordInfo.NOT_AN_INDEX /* indexOfTouchPointOfSecondWord */,