Merge "Use InstrumentationTestCase and get rid of AndroidTestCase.getTestContext call"
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index da091dd..4670bed 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -449,7 +449,7 @@
             oldContactsDictionary = null;
         }
         mSuggest = new Suggest(this, subtypeLocale);
-        if (mCurrentSettings.mAutoCorrectEnabled) {
+        if (mCurrentSettings.isCorrectionOn()) {
             mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
         }
 
@@ -680,7 +680,7 @@
 
         loadSettings();
 
-        if (mSuggest != null && mCurrentSettings.mAutoCorrectEnabled) {
+        if (mSuggest != null && mCurrentSettings.isCorrectionOn()) {
             mSuggest.setAutoCorrectionThreshold(mCurrentSettings.mAutoCorrectionThreshold);
         }
 
@@ -1401,7 +1401,7 @@
                     return;
                 }
             } else if (SPACE_STATE_SWAP_PUNCTUATION == spaceState) {
-                if (revertSwapPunctuation()) {
+                if (mConnection.revertSwapPunctuation()) {
                     // Likewise
                     return;
                 }
@@ -1553,8 +1553,7 @@
             // not to auto correct, but accept the typed word. For instance,
             // in Italian dov' should not be expanded to dove' because the elision
             // requires the last vowel to be removed.
-            final boolean shouldAutoCorrect = mCurrentSettings.mAutoCorrectEnabled
-                    && !mInputAttributes.mInputTypeNoAutoCorrect;
+            final boolean shouldAutoCorrect = mCurrentSettings.isCorrectionOn();
             if (shouldAutoCorrect && primaryCode != Keyboard.CODE_SINGLE_QUOTE) {
                 commitCurrentAutoCorrection(primaryCode);
                 didAutoCorrect = true;
@@ -1914,14 +1913,11 @@
             mConnection.commitText(SuggestionSpanUtils.getTextWithSuggestionSpan(
                     this, chosenWord, suggestedWords, mIsMainDictionaryAvailable),
                     1);
-            if (ProductionFlag.IS_EXPERIMENTAL) {
-                ResearchLogger.latinIME_commitText(chosenWord);
-            }
         } else {
             mConnection.commitText(chosenWord, 1);
-            if (ProductionFlag.IS_EXPERIMENTAL) {
-                ResearchLogger.latinIME_commitText(chosenWord);
-            }
+        }
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.latinIME_commitText(chosenWord);
         }
         // Add the word to the user history dictionary
         final CharSequence prevWord = addToUserHistoryDictionary(chosenWord);
@@ -1975,10 +1971,7 @@
         // Only auto-add to dictionary if auto-correct is ON. Otherwise we'll be
         // adding words in situations where the user or application really didn't
         // want corrections enabled or learned.
-        if (!(mCurrentSettings.mCorrectionMode == Suggest.CORRECTION_FULL
-                || mCurrentSettings.mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM)) {
-            return null;
-        }
+        if (!mCurrentSettings.isCorrectionOn()) return null;
 
         if (mUserHistoryDictionary != null) {
             final CharSequence prevWord
@@ -2075,32 +2068,6 @@
         mHandler.postUpdateSuggestions();
     }
 
-    private boolean revertSwapPunctuation() {
-        // Here we test whether we indeed have a space and something else before us. This should not
-        // be needed, but it's there just in case something went wrong.
-        final CharSequence textBeforeCursor = mConnection.getTextBeforeCursor(2, 0);
-        // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
-        // enter surrogate pairs this code will have been removed.
-        if (TextUtils.isEmpty(textBeforeCursor)
-                || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) {
-            // We may only come here if the application is changing the text while we are typing.
-            // This is quite a broken case, but not logically impossible, so we shouldn't crash,
-            // but some debugging log may be in order.
-            Log.d(TAG, "Tried to revert a swap of punctuation but we didn't "
-                    + "find a space just before the cursor.");
-            return false;
-        }
-        mConnection.deleteSurroundingText(2, 0);
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.latinIME_deleteSurroundingText(2);
-        }
-        mConnection.commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
-        if (ProductionFlag.IS_EXPERIMENTAL) {
-            ResearchLogger.latinIME_revertSwapPunctuation();
-        }
-        return true;
-    }
-
     public boolean isWordSeparator(int code) {
         return mCurrentSettings.isWordSeparator(code);
     }
@@ -2260,7 +2227,7 @@
         p.println("  mIsSuggestionsRequested=" + mInputAttributes.mIsSettingsSuggestionStripOn);
         p.println("  mCorrectionMode=" + mCurrentSettings.mCorrectionMode);
         p.println("  isComposingWord=" + mWordComposer.isComposingWord());
-        p.println("  mAutoCorrectEnabled=" + mCurrentSettings.mAutoCorrectEnabled);
+        p.println("  isCorrectionOn=" + mCurrentSettings.isCorrectionOn());
         p.println("  mSoundOn=" + mCurrentSettings.mSoundOn);
         p.println("  mVibrateOn=" + mCurrentSettings.mVibrateOn);
         p.println("  mKeyPreviewPopupOn=" + mCurrentSettings.mKeyPreviewPopupOn);
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index f27d070..46efa78 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -40,6 +40,7 @@
 import com.android.inputmethod.keyboard.Key;
 import com.android.inputmethod.keyboard.Keyboard;
 import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.latin.RichInputConnection.Range;
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.define.ProductionFlag;
 
@@ -614,11 +615,17 @@
             final int composingSpanEnd, final boolean expectingUpdateSelection,
             final boolean expectingUpdateSelectionFromLogger,
             final RichInputConnection connection) {
+        String word = "";
+        if (connection != null) {
+            Range range = connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1);
+            if (range != null) {
+                word = range.mWord;
+            }
+        }
         final Object[] values = {
             lastSelectionStart, lastSelectionEnd, oldSelStart, oldSelEnd, newSelStart,
             newSelEnd, composingSpanStart, composingSpanEnd, expectingUpdateSelection,
-            expectingUpdateSelectionFromLogger,
-            connection.getWordRangeAtCursor(WHITESPACE_SEPARATORS, 1).mWord
+            expectingUpdateSelectionFromLogger, word
         };
         getInstance().writeEvent(EVENTKEYS_LATINIME_ONUPDATESELECTION, values);
     }
@@ -637,9 +644,9 @@
         "LatinIMEPickApplicationSpecifiedCompletion", "index", "text", "x", "y"
     };
     public static void latinIME_pickApplicationSpecifiedCompletion(final int index,
-            final CharSequence text, int x, int y) {
+            final CharSequence cs, int x, int y) {
         final Object[] values = {
-            index, text.toString(), x, y
+            index, cs, x, y
         };
         getInstance().writeEvent(EVENTKEYS_LATINIME_PICKAPPLICATIONSPECIFIEDCOMPLETION, values);
     }
@@ -650,7 +657,7 @@
     public static void latinIME_pickSuggestionManually(final String replacedWord,
             final int index, CharSequence suggestion, int x, int y) {
         final Object[] values = {
-            replacedWord, index, suggestion.toString(), x, y
+            replacedWord, index, suggestion, x, y
         };
         getInstance().writeEvent(EVENTKEYS_LATINIME_PICKSUGGESTIONMANUALLY, values);
     }
@@ -661,7 +668,7 @@
     public static void latinIME_punctuationSuggestion(final int index,
             final CharSequence suggestion, int x, int y) {
         final Object[] values = {
-            index, suggestion.toString(), x, y
+            index, suggestion, x, y
         };
         getInstance().writeEvent(EVENTKEYS_LATINIME_PUNCTUATIONSUGGESTION, values);
     }
@@ -773,8 +780,8 @@
         if (key != null) {
             CharSequence outputText = key.mOutputText;
             final Object[] values = {
-                Keyboard.printableCode(code), outputText == null ? "" : outputText.toString(),
-                x, y, ignoreModifierKey, altersCode, key.isEnabled()
+                Keyboard.printableCode(code), outputText, x, y, ignoreModifierKey, altersCode,
+                key.isEnabled()
             };
             getInstance().writeEvent(EVENTKEYS_POINTERTRACKER_CALLLISTENERONCODEINPUT, values);
         }
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 5ca4a84..227990a 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -393,4 +393,30 @@
         }
         return true;
     }
+
+    public boolean revertSwapPunctuation() {
+        // Here we test whether we indeed have a space and something else before us. This should not
+        // be needed, but it's there just in case something went wrong.
+        final CharSequence textBeforeCursor = getTextBeforeCursor(2, 0);
+        // NOTE: This does not work with surrogate pairs. Hopefully when the keyboard is able to
+        // enter surrogate pairs this code will have been removed.
+        if (TextUtils.isEmpty(textBeforeCursor)
+                || (Keyboard.CODE_SPACE != textBeforeCursor.charAt(1))) {
+            // We may only come here if the application is changing the text while we are typing.
+            // This is quite a broken case, but not logically impossible, so we shouldn't crash,
+            // but some debugging log may be in order.
+            Log.d(TAG, "Tried to revert a swap of punctuation but we didn't "
+                    + "find a space just before the cursor.");
+            return false;
+        }
+        deleteSurroundingText(2, 0);
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.latinIME_deleteSurroundingText(2);
+        }
+        commitText(" " + textBeforeCursor.subSequence(0, 1), 1);
+        if (ProductionFlag.IS_EXPERIMENTAL) {
+            ResearchLogger.latinIME_revertSwapPunctuation();
+        }
+        return true;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 9985d2f..6a79aa6 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -91,7 +91,7 @@
     public final int mKeypressVibrationDuration;
     public final float mFxVolume;
     public final int mKeyPreviewPopupDismissDelay;
-    public final boolean mAutoCorrectEnabled;
+    private final boolean mAutoCorrectEnabled;
     public final float mAutoCorrectionThreshold;
     public final int mCorrectionMode;
     public final int mSuggestionVisibility;
@@ -226,6 +226,11 @@
                 res.getBoolean(R.bool.config_default_vibration_enabled));
     }
 
+    public boolean isCorrectionOn() {
+        return mCorrectionMode == Suggest.CORRECTION_FULL
+                || mCorrectionMode == Suggest.CORRECTION_FULL_BIGRAM;
+    }
+
     public boolean isSuggestionStripVisibleInOrientation(final int orientation) {
         return (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_VALUE)
                 || (mSuggestionVisibility == SUGGESTION_VISIBILITY_SHOW_ONLY_PORTRAIT_VALUE