Merge "Fix missing Azerbaijani text resource"
diff --git a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
index e195a54..55282c5 100644
--- a/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
+++ b/java/src/com/android/inputmethod/compat/SuggestionSpanUtils.java
@@ -32,8 +32,6 @@
 import java.util.ArrayList;
 
 public final class SuggestionSpanUtils {
-    private static final String TAG = SuggestionSpanUtils.class.getSimpleName();
-
     // Note that SuggestionSpan.FLAG_AUTO_CORRECTION has been introduced
     // in API level 15 (Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1).
     public static final Field FIELD_FLAG_AUTO_CORRECTION = CompatUtils.getField(
@@ -60,7 +58,7 @@
         }
         final Spannable spannable = new SpannableString(text);
         final SuggestionSpan suggestionSpan = new SuggestionSpan(context, null /* locale */,
-                new String[] {} /* suggestions */, (int)OBJ_FLAG_AUTO_CORRECTION,
+                new String[] {} /* suggestions */, OBJ_FLAG_AUTO_CORRECTION,
                 SuggestionSpanPickedNotificationReceiver.class);
         spannable.setSpan(suggestionSpan, 0, text.length(),
                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE | Spanned.SPAN_COMPOSING);
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
index 62b905d..1d9b999 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryProvider.java
@@ -54,7 +54,6 @@
     private static final String QUERY_PARAMETER_MAY_PROMPT_USER = "mayPrompt";
     private static final String QUERY_PARAMETER_TRUE = "true";
     private static final String QUERY_PARAMETER_DELETE_RESULT = "result";
-    private static final String QUERY_PARAMETER_SUCCESS = "success";
     private static final String QUERY_PARAMETER_FAILURE = "failure";
     public static final String QUERY_PARAMETER_PROTOCOL_VERSION = "protocol";
     private static final int NO_MATCH = 0;
diff --git a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
index 939c25f..41916b6 100644
--- a/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
+++ b/java/src/com/android/inputmethod/dictionarypack/DictionaryService.java
@@ -50,8 +50,6 @@
  *     to access, and mark the current state as such.
  */
 public final class DictionaryService extends Service {
-    private static final String TAG = DictionaryService.class.getName();
-
     /**
      * The package name, to use in the intent actions.
      */
diff --git a/java/src/com/android/inputmethod/dictionarypack/EventHandler.java b/java/src/com/android/inputmethod/dictionarypack/EventHandler.java
index d8aa33b..859f1b3 100644
--- a/java/src/com/android/inputmethod/dictionarypack/EventHandler.java
+++ b/java/src/com/android/inputmethod/dictionarypack/EventHandler.java
@@ -21,8 +21,6 @@
 import android.content.Intent;
 
 public final class EventHandler extends BroadcastReceiver {
-    private static final String TAG = EventHandler.class.getName();
-
     /**
      * Receives a intent broadcast.
      *
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 8ead44c..164910d 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -29,8 +29,8 @@
  *
  * The input events are {@link #onLoadKeyboard()}, {@link #onSaveKeyboardState()},
  * {@link #onPressKey(int,boolean,int)}, {@link #onReleaseKey(int,boolean)},
- * {@link #onCodeInput(int,int)}, {@link #onFinishSlidingInput()}, {@link #onCancelInput()},
- * {@link #onUpdateShiftState(int,int)}.
+ * {@link #onCodeInput(int,int)}, {@link #onFinishSlidingInput()},
+ * {@link #onUpdateShiftState(int,int)}, {@link #onResetKeyboardStateToAlphabet()}.
  *
  * The actions are {@link SwitchActions}'s methods.
  */
diff --git a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
index 4916a15..c1f3749 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/MatrixUtils.java
@@ -30,7 +30,6 @@
 public class MatrixUtils {
     private static final String TAG = MatrixUtils.class.getSimpleName();
     public static class MatrixOperationFailedException extends Exception {
-        private static final String TAG = MatrixOperationFailedException.class.getSimpleName();
         private static final long serialVersionUID = 4384485606788583829L;
 
         public MatrixOperationFailedException(String msg) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/SmoothingUtils.java b/java/src/com/android/inputmethod/keyboard/internal/SmoothingUtils.java
index e5665bc..10847f6 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/SmoothingUtils.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/SmoothingUtils.java
@@ -62,7 +62,7 @@
             for (int j = 0; j < COEFF_COUNT; ++j) {
                 final int pow = i + j;
                 for (int k = 0; k < N; ++k) {
-                    m0[i][j] += (float) Math.pow((double) xs[k], pow);
+                    m0[i][j] += (float) Math.pow(xs[k], pow);
                 }
             }
         }
diff --git a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
index 31a892e..fa301b5 100644
--- a/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
+++ b/java/src/com/android/inputmethod/latin/BinaryDictionaryGetter.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.SharedPreferences;
-import android.content.pm.PackageManager;
 import android.content.res.AssetFileDescriptor;
 import android.util.Log;
 
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 65f0a7a..1211ea5 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -548,8 +548,9 @@
         }
         mSuggest = new Suggest(this /* Context */, subtypeLocale,
                 this /* SuggestInitializationListener */);
-        if (mSettings.getCurrent().mCorrectionEnabled) {
-            mSuggest.setAutoCorrectionThreshold(mSettings.getCurrent().mAutoCorrectionThreshold);
+        final SettingsValues settingsValues = mSettings.getCurrent();
+        if (settingsValues.mCorrectionEnabled) {
+            mSuggest.setAutoCorrectionThreshold(settingsValues.mAutoCorrectionThreshold);
         }
 
         mIsMainDictionaryAvailable = DictionaryFactory.isDictionaryAvailable(this, subtypeLocale);
@@ -1216,10 +1217,11 @@
     private void resetEntireInputState(final int newCursorPosition) {
         final boolean shouldFinishComposition = mWordComposer.isComposingWord();
         resetComposingState(true /* alsoResetLastComposedWord */);
-        if (mSettings.getCurrent().mBigramPredictionEnabled) {
+        final SettingsValues settingsValues = mSettings.getCurrent();
+        if (settingsValues.mBigramPredictionEnabled) {
             clearSuggestionStrip();
         } else {
-            setSuggestedWords(mSettings.getCurrent().mSuggestPuncList, false);
+            setSuggestedWords(settingsValues.mSuggestPuncList, false);
         }
         mConnection.resetCachesUponCursorMove(newCursorPosition, shouldFinishComposition);
     }
@@ -1293,8 +1295,9 @@
     }
 
     private boolean maybeDoubleSpacePeriod() {
-        if (!mSettings.getCurrent().mCorrectionEnabled) return false;
-        if (!mSettings.getCurrent().mUseDoubleSpacePeriod) return false;
+        final SettingsValues settingsValues = mSettings.getCurrent();
+        if (!settingsValues.mCorrectionEnabled) return false;
+        if (!settingsValues.mUseDoubleSpacePeriod) return false;
         if (!mHandler.isAcceptingDoubleSpacePeriod()) return false;
         final CharSequence lastThree = mConnection.getTextBeforeCursor(3, 0);
         if (lastThree != null && lastThree.length() == 3
@@ -1554,12 +1557,13 @@
             final int spaceState) {
         mSpaceState = SPACE_STATE_NONE;
         final boolean didAutoCorrect;
-        if (mSettings.getCurrent().isWordSeparator(primaryCode)) {
+        final SettingsValues settingsValues = mSettings.getCurrent();
+        if (settingsValues.isWordSeparator(primaryCode)) {
             didAutoCorrect = handleSeparator(primaryCode, x, y, spaceState);
         } else {
             didAutoCorrect = false;
             if (SPACE_STATE_PHANTOM == spaceState) {
-                if (mSettings.isInternal()) {
+                if (settingsValues.mIsInternal) {
                     if (mWordComposer.isComposingWord() && mWordComposer.isBatchMode()) {
                         LatinImeLoggerUtils.onAutoCorrection(
                                 "", mWordComposer.getTypedWord(), " ", mWordComposer);
@@ -1619,8 +1623,9 @@
         BatchInputUpdater.getInstance().onStartBatchInput(this);
         mHandler.cancelUpdateSuggestionStrip();
         mConnection.beginBatchEdit();
+        final SettingsValues settingsValues = mSettings.getCurrent();
         if (mWordComposer.isComposingWord()) {
-            if (mSettings.isInternal()) {
+            if (settingsValues.mIsInternal) {
                 if (mWordComposer.isBatchMode()) {
                     LatinImeLoggerUtils.onAutoCorrection(
                             "", mWordComposer.getTypedWord(), " ", mWordComposer);
@@ -1649,7 +1654,7 @@
         }
         final int codePointBeforeCursor = mConnection.getCodePointBeforeCursor();
         if (Character.isLetterOrDigit(codePointBeforeCursor)
-                || mSettings.getCurrent().isUsuallyFollowedBySpace(codePointBeforeCursor)) {
+                || settingsValues.isUsuallyFollowedBySpace(codePointBeforeCursor)) {
             mSpaceState = SPACE_STATE_PHANTOM;
         }
         mConnection.endBatchEdit();
@@ -1869,8 +1874,9 @@
                 mConnection.deleteSurroundingText(1, 0);
             }
         } else {
+            final SettingsValues currentSettings = mSettings.getCurrent();
             if (mLastComposedWord.canRevertCommit()) {
-                if (mSettings.isInternal()) {
+                if (currentSettings.mIsInternal) {
                     LatinImeLoggerUtils.onAutoCorrectionCancellation();
                 }
                 revertCommit();
@@ -1947,7 +1953,7 @@
                     }
                 }
             }
-            if (mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) {
+            if (currentSettings.isSuggestionsRequested(mDisplayOrientation)) {
                 restartSuggestionsOnWordBeforeCursorIfAtEndOfWord();
             }
         }
@@ -1964,8 +1970,9 @@
         }
         if ((SPACE_STATE_WEAK == spaceState || SPACE_STATE_SWAP_PUNCTUATION == spaceState)
                 && isFromSuggestionStrip) {
-            if (mSettings.getCurrent().isUsuallyPrecededBySpace(code)) return false;
-            if (mSettings.getCurrent().isUsuallyFollowedBySpace(code)) return true;
+            final SettingsValues currentSettings = mSettings.getCurrent();
+            if (currentSettings.isUsuallyPrecededBySpace(code)) return false;
+            if (currentSettings.isUsuallyFollowedBySpace(code)) return true;
             mConnection.removeTrailingSpace();
         }
         return false;
@@ -1977,8 +1984,8 @@
 
         // TODO: remove isWordConnector() and use isUsuallyFollowedBySpace() instead.
         // See onStartBatchInput() to see how to do it.
-        if (SPACE_STATE_PHANTOM == spaceState &&
-                !mSettings.getCurrent().isWordConnector(primaryCode)) {
+        final SettingsValues currentSettings = mSettings.getCurrent();
+        if (SPACE_STATE_PHANTOM == spaceState && !currentSettings.isWordConnector(primaryCode)) {
             if (isComposingWord) {
                 // Sanity check
                 throw new RuntimeException("Should not be composing here");
@@ -1996,9 +2003,9 @@
         // dozen milliseconds. Avoid calling it as much as possible, since we are on the UI
         // thread here.
         if (!isComposingWord && (isAlphabet(primaryCode)
-                || mSettings.getCurrent().isWordConnector(primaryCode))
-                && mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation) &&
-                !mConnection.isCursorTouchingWord(mSettings.getCurrent())) {
+                || currentSettings.isWordConnector(primaryCode))
+                && currentSettings.isSuggestionsRequested(mDisplayOrientation) &&
+                !mConnection.isCursorTouchingWord(currentSettings)) {
             // Reset entirely the composing state anyway, then start composing a new word unless
             // the character is a single quote. The idea here is, single quote is not a
             // separator and it should be treated as a normal character, except in the first
@@ -2041,7 +2048,7 @@
             if (null != mSuggestionStripView) mSuggestionStripView.dismissAddToDictionaryHint();
         }
         mHandler.postUpdateSuggestionStrip();
-        if (mSettings.isInternal()) {
+        if (currentSettings.mIsInternal) {
             LatinImeLoggerUtils.onNonSeparator((char)primaryCode, x, y);
         }
     }
@@ -2054,9 +2061,10 @@
             final CharSequence selectedText =
                     mConnection.getSelectedText(0 /* flags, 0 for no styles */);
             if (TextUtils.isEmpty(selectedText)) return; // Race condition with the input connection
+            final SettingsValues currentSettings = mSettings.getCurrent();
             mRecapitalizeStatus.initialize(mLastSelectionStart, mLastSelectionEnd,
-                    selectedText.toString(), mSettings.getCurrentLocale(),
-                    mSettings.getWordSeparators());
+                    selectedText.toString(), currentSettings.mLocale,
+                    currentSettings.mWordSeparators);
             // We trim leading and trailing whitespace.
             mRecapitalizeStatus.trim();
             // Trimming the object may have changed the length of the string, and we need to
@@ -2090,8 +2098,9 @@
             // first so that we can insert the separator at the current cursor position.
             resetEntireInputState(mLastSelectionStart);
         }
+        final SettingsValues currentSettings = mSettings.getCurrent();
         if (mWordComposer.isComposingWord()) {
-            if (mSettings.getCurrent().mCorrectionEnabled) {
+            if (currentSettings.mCorrectionEnabled) {
                 // TODO: maybe cache Strings in an <String> sparse array or something
                 commitCurrentAutoCorrection(new String(new int[]{primaryCode}, 0, 1));
                 didAutoCorrect = true;
@@ -2104,7 +2113,7 @@
                 Constants.SUGGESTION_STRIP_COORDINATE == x);
 
         if (SPACE_STATE_PHANTOM == spaceState &&
-                mSettings.getCurrent().isUsuallyPrecededBySpace(primaryCode)) {
+                currentSettings.isUsuallyPrecededBySpace(primaryCode)) {
             promotePhantomSpace();
         }
         if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@@ -2113,7 +2122,7 @@
         sendKeyCodePoint(primaryCode);
 
         if (Constants.CODE_SPACE == primaryCode) {
-            if (mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) {
+            if (currentSettings.isSuggestionsRequested(mDisplayOrientation)) {
                 if (maybeDoubleSpacePeriod()) {
                     mSpaceState = SPACE_STATE_DOUBLE;
                 } else if (!isShowingPunctuationList()) {
@@ -2128,7 +2137,7 @@
                 swapSwapperAndSpace();
                 mSpaceState = SPACE_STATE_SWAP_PUNCTUATION;
             } else if (SPACE_STATE_PHANTOM == spaceState
-                    && mSettings.getCurrent().isUsuallyFollowedBySpace(primaryCode)) {
+                    && currentSettings.isUsuallyFollowedBySpace(primaryCode)) {
                 // If we are in phantom space state, and the user presses a separator, we want to
                 // stay in phantom space state so that the next keypress has a chance to add the
                 // space. For example, if I type "Good dat", pick "day" from the suggestion strip
@@ -2146,7 +2155,7 @@
             // already displayed or not, so it's okay.
             setPunctuationSuggestions();
         }
-        if (mSettings.isInternal()) {
+        if (currentSettings.mIsInternal) {
             LatinImeLoggerUtils.onSeparator((char)primaryCode, x, y);
         }
 
@@ -2179,17 +2188,18 @@
     }
 
     private boolean isSuggestionsStripVisible() {
+        final SettingsValues currentSettings = mSettings.getCurrent();
         if (mSuggestionStripView == null)
             return false;
         if (mSuggestionStripView.isShowingAddToDictionaryHint())
             return true;
-        if (null == mSettings.getCurrent())
+        if (null == currentSettings)
             return false;
-        if (!mSettings.getCurrent().isSuggestionStripVisibleInOrientation(mDisplayOrientation))
+        if (!currentSettings.isSuggestionStripVisibleInOrientation(mDisplayOrientation))
             return false;
-        if (mSettings.getCurrent().isApplicationSpecifiedCompletionsOn())
+        if (currentSettings.isApplicationSpecifiedCompletionsOn())
             return true;
-        return mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation);
+        return currentSettings.isSuggestionsRequested(mDisplayOrientation);
     }
 
     private void clearSuggestionStrip() {
@@ -2222,10 +2232,11 @@
 
     private void updateSuggestionStrip() {
         mHandler.cancelUpdateSuggestionStrip();
+        final SettingsValues currentSettings = mSettings.getCurrent();
 
         // Check if we have a suggestion engine attached.
         if (mSuggest == null
-                || !mSettings.getCurrent().isSuggestionsRequested(mDisplayOrientation)) {
+                || !currentSettings.isSuggestionsRequested(mDisplayOrientation)) {
             if (mWordComposer.isComposingWord()) {
                 Log.w(TAG, "Called updateSuggestionsOrPredictions but suggestions were not "
                         + "requested!");
@@ -2233,7 +2244,7 @@
             return;
         }
 
-        if (!mWordComposer.isComposingWord() && !mSettings.getCurrent().mBigramPredictionEnabled) {
+        if (!mWordComposer.isComposingWord() && !currentSettings.mBigramPredictionEnabled) {
             setPunctuationSuggestions();
             return;
         }
@@ -2254,12 +2265,13 @@
         // whatever is *before* the half-committed word in the buffer, hence 2; if we aren't, we
         // should just skip whitespace if any, so 1.
         // TODO: this is slow (2-way IPC) - we should probably cache this instead.
+        final SettingsValues currentSettings = mSettings.getCurrent();
         final String prevWord =
-                mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators,
+                mConnection.getNthPreviousWord(currentSettings.mWordSeparators,
                 mWordComposer.isComposingWord() ? 2 : 1);
         return suggest.getSuggestedWords(mWordComposer, prevWord, keyboard.getProximityInfo(),
-                mSettings.getBlockPotentiallyOffensive(),
-                mSettings.getCurrent().mCorrectionEnabled, sessionId);
+                currentSettings.mBlockPotentiallyOffensive,
+                currentSettings.mCorrectionEnabled, sessionId);
     }
 
     private SuggestedWords getSuggestedWordsOrOlderSuggestions(final int sessionId) {
@@ -2385,18 +2397,19 @@
         }
 
         mConnection.beginBatchEdit();
+        final SettingsValues currentSettings = mSettings.getCurrent();
         if (SPACE_STATE_PHANTOM == mSpaceState && suggestion.length() > 0
                 // In the batch input mode, a manually picked suggested word should just replace
                 // the current batch input text and there is no need for a phantom space.
                 && !mWordComposer.isBatchMode()) {
             final int firstChar = Character.codePointAt(suggestion, 0);
-            if (!mSettings.getCurrent().isWordSeparator(firstChar)
-                    || mSettings.getCurrent().isUsuallyPrecededBySpace(firstChar)) {
+            if (!currentSettings.isWordSeparator(firstChar)
+                    || currentSettings.isUsuallyPrecededBySpace(firstChar)) {
                 promotePhantomSpace();
             }
         }
 
-        if (mSettings.getCurrent().isApplicationSpecifiedCompletionsOn()
+        if (currentSettings.isApplicationSpecifiedCompletionsOn()
                 && mApplicationSpecifiedCompletions != null
                 && index >= 0 && index < mApplicationSpecifiedCompletions.length) {
             mSuggestedWords = SuggestedWords.EMPTY;
@@ -2441,13 +2454,13 @@
                         // If the suggestion is not in the dictionary, the hint should be shown.
                         && !AutoCorrectionUtils.isValidWord(mSuggest, suggestion, true);
 
-        if (mSettings.isInternal()) {
+        if (currentSettings.mIsInternal) {
             LatinImeLoggerUtils.onSeparator((char)Constants.CODE_SPACE,
                     Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE);
         }
         if (showingAddToDictionaryHint && mIsUserDictionaryAvailable) {
             mSuggestionStripView.showAddToDictionaryHint(
-                    suggestion, mSettings.getCurrent().mHintToSaveText);
+                    suggestion, currentSettings.mHintToSaveText);
         } else {
             // If we're not showing the "Touch again to save", then update the suggestion strip.
             mHandler.postUpdateSuggestionStrip();
@@ -2473,10 +2486,11 @@
     }
 
     private void setPunctuationSuggestions() {
-        if (mSettings.getCurrent().mBigramPredictionEnabled) {
+        final SettingsValues currentSettings = mSettings.getCurrent();
+        if (currentSettings.mBigramPredictionEnabled) {
             clearSuggestionStrip();
         } else {
-            setSuggestedWords(mSettings.getCurrent().mSuggestPuncList, false);
+            setSuggestedWords(currentSettings.mSuggestPuncList, false);
         }
         setAutoCorrectionIndicator(false);
         setSuggestionStripShown(isSuggestionsStripVisible());
@@ -2489,7 +2503,8 @@
         // If correction is not enabled, we don't add words to the user history dictionary.
         // That's to avoid unintended additions in some sensitive fields, or fields that
         // expect to receive non-words.
-        if (!mSettings.getCurrent().mCorrectionEnabled) return null;
+        final SettingsValues currentSettings = mSettings.getCurrent();
+        if (!currentSettings.mCorrectionEnabled) return null;
 
         final Suggest suggest = mSuggest;
         final UserHistoryDictionary userHistoryDictionary = mUserHistoryDictionary;
@@ -2497,8 +2512,7 @@
             // Avoid concurrent issue
             return null;
         }
-        final String prevWord
-                = mConnection.getNthPreviousWord(mSettings.getCurrent().mWordSeparators, 2);
+        final String prevWord = mConnection.getNthPreviousWord(currentSettings.mWordSeparators, 2);
         final String secondWord;
         if (mWordComposer.wasAutoCapitalized() && !mWordComposer.isMostlyCaps()) {
             secondWord = suggestion.toLowerCase(mSubtypeSwitcher.getCurrentSubtypeLocale());
@@ -2527,8 +2541,9 @@
         if (mLastSelectionStart != mLastSelectionEnd) return;
         // If we don't know the cursor location, return.
         if (mLastSelectionStart < 0) return;
-        if (!mConnection.isCursorTouchingWord(mSettings.getCurrent())) return;
-        final TextRange range = mConnection.getWordRangeAtCursor(mSettings.getWordSeparators(),
+        final SettingsValues currentSettings = mSettings.getCurrent();
+        if (!mConnection.isCursorTouchingWord(currentSettings)) return;
+        final TextRange range = mConnection.getWordRangeAtCursor(currentSettings.mWordSeparators,
                 0 /* additionalPrecedingWordsCount */);
         if (null == range) return; // Happens if we don't have an input connection at all
         // If for some strange reason (editor bug or so) we measure the text before the cursor as
diff --git a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
index 000c252..167c691 100644
--- a/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
+++ b/java/src/com/android/inputmethod/latin/makedict/BinaryDictIOUtils.java
@@ -982,6 +982,7 @@
         return null;
     }
 
+    private static final int HEADER_READING_BUFFER_SIZE = 16384;
     /**
      * Convenience method to read the header of a binary file.
      *
@@ -991,7 +992,6 @@
      * @param offset The offset in the file where to start reading the data.
      * @param length The length of the data file.
      */
-    private static final int HEADER_READING_BUFFER_SIZE = 16384;
     public static FileHeader getDictionaryFileHeader(
             final File file, final long offset, final long length)
             throws FileNotFoundException, IOException, UnsupportedFormatException {
diff --git a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
index 5a2b24c..118dc22 100644
--- a/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
+++ b/java/src/com/android/inputmethod/latin/makedict/FusionDictionary.java
@@ -34,6 +34,8 @@
 public final class FusionDictionary implements Iterable<Word> {
     private static final boolean DBG = MakedictLog.DBG;
 
+    private static int CHARACTER_NOT_FOUND_INDEX = -1;
+
     /**
      * A node of the dictionary, containing several CharGroups.
      *
@@ -473,7 +475,7 @@
         CharGroup currentGroup = null;
         int differentCharIndex = 0; // Set by the loop to the index of the char that differs
         int nodeIndex = findIndexOfChar(mRoot, word[charIndex]);
-        while (CHARACTER_NOT_FOUND != nodeIndex) {
+        while (CHARACTER_NOT_FOUND_INDEX != nodeIndex) {
             currentGroup = currentNode.mData.get(nodeIndex);
             differentCharIndex = compareArrays(currentGroup.mChars, word, charIndex);
             if (ARRAYS_ARE_EQUAL != differentCharIndex
@@ -485,7 +487,7 @@
             nodeIndex = findIndexOfChar(currentNode, word[charIndex]);
         }
 
-        if (-1 == nodeIndex) {
+        if (CHARACTER_NOT_FOUND_INDEX == nodeIndex) {
             // No node at this point to accept the word. Create one.
             final int insertionIndex = findInsertionIndex(currentNode, word[charIndex]);
             final CharGroup newGroup = new CharGroup(
@@ -612,20 +614,18 @@
         return result >= 0 ? result : -result - 1;
     }
 
-    private static int CHARACTER_NOT_FOUND = -1;
-
     /**
      * Find the index of a char in a node, if it exists.
      *
      * @param node the node to search in.
      * @param character the character to search for.
-     * @return the position of the character if it's there, or CHARACTER_NOT_FOUND = -1 else.
+     * @return the position of the character if it's there, or CHARACTER_NOT_FOUND_INDEX = -1 else.
      */
     private static int findIndexOfChar(final Node node, int character) {
         final int insertionIndex = findInsertionIndex(node, character);
-        if (node.mData.size() <= insertionIndex) return CHARACTER_NOT_FOUND;
+        if (node.mData.size() <= insertionIndex) return CHARACTER_NOT_FOUND_INDEX;
         return character == node.mData.get(insertionIndex).mChars[0] ? insertionIndex
-                : CHARACTER_NOT_FOUND;
+                : CHARACTER_NOT_FOUND_INDEX;
     }
 
     /**
@@ -640,7 +640,7 @@
         CharGroup currentGroup;
         do {
             int indexOfGroup = findIndexOfChar(node, codePoints[index]);
-            if (CHARACTER_NOT_FOUND == indexOfGroup) return null;
+            if (CHARACTER_NOT_FOUND_INDEX == indexOfGroup) return null;
             currentGroup = node.mData.get(indexOfGroup);
 
             if (codePoints.length - index < currentGroup.mChars.length) return null;
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDicitonary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
similarity index 92%
rename from java/src/com/android/inputmethod/latin/personalization/PersonalizationDicitonary.java
rename to java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
index d3e2dfe..19554d6 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationDicitonary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationDictionary.java
@@ -24,7 +24,7 @@
 /**
  * This class is a dictionary for the personalized language model that uses binary dictionary.
  */
-public class PersonalizationDicitonary extends ExpandableBinaryDictionary {
+public class PersonalizationDictionary extends ExpandableBinaryDictionary {
     private static final String NAME = "personalization";
 
     public static void registerUpdateListener(PersonalizationDictionaryUpdateListener listener) {
@@ -35,7 +35,7 @@
     private final String mLocale;
 
     // Singleton
-    private PersonalizationDicitonary(final Context context, final String locale) {
+    private PersonalizationDictionary(final Context context, final String locale) {
         super(context, getFilenameWithLocale(NAME, locale), Dictionary.TYPE_PERSONALIZATION);
         mLocale = locale;
     }
diff --git a/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDicitonary.java b/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java
similarity index 91%
rename from java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDicitonary.java
rename to java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java
index 3e77725..7bce979 100644
--- a/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDicitonary.java
+++ b/java/src/com/android/inputmethod/latin/personalization/PersonalizationPredictionDictionary.java
@@ -25,7 +25,7 @@
 /**
  * This class is a dictionary for the personalized prediction language model implemented in Java.
  */
-public class PersonalizationPredictionDicitonary extends ExpandableDictionary {
+public class PersonalizationPredictionDictionary extends ExpandableDictionary {
     public static void registerUpdateListener(PersonalizationDictionaryUpdateListener listener) {
         // TODO: Implement
     }
@@ -35,7 +35,7 @@
     private final SharedPreferences mPrefs;
 
     // Singleton
-    private PersonalizationPredictionDicitonary(final Context context, final String locale,
+    private PersonalizationPredictionDictionary(final Context context, final String locale,
             final SharedPreferences sp) {
         super(context, Dictionary.TYPE_PERSONALIZATION_PREDICTION_IN_JAVA);
         mLocale = locale;
diff --git a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
index 34ea227..e675f42 100644
--- a/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
+++ b/java/src/com/android/inputmethod/latin/settings/DebugSettings.java
@@ -32,7 +32,6 @@
 
 public final class DebugSettings extends PreferenceFragment
         implements SharedPreferences.OnSharedPreferenceChangeListener {
-    private static final String TAG = DebugSettings.class.getSimpleName();
 
     public static final String PREF_DEBUG_MODE = "debug_mode";
     public static final String PREF_FORCE_NON_DISTINCT_MULTITOUCH = "force_non_distinct_multitouch";
diff --git a/java/src/com/android/inputmethod/latin/settings/Settings.java b/java/src/com/android/inputmethod/latin/settings/Settings.java
index b690fed..2631cd3 100644
--- a/java/src/com/android/inputmethod/latin/settings/Settings.java
+++ b/java/src/com/android/inputmethod/latin/settings/Settings.java
@@ -93,7 +93,6 @@
 
     private Resources mRes;
     private SharedPreferences mPrefs;
-    private Locale mCurrentLocale;
     private SettingsValues mSettingsValues;
 
     private static final Settings sInstance = new Settings();
@@ -128,16 +127,15 @@
             Log.w(TAG, "onSharedPreferenceChanged called before loadSettings.");
             return;
         }
-        loadSettings(mCurrentLocale, mSettingsValues.mInputAttributes);
+        loadSettings(mSettingsValues.mLocale, mSettingsValues.mInputAttributes);
     }
 
     public void loadSettings(final Locale locale, final InputAttributes inputAttributes) {
-        mCurrentLocale = locale;
         final SharedPreferences prefs = mPrefs;
         final RunInLocale<SettingsValues> job = new RunInLocale<SettingsValues>() {
             @Override
             protected SettingsValues job(final Resources res) {
-                return new SettingsValues(prefs, res, inputAttributes);
+                return new SettingsValues(prefs, locale, res, inputAttributes);
             }
         };
         mSettingsValues = job.runInLocale(mRes, locale);
@@ -160,10 +158,6 @@
         return mSettingsValues.isWordSeparator(code);
     }
 
-    public Locale getCurrentLocale() {
-        return mCurrentLocale;
-    }
-
     public boolean getBlockPotentiallyOffensive() {
         return mSettingsValues.mBlockPotentiallyOffensive;
     }
diff --git a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
index 3fa00bb..8aafb07 100644
--- a/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/settings/SettingsValues.java
@@ -32,11 +32,11 @@
 import com.android.inputmethod.latin.SuggestedWords.SuggestedWordInfo;
 import com.android.inputmethod.latin.utils.CollectionUtils;
 import com.android.inputmethod.latin.utils.InputTypeUtils;
-import com.android.inputmethod.latin.utils.RunInLocale;
 import com.android.inputmethod.latin.utils.StringUtils;
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Locale;
 
 /**
  * When you call the constructor of this class, you may want to change the current system locale by
@@ -75,6 +75,7 @@
     public final boolean mGestureFloatingPreviewTextEnabled;
     public final boolean mSlidingKeyInputPreviewEnabled;
     public final int mKeyLongpressTimeout;
+    public final Locale mLocale;
 
     // From the input box
     public final InputAttributes mInputAttributes;
@@ -97,8 +98,9 @@
     // Debug settings
     public final boolean mIsInternal;
 
-    public SettingsValues(final SharedPreferences prefs, final Resources res,
+    public SettingsValues(final SharedPreferences prefs, final Locale locale, final Resources res,
             final InputAttributes inputAttributes) {
+        mLocale = locale;
         // Get the resources
         mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
         mSymbolsPrecededBySpace =
diff --git a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java
index 30466bb..4fc132f 100644
--- a/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java
+++ b/java/src/com/android/inputmethod/latin/userdictionary/UserDictionaryAddWordFragment.java
@@ -103,7 +103,7 @@
     /**
      * Callback for the framework when a menu option is pressed.
      *
-     * @param MenuItem the item that was pressed
+     * @param item the item that was pressed
      * @return false to allow normal menu processing to proceed, true to consume it here
      */
     @Override
diff --git a/java/src/com/android/inputmethod/latin/utils/CsvUtils.java b/java/src/com/android/inputmethod/latin/utils/CsvUtils.java
index 159ebb1..36b927e 100644
--- a/java/src/com/android/inputmethod/latin/utils/CsvUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/CsvUtils.java
@@ -22,7 +22,7 @@
 
 /**
  * Utility methods for parsing and serializing Comma-Separated Values. The public APIs of this
- * utility class are {@link #split(String)}, {@link #split(int,String)}, {@link #join(String)},
+ * utility class are {@link #split(String)}, {@link #split(int,String)}, {@link #join(String...)},
  * {@link #join(int,String...)}, and {@link #join(int,int[],String...)}.
  *
  * This class implements CSV parsing and serializing methods conforming to RFC 4180 with an
diff --git a/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java b/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java
index ef9cacf..729a872 100644
--- a/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java
+++ b/java/src/com/android/inputmethod/latin/utils/UsabilityStudyLogUtils.java
@@ -191,7 +191,7 @@
                     Log.w(USABILITY_TAG, e2);
                     return;
                 }
-                if (destFile == null || !destFile.exists()) {
+                if (!destFile.exists()) {
                     Log.w(USABILITY_TAG, "Dest file doesn't exist.");
                     return;
                 }
diff --git a/java/src/com/android/inputmethod/research/MainLogBuffer.java b/java/src/com/android/inputmethod/research/MainLogBuffer.java
index 3482153..6df7c17 100644
--- a/java/src/com/android/inputmethod/research/MainLogBuffer.java
+++ b/java/src/com/android/inputmethod/research/MainLogBuffer.java
@@ -119,9 +119,9 @@
      *
      * @param logUnits a LogUnit list to check for publishability
      * @param nGramSize the smallest n-gram acceptable to be published.  if
-     * {@link ResearchLogger.IS_LOGGING_EVERYTHING} is true, then publish if there are more than
+     * {@link ResearchLogger#IS_LOGGING_EVERYTHING} is true, then publish if there are more than
      * {@code minNGramSize} words in the logUnits, otherwise wait.  if {@link
-     * ResearchLogger.IS_LOGGING_EVERYTHING} is false, then ensure that there are exactly nGramSize
+     * ResearchLogger#IS_LOGGING_EVERYTHING} is false, then ensure that there are exactly nGramSize
      * words in the LogUnits.
      *
      * @return one of the {@code PUBLISHABILITY_*} result codes defined in this class.
diff --git a/java/src/com/android/inputmethod/research/MotionEventReader.java b/java/src/com/android/inputmethod/research/MotionEventReader.java
index fbfd9b5..3388645 100644
--- a/java/src/com/android/inputmethod/research/MotionEventReader.java
+++ b/java/src/com/android/inputmethod/research/MotionEventReader.java
@@ -315,16 +315,6 @@
         return pointerCoords;
     }
 
-    /**
-     * Tests that {@code x} is uninitialized.
-     *
-     * Assumes that {@code x} will never be given a valid value less than 0, and that
-     * UNINITIALIZED_FLOAT is less than 0.0f.
-     */
-    private boolean isUninitializedFloat(final float x) {
-        return x < 0.0f;
-    }
-
     private void addMotionEventData(final ReplayData replayData, final int actionType,
             final long time, final PointerProperties[] pointerProperties,
             final PointerCoords[] pointerCoords) {
diff --git a/java/src/com/android/inputmethod/research/ResearchLogger.java b/java/src/com/android/inputmethod/research/ResearchLogger.java
index ed047e1..fc8615b 100644
--- a/java/src/com/android/inputmethod/research/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/research/ResearchLogger.java
@@ -180,7 +180,6 @@
     private ResearchLogDirectory mResearchLogDirectory;
     private SplashScreen mSplashScreen;
 
-    private Intent mUploadIntent;
     private Intent mUploadNowIntent;
 
     /* package for test */ LogUnit mCurrentLogUnit = new LogUnit();
@@ -233,7 +232,6 @@
         resetLogBuffers();
 
         // Initialize external services
-        mUploadIntent = new Intent(mLatinIME, UploaderService.class);
         mUploadNowIntent = new Intent(mLatinIME, UploaderService.class);
         mUploadNowIntent.putExtra(UploaderService.EXTRA_UPLOAD_UNCONDITIONALLY, true);
         if (ProductionFlag.USES_DEVELOPMENT_ONLY_DIAGNOSTICS) {
@@ -319,12 +317,6 @@
         restart();
     }
 
-    private void setLoggingAllowed(final boolean enableLogging) {
-        if (mPrefs == null) return;
-        sIsLogging = enableLogging;
-        ResearchSettings.writeResearchLoggerEnabledFlag(mPrefs, enableLogging);
-    }
-
     private void checkForEmptyEditor() {
         if (mLatinIME == null) {
             return;
@@ -1261,10 +1253,23 @@
     private static final LogStatement LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY =
             new LogStatement("LatinIMEPickSuggestionManually", true, false, "replacedWord", "index",
                     "suggestion", "x", "y", "isBatchMode", "score", "kind", "sourceDict");
+    /**
+     * Log a call to LatinIME.pickSuggestionManually().
+     *
+     * @param replacedWord the typed word that this manual suggestion replaces. May not be null.
+     * @param index the index in the suggestion strip
+     * @param suggestion the committed suggestion. May not be null.
+     * @param isBatchMode whether this was input in batch mode, aka gesture.
+     * @param score the internal score of the suggestion, as output by the dictionary
+     * @param kind the kind of suggestion, as one of the SuggestedWordInfo#KIND_* constants
+     * @param sourceDict the source origin of this word, as one of the Dictionary#TYPE_* constants.
+     */
     public static void latinIME_pickSuggestionManually(final String replacedWord,
             final int index, final String suggestion, final boolean isBatchMode,
             final int score, final int kind, final String sourceDict) {
         final ResearchLogger researchLogger = getInstance();
+        // Note : suggestion can't be null here, because it's only called in a place where it
+        // can't be null.
         if (!replacedWord.equals(suggestion.toString())) {
             // The user chose something other than what was already there.
             researchLogger.setCurrentLogUnitContainsUserDeletions();
@@ -1273,7 +1278,7 @@
         final String scrubbedWord = scrubDigitsFromString(suggestion);
         researchLogger.enqueueEvent(LOGSTATEMENT_LATINIME_PICKSUGGESTIONMANUALLY,
                 scrubDigitsFromString(replacedWord), index,
-                suggestion == null ? null : scrubbedWord, Constants.SUGGESTION_STRIP_COORDINATE,
+                scrubbedWord, Constants.SUGGESTION_STRIP_COORDINATE,
                 Constants.SUGGESTION_STRIP_COORDINATE, isBatchMode, score, kind, sourceDict);
         researchLogger.commitCurrentLogUnitAsWord(scrubbedWord, Long.MAX_VALUE, isBatchMode);
         researchLogger.mStatistics.recordManualSuggestion(SystemClock.uptimeMillis());