Merge "Add a functionality to attach a log file to Gmail app Bug: 5722703"
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index 842f59f..77218d3 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -274,18 +274,25 @@
                 voiceKeyEnabled, hasShortcutKey);
     }
 
-    public int getKeyboardMode() {
-        return mCurrentId != null ? mCurrentId.mMode : KeyboardId.MODE_TEXT;
-    }
-
     public boolean isAlphabetMode() {
-        return mState.isAlphabetMode();
+        final Keyboard keyboard = getLatinKeyboard();
+        return keyboard != null && keyboard.mId.isAlphabetKeyboard();
     }
 
     public boolean isInputViewShown() {
         return mCurrentInputView != null && mCurrentInputView.isShown();
     }
 
+    public boolean isShiftedOrShiftLocked() {
+        final Keyboard keyboard = getLatinKeyboard();
+        return keyboard != null && keyboard.isShiftedOrShiftLocked();
+    }
+
+    public boolean isManualTemporaryUpperCase() {
+        final Keyboard keyboard = getLatinKeyboard();
+        return keyboard != null && keyboard.isManualTemporaryUpperCase();
+    }
+
     public boolean isKeyboardAvailable() {
         if (mKeyboardView != null)
             return mKeyboardView.getKeyboard() != null;
@@ -301,14 +308,6 @@
         return null;
     }
 
-    public boolean isShiftedOrShiftLocked() {
-        return mState.isShiftedOrShiftLocked();
-    }
-
-    public boolean isManualTemporaryUpperCase() {
-        return mState.isManualTemporaryUpperCase();
-    }
-
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void setShifted(int shiftMode) {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 2a8f9f4..292194b4 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -26,11 +26,13 @@
  * Keyboard state machine.
  *
  * This class contains all keyboard state transition logic.
+ *
  * The input events are {@link #onLoadKeyboard(String, boolean)}, {@link #onSaveKeyboardState()},
  * {@link #onPressShift(boolean)}, {@link #onReleaseShift(boolean)}, {@link #onPressSymbol()},
  * {@link #onReleaseSymbol()}, {@link #onOtherKeyPressed()}, {@link #onCodeInput(int, boolean)},
  * {@link #onCancelInput(boolean)}, {@link #onUpdateShiftState(boolean)}, {@link #onToggleShift()},
  * {@link #onToggleCapsLock()}, and {@link #onToggleAlphabetAndSymbols()}.
+ *
  * The actions are {@link SwitchActions}'s methods.
  */
 public class KeyboardState {
@@ -39,12 +41,16 @@
 
     public interface SwitchActions {
         public void setAlphabetKeyboard();
+
         public static final int UNSHIFT = 0;
         public static final int MANUAL_SHIFT = 1;
         public static final int AUTOMATIC_SHIFT = 2;
         public void setShifted(int shiftMode);
+
         public void setShiftLocked(boolean shiftLocked);
+
         public void setSymbolsKeyboard();
+
         public void setSymbolsShiftedKeyboard();
     }
 
@@ -103,8 +109,9 @@
         final SavedKeyboardState state = mSavedKeyboardState;
         state.mIsAlphabetMode = mIsAlphabetMode;
         if (mIsAlphabetMode) {
-            state.mIsShiftLocked = isShiftLocked();
-            state.mIsShifted = !state.mIsShiftLocked && isShiftedOrShiftLocked();
+            state.mIsShiftLocked = mKeyboardShiftState.isShiftLocked();
+            state.mIsShifted = !state.mIsShiftLocked
+                    && mKeyboardShiftState.isShiftedOrShiftLocked();
         } else {
             state.mIsShiftLocked = false;
             state.mIsShifted = mIsSymbolShifted;
@@ -144,34 +151,11 @@
         }
     }
 
-    public boolean isAlphabetMode() {
-        return mIsAlphabetMode;
-    }
-
+    // TODO: Remove this method.
     public boolean isShiftLocked() {
         return mKeyboardShiftState.isShiftLocked();
     }
 
-    public boolean isShiftLockShifted() {
-        return mKeyboardShiftState.isShiftLockShifted();
-    }
-
-    public boolean isShiftedOrShiftLocked() {
-        return mKeyboardShiftState.isShiftedOrShiftLocked();
-    }
-
-    public boolean isAutomaticTemporaryUpperCase() {
-        return mKeyboardShiftState.isAutomaticTemporaryUpperCase();
-    }
-
-    public boolean isManualTemporaryUpperCase() {
-        return mKeyboardShiftState.isManualTemporaryUpperCase();
-    }
-
-    public boolean isManualTemporaryUpperCaseFromAuto() {
-        return mKeyboardShiftState.isManualTemporaryUpperCaseFromAuto();
-    }
-
     private void setShifted(int shiftMode) {
         if (DEBUG_STATE) {
             Log.d(TAG, "setShifted: shiftMode=" + shiftModeToString(shiftMode));
@@ -185,7 +169,7 @@
             // state when shift key is pressed to go to normal mode.
             // On the other hand, on distinct multi touch panel device, turning off the shift
             // locked state with shift key pressing is handled by onReleaseShift().
-            if (!mHasDistinctMultitouch && !shifted && isShiftLocked()) {
+            if (!mHasDistinctMultitouch && !shifted && mKeyboardShiftState.isShiftLocked()) {
                 mKeyboardShiftState.setShiftLocked(false);
             }
             mKeyboardShiftState.setShifted(shifted);
@@ -233,7 +217,7 @@
         if (DEBUG_STATE) {
             Log.d(TAG, "setSymbolsKeyboard");
         }
-        mPrevMainKeyboardWasShiftLocked = isShiftLocked();
+        mPrevMainKeyboardWasShiftLocked = mKeyboardShiftState.isShiftLocked();
         mSwitchActions.setSymbolsKeyboard();
         mIsAlphabetMode = false;
         mIsSymbolShifted = false;
@@ -284,7 +268,7 @@
             Log.d(TAG, "onUpdateShiftState: " + this + " autoCaps=" + autoCaps);
         }
         if (mIsAlphabetMode) {
-            if (!isShiftLocked() && !mShiftKeyState.isIgnoring()) {
+            if (!mKeyboardShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
                 if (mShiftKeyState.isReleasing() && autoCaps) {
                     // Only when shift key is releasing, automatic temporary upper case will be set.
                     setShifted(SwitchActions.AUTOMATIC_SHIFT);
@@ -305,17 +289,17 @@
             Log.d(TAG, "onPressShift: " + this + " sliding=" + withSliding);
         }
         if (mIsAlphabetMode) {
-            if (isShiftLocked()) {
+            if (mKeyboardShiftState.isShiftLocked()) {
                 // Shift key is pressed while caps lock state, we will treat this state as shifted
                 // caps lock state and mark as if shift key pressed while normal state.
                 setShifted(SwitchActions.MANUAL_SHIFT);
                 mShiftKeyState.onPress();
-            } else if (isAutomaticTemporaryUpperCase()) {
+            } else if (mKeyboardShiftState.isAutomaticTemporaryUpperCase()) {
                 // Shift key is pressed while automatic temporary upper case, we have to move to
                 // manual temporary upper case.
                 setShifted(SwitchActions.MANUAL_SHIFT);
                 mShiftKeyState.onPress();
-            } else if (isShiftedOrShiftLocked()) {
+            } else if (mKeyboardShiftState.isShiftedOrShiftLocked()) {
                 // In manual upper case state, we just record shift key has been pressing while
                 // shifted state.
                 mShiftKeyState.onPressOnShifted();
@@ -337,22 +321,23 @@
             Log.d(TAG, "onReleaseShift: " + this + " sliding=" + withSliding);
         }
         if (mIsAlphabetMode) {
-            final boolean isShiftLocked = isShiftLocked();
+            final boolean isShiftLocked = mKeyboardShiftState.isShiftLocked();
             if (mShiftKeyState.isMomentary()) {
                 // After chording input while normal state.
                 setShifted(SwitchActions.UNSHIFT);
-            } else if (isShiftLocked && !isShiftLockShifted() && (mShiftKeyState.isPressing()
-                    || mShiftKeyState.isPressingOnShifted()) && !withSliding) {
+            } else if (isShiftLocked && !mKeyboardShiftState.isShiftLockShifted()
+                    && (mShiftKeyState.isPressing() || mShiftKeyState.isPressingOnShifted())
+                    && !withSliding) {
                 // Shift has been long pressed, ignore this release.
             } else if (isShiftLocked && !mShiftKeyState.isIgnoring() && !withSliding) {
                 // Shift has been pressed without chording while caps lock state.
                 setShiftLocked(false);
-            } else if (isShiftedOrShiftLocked() && mShiftKeyState.isPressingOnShifted()
-                    && !withSliding) {
+            } else if (mKeyboardShiftState.isShiftedOrShiftLocked()
+                    && mShiftKeyState.isPressingOnShifted() && !withSliding) {
                 // Shift has been pressed without chording while shifted state.
                 setShifted(SwitchActions.UNSHIFT);
-            } else if (isManualTemporaryUpperCaseFromAuto() && mShiftKeyState.isPressing()
-                    && !withSliding) {
+            } else if (mKeyboardShiftState.isManualTemporaryUpperCaseFromAuto()
+                    && mShiftKeyState.isPressing() && !withSliding) {
                 // Shift has been pressed without chording while manual temporary upper case
                 // transited from automatic temporary upper case.
                 setShifted(SwitchActions.UNSHIFT);
@@ -468,7 +453,7 @@
             Log.d(TAG, "onToggleShift: " + this);
         }
         if (mIsAlphabetMode) {
-            setShifted(isShiftedOrShiftLocked()
+            setShifted(mKeyboardShiftState.isShiftedOrShiftLocked()
                     ? SwitchActions.UNSHIFT : SwitchActions.MANUAL_SHIFT);
         } else {
             toggleShiftInSymbols();
@@ -480,7 +465,7 @@
             Log.d(TAG, "onToggleCapsLock: " + this);
         }
         if (mIsAlphabetMode) {
-            if (isShiftLocked()) {
+            if (mKeyboardShiftState.isShiftLocked()) {
                 setShiftLocked(false);
                 // Shift key is long pressed while caps lock state, we will toggle back to normal
                 // state. And mark as if shift key is released.
@@ -506,6 +491,7 @@
         default: return null;
         }
     }
+
     private static String switchStateToString(int switchState) {
         switch (switchState) {
         case SWITCH_STATE_ALPHA: return "ALPHA";
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index de273b5..5d075b1 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -78,7 +78,6 @@
 public class LatinIME extends InputMethodServiceCompatWrapper implements KeyboardActionListener,
         SuggestionsView.Listener {
     private static final String TAG = LatinIME.class.getSimpleName();
-    private static final boolean PERF_DEBUG = false;
     private static final boolean TRACE = false;
     private static boolean DEBUG;
 
@@ -144,6 +143,7 @@
      */
     private static final String SCHEME_PACKAGE = "package";
 
+    // TODO: migrate this to SettingsValues
     private int mSuggestionVisibility;
     private static final int SUGGESTION_VISIBILILTY_SHOW_VALUE
             = R.string.prefs_suggestion_visibility_show_value;
@@ -1576,7 +1576,6 @@
         }
 
         switcher.updateShiftState();
-        if (LatinIME.PERF_DEBUG) measureCps();
         TextEntryState.typedCharacter((char) code, mSettingsValues.isWordSeparator(code), x, y);
         if (null != ic) ic.endBatchEdit();
     }
@@ -2389,9 +2388,7 @@
     }
 
     private void updateSuggestionVisibility(final SharedPreferences prefs, final Resources res) {
-        final String suggestionVisiblityStr = prefs.getString(
-                Settings.PREF_SHOW_SUGGESTIONS_SETTING,
-                res.getString(R.string.prefs_suggestion_visibility_default_value));
+        final String suggestionVisiblityStr = mSettingsValues.mShowSuggestionsSetting;
         for (int visibility : SUGGESTION_VISIBILITY_VALUE_ARRAY) {
             if (suggestionVisiblityStr.equals(res.getString(visibility))) {
                 mSuggestionVisibility = visibility;
@@ -2479,7 +2476,9 @@
 
         final Printer p = new PrintWriterPrinter(fout);
         p.println("LatinIME state :");
-        p.println("  Keyboard mode = " + mKeyboardSwitcher.getKeyboardMode());
+        final Keyboard keyboard = mKeyboardSwitcher.getLatinKeyboard();
+        final int keyboardMode = keyboard != null ? keyboard.mId.mMode : -1;
+        p.println("  Keyboard mode = " + keyboardMode);
         p.println("  mComposingStringBuilder=" + mComposingStringBuilder.toString());
         p.println("  mIsSuggestionsRequested=" + mIsSettingsSuggestionStripOn);
         p.println("  mCorrectionMode=" + mCorrectionMode);
@@ -2492,22 +2491,4 @@
         p.println("  mVibrateOn=" + mSettingsValues.mVibrateOn);
         p.println("  mKeyPreviewPopupOn=" + mSettingsValues.mKeyPreviewPopupOn);
     }
-
-    // Characters per second measurement
-
-    private long mLastCpsTime;
-    private static final int CPS_BUFFER_SIZE = 16;
-    private long[] mCpsIntervals = new long[CPS_BUFFER_SIZE];
-    private int mCpsIndex;
-
-    private void measureCps() {
-        long now = System.currentTimeMillis();
-        if (mLastCpsTime == 0) mLastCpsTime = now - 100; // Initial
-        mCpsIntervals[mCpsIndex] = now - mLastCpsTime;
-        mLastCpsTime = now;
-        mCpsIndex = (mCpsIndex + 1) % CPS_BUFFER_SIZE;
-        long total = 0;
-        for (int i = 0; i < CPS_BUFFER_SIZE; i++) total += mCpsIntervals[i];
-        System.out.println("CPS = " + ((CPS_BUFFER_SIZE * 1000f) / total));
-    }
 }
diff --git a/java/src/com/android/inputmethod/latin/Settings.java b/java/src/com/android/inputmethod/latin/Settings.java
index 4166e62..ac4f705 100644
--- a/java/src/com/android/inputmethod/latin/Settings.java
+++ b/java/src/com/android/inputmethod/latin/Settings.java
@@ -58,42 +58,37 @@
 
     public static final boolean ENABLE_EXPERIMENTAL_SETTINGS = false;
 
-    public static final String PREF_GENERAL_SETTINGS_KEY = "general_settings";
+    // In the same order as xml/prefs.xml
+    public static final String PREF_GENERAL_SETTINGS = "general_settings";
+    public static final String PREF_SUBTYPES_SETTINGS = "subtype_settings";
+    public static final String PREF_AUTO_CAP = "auto_cap";
     public static final String PREF_VIBRATE_ON = "vibrate_on";
     public static final String PREF_SOUND_ON = "sound_on";
-    public static final String PREF_KEY_PREVIEW_POPUP_ON = "popup_on";
-    public static final String PREF_AUTO_CAP = "auto_cap";
+    public static final String PREF_POPUP_ON = "popup_on";
     public static final String PREF_SHOW_SETTINGS_KEY = "show_settings_key";
-    public static final String PREF_VOICE_SETTINGS_KEY = "voice_mode";
-    public static final String PREF_INPUT_LANGUAGE = "input_language";
-    public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
-    public static final String PREF_SUBTYPES = "subtype_settings";
-
+    public static final String PREF_VOICE_MODE = "voice_mode";
+    public static final String PREF_CORRECTION_SETTINGS = "correction_settings";
     public static final String PREF_CONFIGURE_DICTIONARIES_KEY = "configure_dictionaries_key";
-    public static final String PREF_CORRECTION_SETTINGS_KEY = "correction_settings";
-    public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
     public static final String PREF_AUTO_CORRECTION_THRESHOLD = "auto_correction_threshold";
-    public static final String PREF_DEBUG_SETTINGS = "debug_settings";
-
-    public static final String PREF_BIGRAM_SUGGESTIONS = "bigram_suggestion";
-    public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction";
-
-    public static final String PREF_MISC_SETTINGS_KEY = "misc_settings";
-
+    public static final String PREF_SHOW_SUGGESTIONS_SETTING = "show_suggestions_setting";
+    public static final String PREF_MISC_SETTINGS = "misc_settings";
+    public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
+    public static final String PREF_ADVANCED_SETTINGS = "pref_advanced_settings";
     public static final String PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY =
             "pref_key_preview_popup_dismiss_delay";
-    public static final String PREF_KEY_USE_CONTACTS_DICT =
-            "pref_key_use_contacts_dict";
-    public static final String PREF_KEY_ENABLE_SPAN_INSERT =
-            "enable_span_insert";
-
-    public static final String PREF_USABILITY_STUDY_MODE = "usability_study_mode";
-
-    public static final String PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS =
+    public static final String PREF_KEY_USE_CONTACTS_DICT = "pref_key_use_contacts_dict";
+    public static final String PREF_BIGRAM_SUGGESTION = "bigram_suggestion";
+    public static final String PREF_BIGRAM_PREDICTIONS = "bigram_prediction";
+    public static final String PREF_KEY_ENABLE_SPAN_INSERT = "enable_span_insert";
+    public static final String PREF_VIBRATION_DURATION_SETTINGS =
             "pref_vibration_duration_settings";
-
     public static final String PREF_KEYPRESS_SOUND_VOLUME =
             "pref_keypress_sound_volume";
+
+    public static final String PREF_INPUT_LANGUAGE = "input_language";
+    public static final String PREF_SELECTED_LANGUAGES = "selected_languages";
+    public static final String PREF_DEBUG_SETTINGS = "debug_settings";
+
     // Dialog ids
     private static final int VOICE_INPUT_CONFIRM_DIALOG = 0;
 
@@ -149,9 +144,9 @@
         final Context context = getActivityInternal();
 
         addPreferencesFromResource(R.xml.prefs);
-        mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES);
+        mInputLanguageSelection = (PreferenceScreen) findPreference(PREF_SUBTYPES_SETTINGS);
         mInputLanguageSelection.setOnPreferenceClickListener(this);
-        mVoicePreference = (ListPreference) findPreference(PREF_VOICE_SETTINGS_KEY);
+        mVoicePreference = (ListPreference) findPreference(PREF_VOICE_MODE);
         mShowSettingsKeyPreference = (CheckBoxPreference) findPreference(PREF_SHOW_SETTINGS_KEY);
         mShowCorrectionSuggestionsPreference =
                 (ListPreference) findPreference(PREF_SHOW_SUGGESTIONS_SETTING);
@@ -159,12 +154,12 @@
         prefs.registerOnSharedPreferenceChangeListener(this);
 
         mVoiceModeOff = getString(R.string.voice_mode_off);
-        mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
+        mVoiceOn = !(prefs.getString(PREF_VOICE_MODE, mVoiceModeOff)
                 .equals(mVoiceModeOff));
 
         mAutoCorrectionThresholdPreference =
                 (ListPreference) findPreference(PREF_AUTO_CORRECTION_THRESHOLD);
-        mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTIONS);
+        mBigramSuggestion = (CheckBoxPreference) findPreference(PREF_BIGRAM_SUGGESTION);
         mBigramPrediction = (CheckBoxPreference) findPreference(PREF_BIGRAM_PREDICTIONS);
         mDebugSettingsPreference = findPreference(PREF_DEBUG_SETTINGS);
         if (mDebugSettingsPreference != null) {
@@ -177,13 +172,13 @@
         ensureConsistencyOfAutoCorrectionSettings();
 
         final PreferenceGroup generalSettings =
-                (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS_KEY);
+                (PreferenceGroup) findPreference(PREF_GENERAL_SETTINGS);
         final PreferenceGroup textCorrectionGroup =
-                (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS_KEY);
+                (PreferenceGroup) findPreference(PREF_CORRECTION_SETTINGS);
         final PreferenceGroup miscSettings =
-                (PreferenceGroup) findPreference(PREF_MISC_SETTINGS_KEY);
+                (PreferenceGroup) findPreference(PREF_MISC_SETTINGS);
 
-        if (!SettingsValues.isShowSettingsKeyOption(res)) {
+        if (!SettingsValues.isShowSettingsKeyOptionEnabled(res)) {
             generalSettings.removePreference(mShowSettingsKeyPreference);
         }
 
@@ -198,13 +193,13 @@
         }
 
         if (InputMethodServiceCompatWrapper.CAN_HANDLE_ON_CURRENT_INPUT_METHOD_SUBTYPE_CHANGED) {
-            generalSettings.removePreference(findPreference(PREF_SUBTYPES));
+            generalSettings.removePreference(findPreference(PREF_SUBTYPES_SETTINGS));
         }
 
         final boolean showPopupOption = res.getBoolean(
                 R.bool.config_enable_show_popup_on_keypress_option);
         if (!showPopupOption) {
-            generalSettings.removePreference(findPreference(PREF_KEY_PREVIEW_POPUP_ON));
+            generalSettings.removePreference(findPreference(PREF_POPUP_ON));
         }
 
         final boolean showBigramSuggestionsOption = res.getBoolean(
@@ -261,7 +256,7 @@
         }
 
         mKeypressVibrationDurationSettingsPref =
-                (PreferenceScreen) findPreference(PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS);
+                (PreferenceScreen) findPreference(PREF_VIBRATION_DURATION_SETTINGS);
         if (mKeypressVibrationDurationSettingsPref != null) {
             mKeypressVibrationDurationSettingsPref.setOnPreferenceClickListener(
                     new OnPreferenceClickListener() {
@@ -317,20 +312,20 @@
     public void onSharedPreferenceChanged(SharedPreferences prefs, String key) {
         (new BackupManager(getActivityInternal())).dataChanged();
         // If turning on voice input, show dialog
-        if (key.equals(PREF_VOICE_SETTINGS_KEY) && !mVoiceOn) {
-            if (!prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
+        if (key.equals(PREF_VOICE_MODE) && !mVoiceOn) {
+            if (!prefs.getString(PREF_VOICE_MODE, mVoiceModeOff)
                     .equals(mVoiceModeOff)) {
                 showVoiceConfirmation();
             }
-        } else if (key.equals(PREF_KEY_PREVIEW_POPUP_ON)) {
+        } else if (key.equals(PREF_POPUP_ON)) {
             final ListPreference popupDismissDelay =
                 (ListPreference)findPreference(PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY);
             if (null != popupDismissDelay) {
-                popupDismissDelay.setEnabled(prefs.getBoolean(PREF_KEY_PREVIEW_POPUP_ON, true));
+                popupDismissDelay.setEnabled(prefs.getBoolean(PREF_POPUP_ON, true));
             }
         }
         ensureConsistencyOfAutoCorrectionSettings();
-        mVoiceOn = !(prefs.getString(PREF_VOICE_SETTINGS_KEY, mVoiceModeOff)
+        mVoiceOn = !(prefs.getString(PREF_VOICE_MODE, mVoiceModeOff)
                 .equals(mVoiceModeOff));
         updateVoiceModeSummary();
         updateShowCorrectionSuggestionsSummary();
@@ -472,7 +467,7 @@
             public void onClick(DialogInterface dialog, int whichButton) {
                 final int ms = Integer.valueOf(
                         mKeypressVibrationDurationSettingsTextView.getText().toString());
-                sp.edit().putInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, ms).apply();
+                sp.edit().putInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, ms).apply();
                 updateKeypressVibrationDurationSettingsSummary(sp, res);
             }
         });
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index 62cf4a3..a3fe15d 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -34,36 +34,42 @@
 
     // From resources:
     public final int mDelayUpdateOldSuggestions;
-    public final String mWordSeparators;
     public final String mMagicSpaceStrippers;
     public final String mMagicSpaceSwappers;
     public final String mSuggestPuncs;
     public final SuggestedWords mSuggestPuncList;
     private final String mSymbolsExcludedFromWordSeparators;
+    public final String mWordSeparators;
     public final CharSequence mHintToSaveText;
 
-    // From preferences:
-    public final boolean mSoundOn; // Sound setting private to Latin IME (see mSilentModeOn)
-    public final boolean mVibrateOn;
-    public final boolean mKeyPreviewPopupOn;
-    public final int mKeyPreviewPopupDismissDelay;
+    // From preferences, in the same order as xml/prefs.xml:
     public final boolean mAutoCap;
-    public final boolean mAutoCorrectEnabled;
-    public final double mAutoCorrectionThreshold;
+    public final boolean mVibrateOn;
+    public final boolean mSoundOn;
+    public final boolean mKeyPreviewPopupOn;
+    private final boolean mShowSettingsKey;
+    private final String mVoiceMode;
+    private final String mAutoCorrectionThresholdRawValue;
+    public final String mShowSuggestionsSetting;
+    private final boolean mUsabilityStudyMode;
+    private final String mKeyPreviewPopupDismissDelayRawValue;
+    public final boolean mUseContactsDict;
     // Suggestion: use bigrams to adjust scores of suggestions obtained from unigram dictionary
     public final boolean mBigramSuggestionEnabled;
     // Prediction: use bigrams to predict the next word when there is no input for it yet
     public final boolean mBigramPredictionEnabled;
-    public final boolean mUseContactsDict;
     public final boolean mEnableSuggestionSpanInsertion;
-
-    private final boolean mShowSettingsKey;
-    private final boolean mVoiceKeyEnabled;
-    private final boolean mVoiceKeyOnMain;
+    private final int mVibrationDurationSettingsRawValue;
+    private final float mKeypressSoundVolumeRawValue;
 
     // Deduced settings
     public final int mKeypressVibrationDuration;
     public final float mFxVolume;
+    public final int mKeyPreviewPopupDismissDelay;
+    public final boolean mAutoCorrectEnabled;
+    public final double mAutoCorrectionThreshold;
+    private final boolean mVoiceKeyEnabled;
+    private final boolean mVoiceKeyOnMain;
 
     public SettingsValues(final SharedPreferences prefs, final Context context,
             final String localeStr) {
@@ -77,60 +83,103 @@
         }
 
         // Get the resources
-        mDelayUpdateOldSuggestions = res.getInteger(
-                R.integer.config_delay_update_old_suggestions);
+        mDelayUpdateOldSuggestions = res.getInteger(R.integer.config_delay_update_old_suggestions);
         mMagicSpaceStrippers = res.getString(R.string.magic_space_stripping_symbols);
         mMagicSpaceSwappers = res.getString(R.string.magic_space_swapping_symbols);
-        String wordSeparators = mMagicSpaceStrippers + mMagicSpaceSwappers
-                + res.getString(R.string.magic_space_promoting_symbols);
-        final String symbolsExcludedFromWordSeparators =
-                res.getString(R.string.symbols_excluded_from_word_separators);
-        for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
-            wordSeparators = wordSeparators.replace(
-                    symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
-        }
-        mSymbolsExcludedFromWordSeparators = symbolsExcludedFromWordSeparators;
-        mWordSeparators = wordSeparators;
         mSuggestPuncs = res.getString(R.string.suggested_punctuations);
         // TODO: it would be nice not to recreate this each time we change the configuration
         mSuggestPuncList = createSuggestPuncList(mSuggestPuncs);
+        mSymbolsExcludedFromWordSeparators =
+                res.getString(R.string.symbols_excluded_from_word_separators);
+        mWordSeparators = createWordSeparators(mMagicSpaceStrippers, mMagicSpaceSwappers,
+                mSymbolsExcludedFromWordSeparators, res);
         mHintToSaveText = context.getText(R.string.hint_add_to_dictionary);
 
         // Get the settings preferences
-        final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator();
-        mVibrateOn = hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
-                res.getBoolean(R.bool.config_default_vibration_enabled));
+        mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
+        mVibrateOn = isVibrateOn(context, prefs, res);
         mSoundOn = prefs.getBoolean(Settings.PREF_SOUND_ON,
                 res.getBoolean(R.bool.config_default_sound_enabled));
         mKeyPreviewPopupOn = isKeyPreviewPopupEnabled(prefs, res);
-        mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res);
-        mAutoCap = prefs.getBoolean(Settings.PREF_AUTO_CAP, true);
-        mAutoCorrectEnabled = isAutoCorrectEnabled(prefs, res);
+        mShowSettingsKey = isSettingsKeyShown(prefs, res);
+        final String voiceModeMain = res.getString(R.string.voice_mode_main);
+        final String voiceModeOff = res.getString(R.string.voice_mode_off);
+        mVoiceMode = prefs.getString(Settings.PREF_VOICE_MODE, voiceModeMain);
+        mAutoCorrectionThresholdRawValue = prefs.getString(Settings.PREF_AUTO_CORRECTION_THRESHOLD,
+                res.getString(R.string.auto_correction_threshold_mode_index_modest));
+        mShowSuggestionsSetting = prefs.getString(Settings.PREF_SHOW_SUGGESTIONS_SETTING,
+                res.getString(R.string.prefs_suggestion_visibility_default_value));
+        mUsabilityStudyMode = getUsabilityStudyMode(prefs, res);
+        mKeyPreviewPopupDismissDelayRawValue = prefs.getString(
+                Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
+                Integer.toString(res.getInteger(R.integer.config_delay_after_preview)));
+        mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
+        mAutoCorrectEnabled = isAutoCorrectEnabled(prefs, res, mAutoCorrectionThresholdRawValue);
         mBigramSuggestionEnabled = mAutoCorrectEnabled
                 && isBigramSuggestionEnabled(prefs, res, mAutoCorrectEnabled);
         mBigramPredictionEnabled = mBigramSuggestionEnabled
                 && isBigramPredictionEnabled(prefs, res);
-        mAutoCorrectionThreshold = getAutoCorrectionThreshold(prefs, res);
-        mUseContactsDict = prefs.getBoolean(Settings.PREF_KEY_USE_CONTACTS_DICT, true);
         mEnableSuggestionSpanInsertion =
                 prefs.getBoolean(Settings.PREF_KEY_ENABLE_SPAN_INSERT, true);
-        final boolean defaultShowSettingsKey = res.getBoolean(
-                R.bool.config_default_show_settings_key);
-        mShowSettingsKey = isShowSettingsKeyOption(res)
-                ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey)
-                : defaultShowSettingsKey;
-        final String voiceModeMain = res.getString(R.string.voice_mode_main);
-        final String voiceModeOff = res.getString(R.string.voice_mode_off);
-        final String voiceMode = prefs.getString(Settings.PREF_VOICE_SETTINGS_KEY, voiceModeMain);
-        mVoiceKeyEnabled = voiceMode != null && !voiceMode.equals(voiceModeOff);
-        mVoiceKeyOnMain = voiceMode != null && voiceMode.equals(voiceModeMain);
+        mVibrationDurationSettingsRawValue =
+                prefs.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
+        mKeypressSoundVolumeRawValue = prefs.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
 
-        mFxVolume = getCurrentKeypressSoundVolume(prefs, res);
+        // Compute other readable settings
         mKeypressVibrationDuration = getCurrentVibrationDuration(prefs, res);
+        mFxVolume = getCurrentKeypressSoundVolume(prefs, res);
+        mKeyPreviewPopupDismissDelay = getKeyPreviewPopupDismissDelay(prefs, res);
+        mAutoCorrectionThreshold = getAutoCorrectionThreshold(prefs, res,
+                mAutoCorrectionThresholdRawValue);
+        mVoiceKeyEnabled = mVoiceMode != null && !mVoiceMode.equals(voiceModeOff);
+        mVoiceKeyOnMain = mVoiceMode != null && mVoiceMode.equals(voiceModeMain);
 
         LocaleUtils.setSystemLocale(res, savedLocale);
     }
 
+    // Helper functions to create member values.
+    private static SuggestedWords createSuggestPuncList(final String puncs) {
+        SuggestedWords.Builder builder = new SuggestedWords.Builder();
+        if (puncs != null) {
+            for (int i = 0; i < puncs.length(); i++) {
+                builder.addWord(puncs.subSequence(i, i + 1));
+            }
+        }
+        return builder.setIsPunctuationSuggestions().build();
+    }
+
+    private static String createWordSeparators(final String magicSpaceStrippers,
+            final String magicSpaceSwappers, final String symbolsExcludedFromWordSeparators,
+            final Resources res) {
+        String wordSeparators = magicSpaceStrippers + magicSpaceSwappers
+                + res.getString(R.string.magic_space_promoting_symbols);
+        for (int i = symbolsExcludedFromWordSeparators.length() - 1; i >= 0; --i) {
+            wordSeparators = wordSeparators.replace(
+                    symbolsExcludedFromWordSeparators.substring(i, i + 1), "");
+        }
+        return wordSeparators;
+    }
+
+    private static boolean isSettingsKeyShown(final SharedPreferences prefs, final Resources res) {
+        final boolean defaultShowSettingsKey = res.getBoolean(
+                R.bool.config_default_show_settings_key);
+        return isShowSettingsKeyOptionEnabled(res)
+                ? prefs.getBoolean(Settings.PREF_SHOW_SETTINGS_KEY, defaultShowSettingsKey)
+                : defaultShowSettingsKey;
+    }
+
+    public static boolean isShowSettingsKeyOptionEnabled(final Resources resources) {
+        // TODO: Read this once and for all into a public final member
+        return resources.getBoolean(R.bool.config_enable_show_settings_key_option);
+    }
+
+    private static boolean isVibrateOn(final Context context, final SharedPreferences prefs,
+            final Resources res) {
+        final boolean hasVibrator = VibratorCompatWrapper.getInstance(context).hasVibrator();
+        return hasVibrator && prefs.getBoolean(Settings.PREF_VIBRATE_ON,
+                res.getBoolean(R.bool.config_default_vibration_enabled));
+    }
+
     public boolean isSuggestedPunctuation(int code) {
         return mSuggestPuncs.contains(String.valueOf((char)code));
     }
@@ -151,10 +200,8 @@
         return mMagicSpaceSwappers.contains(String.valueOf((char)code));
     }
 
-    private static boolean isAutoCorrectEnabled(SharedPreferences sp, Resources resources) {
-        final String currentAutoCorrectionSetting = sp.getString(
-                Settings.PREF_AUTO_CORRECTION_THRESHOLD,
-                resources.getString(R.string.auto_correction_threshold_mode_index_modest));
+    private static boolean isAutoCorrectEnabled(final SharedPreferences sp,
+            final Resources resources, final String currentAutoCorrectionSetting) {
         final String autoCorrectionOff = resources.getString(
                 R.string.auto_correction_threshold_mode_index_off);
         return !currentAutoCorrectionSetting.equals(autoCorrectionOff);
@@ -166,39 +213,37 @@
         final boolean showPopupOption = resources.getBoolean(
                 R.bool.config_enable_show_popup_on_keypress_option);
         if (!showPopupOption) return resources.getBoolean(R.bool.config_default_popup_preview);
-        return sp.getBoolean(Settings.PREF_KEY_PREVIEW_POPUP_ON,
+        return sp.getBoolean(Settings.PREF_POPUP_ON,
                 resources.getBoolean(R.bool.config_default_popup_preview));
     }
 
     // Likewise
     public static int getKeyPreviewPopupDismissDelay(SharedPreferences sp,
             Resources resources) {
+        // TODO: use mKeyPreviewPopupDismissDelayRawValue instead of reading it again here.
         return Integer.parseInt(sp.getString(Settings.PREF_KEY_PREVIEW_POPUP_DISMISS_DELAY,
                 Integer.toString(resources.getInteger(R.integer.config_delay_after_preview))));
     }
 
-    private static boolean isBigramSuggestionEnabled(SharedPreferences sp, Resources resources,
-            boolean autoCorrectEnabled) {
+    private static boolean isBigramSuggestionEnabled(final SharedPreferences sp,
+            final Resources resources, final boolean autoCorrectEnabled) {
         final boolean showBigramSuggestionsOption = resources.getBoolean(
                 R.bool.config_enable_bigram_suggestions_option);
         if (!showBigramSuggestionsOption) {
             return autoCorrectEnabled;
         }
-        return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTIONS, resources.getBoolean(
+        return sp.getBoolean(Settings.PREF_BIGRAM_SUGGESTION, resources.getBoolean(
                 R.bool.config_default_bigram_suggestions));
     }
 
-    private static boolean isBigramPredictionEnabled(SharedPreferences sp,
-            Resources resources) {
+    private static boolean isBigramPredictionEnabled(final SharedPreferences sp,
+            final Resources resources) {
         return sp.getBoolean(Settings.PREF_BIGRAM_PREDICTIONS, resources.getBoolean(
                 R.bool.config_default_bigram_prediction));
     }
 
-    private static double getAutoCorrectionThreshold(SharedPreferences sp,
-            Resources resources) {
-        final String currentAutoCorrectionSetting = sp.getString(
-                Settings.PREF_AUTO_CORRECTION_THRESHOLD,
-                resources.getString(R.string.auto_correction_threshold_mode_index_modest));
+    private static double getAutoCorrectionThreshold(final SharedPreferences sp,
+            final Resources resources, final String currentAutoCorrectionSetting) {
         final String[] autoCorrectionThresholdValues = resources.getStringArray(
                 R.array.auto_correction_threshold_values);
         // When autoCorrectionThreshold is greater than 1.0, it's like auto correction is off.
@@ -220,26 +265,11 @@
         return autoCorrectionThreshold;
     }
 
-    private static SuggestedWords createSuggestPuncList(final String puncs) {
-        SuggestedWords.Builder builder = new SuggestedWords.Builder();
-        if (puncs != null) {
-            for (int i = 0; i < puncs.length(); i++) {
-                builder.addWord(puncs.subSequence(i, i + 1));
-            }
-        }
-        return builder.setIsPunctuationSuggestions().build();
-    }
-
-    public static boolean isShowSettingsKeyOption(final Resources resources) {
-        return resources.getBoolean(R.bool.config_enable_show_settings_key_option);
-
-    }
-
     public boolean isSettingsKeyEnabled() {
         return mShowSettingsKey;
     }
 
-    public boolean isVoiceKeyEnabled(EditorInfo editorInfo) {
+    public boolean isVoiceKeyEnabled(final EditorInfo editorInfo) {
         final boolean shortcutImeEnabled = SubtypeSwitcher.getInstance().isShortcutImeEnabled();
         final int inputType = (editorInfo != null) ? editorInfo.inputType : 0;
         return shortcutImeEnabled && mVoiceKeyEnabled
@@ -253,6 +283,7 @@
     // Accessed from the settings interface, hence public
     public static float getCurrentKeypressSoundVolume(final SharedPreferences sp,
                 final Resources res) {
+        // TODO: use mVibrationDurationSettingsRawValue instead of reading it again here
         final float volume = sp.getFloat(Settings.PREF_KEYPRESS_SOUND_VOLUME, -1.0f);
         if (volume >= 0) {
             return volume;
@@ -271,7 +302,8 @@
     // Likewise
     public static int getCurrentVibrationDuration(final SharedPreferences sp,
                 final Resources res) {
-        final int ms = sp.getInt(Settings.PREF_KEYPRESS_VIBRATION_DURATION_SETTINGS, -1);
+        // TODO: use mKeypressVibrationDuration instead of reading it again here
+        final int ms = sp.getInt(Settings.PREF_VIBRATION_DURATION_SETTINGS, -1);
         if (ms >= 0) {
             return ms;
         }
@@ -285,4 +317,11 @@
         }
         return -1;
     }
+
+    // Likewise
+    public static boolean getUsabilityStudyMode(final SharedPreferences prefs,
+            final Resources res) {
+        // TODO: use mUsabilityStudyMode instead of reading it again here
+        return prefs.getBoolean(Settings.PREF_USABILITY_STUDY_MODE, true);
+    }
 }