Merge "KeyboardState keeps track of isAlphabetMode and isSymbolShifted"
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 602de92..de273b5 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -221,11 +221,9 @@
     private long mLastKeyTime;
 
     private AudioManager mAudioManager;
-    private float mFxVolume = -1.0f; // default volume
     private boolean mSilentModeOn; // System-wide current configuration
 
     private VibratorCompatWrapper mVibrator;
-    private long mKeypressVibrationDuration = -1;
 
     // TODO: Move this flag to VoiceProxy
     private boolean mConfigurationChanging;
@@ -550,8 +548,6 @@
         if (null == mSubtypeSwitcher) mSubtypeSwitcher = SubtypeSwitcher.getInstance();
         mSettingsValues = new SettingsValues(mPrefs, this, mSubtypeSwitcher.getInputLocaleStr());
         resetContactsDictionary(null == mSuggest ? null : mSuggest.getContactsDictionary());
-        updateSoundEffectVolume();
-        updateKeypressVibrationDuration();
     }
 
     private void initSuggest() {
@@ -1791,8 +1787,8 @@
             prevWord = EditingUtils.getPreviousWord(ic, mSettingsValues.mWordSeparators);
         }
         // getSuggestedWordBuilder handles gracefully a null value of prevWord
-        final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(
-                wordComposer, prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo());
+        final SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(wordComposer,
+                prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo(), mCorrectionMode);
 
         boolean autoCorrectionAvailable = !mInputTypeNoAutoCorrect && mSuggest.hasAutoCorrection();
         final CharSequence typedWord = wordComposer.getTypedWord();
@@ -2035,7 +2031,7 @@
         final CharSequence prevWord = EditingUtils.getThisWord(getCurrentInputConnection(),
                 mSettingsValues.mWordSeparators);
         SuggestedWords.Builder builder = mSuggest.getSuggestedWordBuilder(sEmptyWordComposer,
-                prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo());
+                prevWord, mKeyboardSwitcher.getLatinKeyboard().getProximityInfo(), mCorrectionMode);
 
         if (builder.size() > 0) {
             // Explicitly supply an empty typed word (the no-second-arg version of
@@ -2321,11 +2317,6 @@
         }
     };
 
-    // update keypress sound volume
-    private void updateSoundEffectVolume() {
-        mFxVolume = Utils.getCurrentKeypressSoundVolume(mPrefs, mResources);
-    }
-
     // update flags for silent mode
     private void updateRingerMode() {
         if (mAudioManager == null) {
@@ -2335,10 +2326,6 @@
         mSilentModeOn = (mAudioManager.getRingerMode() != AudioManager.RINGER_MODE_NORMAL);
     }
 
-    private void updateKeypressVibrationDuration() {
-        mKeypressVibrationDuration = Utils.getCurrentVibrationDuration(mPrefs, mResources);
-    }
-
     private void playKeyClick(int primaryCode) {
         // if mAudioManager is null, we don't have the ringer state yet
         // mAudioManager will be set by updateRingerMode
@@ -2363,7 +2350,7 @@
                 sound = AudioManager.FX_KEYPRESS_STANDARD;
                 break;
             }
-            mAudioManager.playSoundEffect(sound, mFxVolume);
+            mAudioManager.playSoundEffect(sound, mSettingsValues.mFxVolume);
         }
     }
 
@@ -2371,7 +2358,7 @@
         if (!mSettingsValues.mVibrateOn) {
             return;
         }
-        if (mKeypressVibrationDuration < 0) {
+        if (mSettingsValues.mKeypressVibrationDuration < 0) {
             // Go ahead with the system default
             LatinKeyboardView inputView = mKeyboardSwitcher.getKeyboardView();
             if (inputView != null) {
@@ -2380,7 +2367,7 @@
                         HapticFeedbackConstants.FLAG_IGNORE_GLOBAL_SETTING);
             }
         } else if (mVibrator != null) {
-            mVibrator.vibrate(mKeypressVibrationDuration);
+            mVibrator.vibrate(mSettingsValues.mKeypressVibrationDuration);
         }
     }
 
@@ -2399,9 +2386,6 @@
         mCorrectionMode = shouldAutoCorrect ? Suggest.CORRECTION_FULL : Suggest.CORRECTION_NONE;
         mCorrectionMode = (mSettingsValues.mBigramSuggestionEnabled && shouldAutoCorrect)
                 ? Suggest.CORRECTION_FULL_BIGRAM : mCorrectionMode;
-        if (mSuggest != null) {
-            mSuggest.setCorrectionMode(mCorrectionMode);
-        }
     }
 
     private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) {
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 9f2f317..4166e62 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -456,7 +456,7 @@
             SharedPreferences sp, Resources res) {
         if (mKeypressVibrationDurationSettingsPref != null) {
             mKeypressVibrationDurationSettingsPref.setSummary(
-                    Utils.getCurrentVibrationDuration(sp, res)
+                    SettingsValues.getCurrentVibrationDuration(sp, res)
                             + res.getString(R.string.settings_ms));
         }
     }
@@ -484,7 +484,7 @@
         });
         final View v = context.getLayoutInflater().inflate(
                 R.layout.vibration_settings_dialog, null);
-        final int currentMs = Utils.getCurrentVibrationDuration(
+        final int currentMs = SettingsValues.getCurrentVibrationDuration(
                 getPreferenceManager().getSharedPreferences(), getResources());
         mKeypressVibrationDurationSettingsTextView = (TextView)v.findViewById(R.id.vibration_value);
         final SeekBar sb = (SeekBar)v.findViewById(R.id.vibration_settings);
@@ -513,8 +513,8 @@
 
     private void updateKeypressSoundVolumeSummary(SharedPreferences sp, Resources res) {
         if (mKeypressSoundVolumeSettingsPref != null) {
-            mKeypressSoundVolumeSettingsPref.setSummary(
-                    String.valueOf((int)(Utils.getCurrentKeypressSoundVolume(sp, res) * 100)));
+            mKeypressSoundVolumeSettingsPref.setSummary(String.valueOf(
+                    (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100)));
         }
     }
 
@@ -543,8 +543,8 @@
         });
         final View v = context.getLayoutInflater().inflate(
                 R.layout.sound_effect_volume_dialog, null);
-        final int currentVolumeInt = (int)(Utils.getCurrentKeypressSoundVolume(
-                getPreferenceManager().getSharedPreferences(), getResources()) * 100);
+        final int currentVolumeInt =
+                (int)(SettingsValues.getCurrentKeypressSoundVolume(sp, res) * 100);
         mKeypressSoundVolumeSettingsTextView =
                 (TextView)v.findViewById(R.id.sound_effect_volume_value);
         final SeekBar sb = (SeekBar)v.findViewById(R.id.sound_effect_volume_bar);
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 4aa683a..62cf4a3 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -19,6 +19,7 @@
 import android.content.Context;
 import android.content.SharedPreferences;
 import android.content.res.Resources;
+import android.os.Build;
 import android.util.Log;
 import android.view.inputmethod.EditorInfo;
 
@@ -60,6 +61,10 @@
     private final boolean mVoiceKeyEnabled;
     private final boolean mVoiceKeyOnMain;
 
+    // Deduced settings
+    public final int mKeypressVibrationDuration;
+    public final float mFxVolume;
+
     public SettingsValues(final SharedPreferences prefs, final Context context,
             final String localeStr) {
         final Resources res = context.getResources();
@@ -120,6 +125,9 @@
         mVoiceKeyEnabled = voiceMode != null && !voiceMode.equals(voiceModeOff);
         mVoiceKeyOnMain = voiceMode != null && voiceMode.equals(voiceModeMain);
 
+        mFxVolume = getCurrentKeypressSoundVolume(prefs, res);
+        mKeypressVibrationDuration = getCurrentVibrationDuration(prefs, res);
+
         LocaleUtils.setSystemLocale(res, savedLocale);
     }
 
@@ -241,4 +249,40 @@
     public boolean isVoiceKeyOnMain() {
         return mVoiceKeyOnMain;
     }
-}
\ No newline at end of file
+
+    // Accessed from the settings interface, hence public
+    public static float getCurrentKeypressSoundVolume(final SharedPreferences sp,
+                final Resources res) {
+        final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
+        if (volume >= 0) {
+            return volume;
+        }
+
+        final String[] volumePerHardwareList = res.getStringArray(R.array.keypress_volumes);
+        final String hardwarePrefix = Build.HARDWARE + ",";
+        for (final String element : volumePerHardwareList) {
+            if (element.startsWith(hardwarePrefix)) {
+                return Float.parseFloat(element.substring(element.lastIndexOf(',') + 1));
+            }
+        }
+        return -1.0f;
+    }
+
+    // Likewise
+    public static int getCurrentVibrationDuration(final SharedPreferences sp,
+                final Resources res) {
+        final int ms = sp.getInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, -1);
+        if (ms >= 0) {
+            return ms;
+        }
+        final String[] durationPerHardwareList = res.getStringArray(
+                R.array.keypress_vibration_durations);
+        final String hardwarePrefix = Build.HARDWARE + ",";
+        for (final String element : durationPerHardwareList) {
+            if (element.startsWith(hardwarePrefix)) {
+                return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
+            }
+        }
+        return -1;
+    }
+}
diff --git a/java/src/com/android/inputmethod/latin/Suggest.java b/java/src/com/android/inputmethod/latin/Suggest.java
index b618ca7..e9ca390 100644
--- a/java/src/com/android/inputmethod/latin/Suggest.java
+++ b/java/src/com/android/inputmethod/latin/Suggest.java
@@ -43,9 +43,8 @@
     public static final int APPROX_MAX_WORD_LENGTH = 32;
 
     public static final int CORRECTION_NONE = 0;
-    public static final int CORRECTION_BASIC = 1;
-    public static final int CORRECTION_FULL = 2;
-    public static final int CORRECTION_FULL_BIGRAM = 3;
+    public static final int CORRECTION_FULL = 1;
+    public static final int CORRECTION_FULL_BIGRAM = 2;
 
     /**
      * Words that appear in both bigram and unigram data gets multiplier ranging from
@@ -109,8 +108,6 @@
     private boolean mIsAllUpperCase;
     private int mTrailingSingleQuotesCount;
 
-    private int mCorrectionMode = CORRECTION_BASIC;
-
     public Suggest(final Context context, final int dictionaryResId, final Locale locale) {
         initAsynchronously(context, dictionaryResId, locale);
     }
@@ -171,10 +168,6 @@
         }.start();
     }
 
-    public void setCorrectionMode(int mode) {
-        mCorrectionMode = mode;
-    }
-
     // The main dictionary could have been loaded asynchronously.  Don't cache the return value
     // of this method.
     public boolean hasMainDictionary() {
@@ -253,9 +246,10 @@
      * @return suggested words object.
      */
     public SuggestedWords getSuggestions(final WordComposer wordComposer,
-            final CharSequence prevWordForBigram, final ProximityInfo proximityInfo) {
+            final CharSequence prevWordForBigram, final ProximityInfo proximityInfo,
+            final int correctionMode) {
         return getSuggestedWordBuilder(wordComposer, prevWordForBigram,
-                proximityInfo).build();
+                proximityInfo, correctionMode).build();
     }
 
     private CharSequence capitalizeWord(boolean all, boolean first, CharSequence word) {
@@ -288,7 +282,7 @@
     // TODO: cleanup dictionaries looking up and suggestions building with SuggestedWords.Builder
     public SuggestedWords.Builder getSuggestedWordBuilder(
             final WordComposer wordComposer, CharSequence prevWordForBigram,
-            final ProximityInfo proximityInfo) {
+            final ProximityInfo proximityInfo, final int correctionMode) {
         LatinImeLogger.onStartSuggestion(prevWordForBigram);
         mAutoCorrection.init();
         mIsFirstCharCapitalized = wordComposer.isFirstCharCapitalized();
@@ -308,8 +302,7 @@
         }
         mConsideredWord = consideredWord;
 
-        if (wordComposer.size() <= 1 && (mCorrectionMode == CORRECTION_FULL_BIGRAM
-                || mCorrectionMode == CORRECTION_BASIC)) {
+        if (wordComposer.size() <= 1 && (correctionMode == CORRECTION_FULL_BIGRAM)) {
             // At first character typed, search only the bigrams
             Arrays.fill(mBigramScores, 0);
             collectGarbage(mBigramSuggestions, PREF_MAX_BIGRAMS);
@@ -373,7 +366,7 @@
                 mWhiteListDictionary.getWhitelistedWord(consideredWordString));
 
         mAutoCorrection.updateAutoCorrectionStatus(mUnigramDictionaries, wordComposer,
-                mSuggestions, mScores, consideredWord, mAutoCorrectionThreshold, mCorrectionMode,
+                mSuggestions, mScores, consideredWord, mAutoCorrectionThreshold, correctionMode,
                 whitelistedWord);
 
         if (whitelistedWord != null) {
diff --git a/java/src/com/android/inputmethod/latin/Utils.java b/java/src/com/android/inputmethod/latin/Utils.java
index 3d0aa09..7f507fe 100644
--- a/java/src/com/android/inputmethod/latin/Utils.java
+++ b/java/src/com/android/inputmethod/latin/Utils.java
@@ -17,11 +17,9 @@
 package com.android.inputmethod.latin;
 
 import android.content.Context;
-import android.content.SharedPreferences;
 import android.content.res.Resources;
 import android.inputmethodservice.InputMethodService;
 import android.os.AsyncTask;
-import android.os.Build;
 import android.os.Handler;
 import android.os.HandlerThread;
 import android.os.Process;
@@ -778,38 +776,6 @@
         return s.toUpperCase(locale).charAt(0) + s.substring(1);
     }
 
-    public static int getCurrentVibrationDuration(SharedPreferences sp, Resources res) {
-        final int ms = sp.getInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, -1);
-        if (ms >= 0) {
-            return ms;
-        }
-        final String[] durationPerHardwareList = res.getStringArray(
-                R.array.keypress_vibration_durations);
-        final String hardwarePrefix = Build.HARDWARE + ",";
-        for (final String element : durationPerHardwareList) {
-            if (element.startsWith(hardwarePrefix)) {
-                return (int)Long.parseLong(element.substring(element.lastIndexOf(',') + 1));
-            }
-        }
-        return -1;
-    }
-
-    public static float getCurrentKeypressSoundVolume(SharedPreferences sp, Resources res) {
-        final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
-        if (volume >= 0) {
-            return volume;
-        }
-
-        final String[] volumePerHardwareList = res.getStringArray(R.array.keypress_volumes);
-        final String hardwarePrefix = Build.HARDWARE + ",";
-        for (final String element : volumePerHardwareList) {
-            if (element.startsWith(hardwarePrefix)) {
-                return Float.parseFloat(element.substring(element.lastIndexOf(',') + 1));
-            }
-        }
-        return -1.0f;
-    }
-
     public static boolean willAutoCorrect(SuggestedWords suggestions) {
         return !suggestions.mTypedWordValid && suggestions.mHasAutoCorrectionCandidate
                 && !suggestions.shouldBlockAutoCorrection();
diff --git a/tests/src/com/android/inputmethod/latin/SuggestHelper.java b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
index 0d90e0e..06b1924 100644
--- a/tests/src/com/android/inputmethod/latin/SuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/SuggestHelper.java
@@ -28,6 +28,7 @@
 
 public class SuggestHelper {
     protected final Suggest mSuggest;
+    protected int mCorrectionMode;
     protected final LatinKeyboard mKeyboard;
     private final KeyDetector mKeyDetector;
 
@@ -50,14 +51,14 @@
     }
 
     private void init() {
-        mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL);
+        setCorrectionMode(Suggest.CORRECTION_FULL);
         mKeyDetector.setKeyboard(mKeyboard, 0, 0);
         mKeyDetector.setProximityCorrectionEnabled(true);
         mKeyDetector.setProximityThreshold(mKeyboard.mMostCommonKeyWidth);
     }
 
     public void setCorrectionMode(int correctionMode) {
-        mSuggest.setCorrectionMode(correctionMode);
+        mCorrectionMode = correctionMode;
     }
 
     public boolean hasMainDictionary() {
@@ -78,13 +79,13 @@
     // TODO: This may be slow, but is OK for test so far.
     public SuggestedWords getSuggestions(CharSequence typed) {
         return mSuggest.getSuggestions(createWordComposer(typed), null,
-                mKeyboard.getProximityInfo());
+                mKeyboard.getProximityInfo(), mCorrectionMode);
     }
 
     public CharSequence getFirstSuggestion(CharSequence typed) {
         WordComposer word = createWordComposer(typed);
         SuggestedWords suggestions = mSuggest.getSuggestions(word, null,
-                mKeyboard.getProximityInfo());
+                mKeyboard.getProximityInfo(), mCorrectionMode);
         // Note that suggestions.getWord(0) is the word user typed.
         return suggestions.size() > 1 ? suggestions.getWord(1) : null;
     }
@@ -92,7 +93,7 @@
     public CharSequence getAutoCorrection(CharSequence typed) {
         WordComposer word = createWordComposer(typed);
         SuggestedWords suggestions = mSuggest.getSuggestions(word, null,
-                mKeyboard.getProximityInfo());
+                mKeyboard.getProximityInfo(), mCorrectionMode);
         // Note that suggestions.getWord(0) is the word user typed.
         return (suggestions.size() > 1 && mSuggest.hasAutoCorrection())
                 ? suggestions.getWord(1) : null;
@@ -101,7 +102,7 @@
     public int getSuggestIndex(CharSequence typed, CharSequence expected) {
         WordComposer word = createWordComposer(typed);
         SuggestedWords suggestions = mSuggest.getSuggestions(word, null,
-                mKeyboard.getProximityInfo());
+                mKeyboard.getProximityInfo(), mCorrectionMode);
         // Note that suggestions.getWord(0) is the word user typed.
         for (int i = 1; i < suggestions.size(); i++) {
             if (TextUtils.equals(suggestions.getWord(i), expected))
@@ -113,7 +114,8 @@
     private void getBigramSuggestions(CharSequence previous, CharSequence typed) {
         if (!TextUtils.isEmpty(previous) && (typed.length() > 1)) {
             WordComposer firstChar = createWordComposer(Character.toString(typed.charAt(0)));
-            mSuggest.getSuggestions(firstChar, previous, mKeyboard.getProximityInfo());
+            mSuggest.getSuggestions(firstChar, previous, mKeyboard.getProximityInfo(),
+                    mCorrectionMode);
         }
     }
 
@@ -121,7 +123,7 @@
         WordComposer word = createWordComposer(typed);
         getBigramSuggestions(previous, typed);
         SuggestedWords suggestions = mSuggest.getSuggestions(word, previous,
-                mKeyboard.getProximityInfo());
+                mKeyboard.getProximityInfo(), mCorrectionMode);
         return suggestions.size() > 1 ? suggestions.getWord(1) : null;
     }
 
@@ -129,7 +131,7 @@
         WordComposer word = createWordComposer(typed);
         getBigramSuggestions(previous, typed);
         SuggestedWords suggestions = mSuggest.getSuggestions(word, previous,
-                mKeyboard.getProximityInfo());
+                mKeyboard.getProximityInfo(), mCorrectionMode);
         return (suggestions.size() > 1 && mSuggest.hasAutoCorrection())
                 ? suggestions.getWord(1) : null;
     }
@@ -139,7 +141,7 @@
         WordComposer word = createWordComposer(typed);
         getBigramSuggestions(previous, typed);
         SuggestedWords suggestions = mSuggest.getSuggestions(word, previous,
-                mKeyboard.getProximityInfo());
+                mKeyboard.getProximityInfo(), mCorrectionMode);
         for (int i = 1; i < suggestions.size(); i++) {
             if (TextUtils.equals(suggestions.getWord(i), expected))
                 return i;
diff --git a/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java b/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java
index 023e20a..863c2b2 100644
--- a/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java
+++ b/tests/src/com/android/inputmethod/latin/UserBigramSuggestHelper.java
@@ -38,7 +38,7 @@
                 Suggest.DIC_USER);
         mUserBigram.setDatabaseMax(userBigramMax);
         mUserBigram.setDatabaseDelete(userBigramDelete);
-        mSuggest.setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM);
+        setCorrectionMode(Suggest.CORRECTION_FULL_BIGRAM);
         mSuggest.setUserBigramDictionary(mUserBigram);
     }
 
@@ -59,7 +59,8 @@
         flushUserBigrams();
         if (!TextUtils.isEmpty(previous) && !TextUtils.isEmpty(Character.toString(typed))) {
             WordComposer firstChar = createWordComposer(Character.toString(typed));
-            mSuggest.getSuggestions(firstChar, previous, mKeyboard.getProximityInfo());
+            mSuggest.getSuggestions(firstChar, previous, mKeyboard.getProximityInfo(),
+                    mCorrectionMode);
             boolean reloading = mUserBigram.reloadDictionaryIfRequired();
             if (reloading) mUserBigram.waitForDictionaryLoading();
             mUserBigram.getBigrams(firstChar, previous, mSuggest);