diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index 2d80a798dfd59327c1916e1b2ff279e180fca8e1..e3661a9f8d669f5ac87a5c5ae33b98913b4d1a51 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -20,6 +20,7 @@ import android.text.TextUtils;
 import android.util.Log;
 
 import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.latin.Constants;
 import com.android.inputmethod.latin.ResearchLogger;
 import com.android.inputmethod.latin.define.ProductionFlag;
 
@@ -30,8 +31,8 @@ import com.android.inputmethod.latin.define.ProductionFlag;
  *
  * The input events are {@link #onLoadKeyboard(String)}, {@link #onSaveKeyboardState()},
  * {@link #onPressKey(int)}, {@link #onReleaseKey(int, boolean)},
- * {@link #onCodeInput(int, boolean, boolean)}, {@link #onCancelInput(boolean)},
- * {@link #onUpdateShiftState(boolean)}, {@link #onLongPressTimeout(int)}.
+ * {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)},
+ * {@link #onUpdateShiftState(int)}, {@link #onLongPressTimeout(int)}.
  *
  * The actions are {@link SwitchActions}'s methods.
  */
@@ -50,7 +51,7 @@ public class KeyboardState {
         public void setSymbolsShiftedKeyboard();
 
         /**
-         * Request to call back {@link KeyboardState#onUpdateShiftState(boolean)}.
+         * Request to call back {@link KeyboardState#onUpdateShiftState(int)}.
          */
         public void requestUpdatingShiftState();
 
@@ -371,14 +372,14 @@ public class KeyboardState {
         }
     }
 
-    public void onUpdateShiftState(boolean autoCaps) {
+    public void onUpdateShiftState(int autoCaps) {
         if (DEBUG_EVENT) {
             Log.d(TAG, "onUpdateShiftState: autoCaps=" + autoCaps + " " + this);
         }
         updateAlphabetShiftState(autoCaps);
     }
 
-    private void updateAlphabetShiftState(boolean autoCaps) {
+    private void updateAlphabetShiftState(int autoCaps) {
         if (!mIsAlphabetMode) return;
         if (!mShiftKeyState.isReleasing()) {
             // Ignore update shift state event while the shift key is being pressed (including
@@ -386,7 +387,7 @@ public class KeyboardState {
             return;
         }
         if (!mAlphabetShiftState.isShiftLocked() && !mShiftKeyState.isIgnoring()) {
-            if (mShiftKeyState.isReleasing() && autoCaps) {
+            if (mShiftKeyState.isReleasing() && autoCaps != Constants.TextUtils.CAP_MODE_OFF) {
                 // Only when shift key is releasing, automatic temporary upper case will be set.
                 setShifted(AUTOMATIC_SHIFT);
             } else {
@@ -521,7 +522,7 @@ public class KeyboardState {
         return false;
     }
 
-    public void onCodeInput(int code, boolean isSinglePointer, boolean autoCaps) {
+    public void onCodeInput(int code, boolean isSinglePointer, int autoCaps) {
         if (DEBUG_EVENT) {
             Log.d(TAG, "onCodeInput: code=" + Keyboard.printableCode(code)
                     + " single=" + isSinglePointer
diff --git a/java/src/com/android/inputmethod/latin/Constants.java b/java/src/com/android/inputmethod/latin/Constants.java
index 7c2284569e9baff37e18db80bf2ab9d76b867bc4..e79db367c3f193cb4a6c04f33cbccc879435329e 100644
--- a/java/src/com/android/inputmethod/latin/Constants.java
+++ b/java/src/com/android/inputmethod/latin/Constants.java
@@ -106,6 +106,21 @@ public final class Constants {
         }
     }
 
+    public static class TextUtils {
+        /**
+         * Capitalization mode for {@link android.text.TextUtils#getCapsMode}: don't capitalize
+         * characters.  This value may be used with
+         * {@link android.text.TextUtils#CAP_MODE_CHARACTERS},
+         * {@link android.text.TextUtils#CAP_MODE_WORDS}, and
+         * {@link android.text.TextUtils#CAP_MODE_SENTENCES}.
+         */
+        public static final int CAP_MODE_OFF = 0;
+
+        private TextUtils() {
+            // This utility class is not publicly instantiable.
+        }
+    }
+
     private Constants() {
         // This utility class is not publicly instantiable.
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index bdefaee92df045020bdc477ccb055e912d3a8ba2..b632d34bf23d1957075e276eb7758d55e01a6d02 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1032,26 +1032,28 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         updateSuggestions();
     }
 
-    public boolean getCurrentAutoCapsState() {
-        if (!mSettingsValues.mAutoCap) return false;
+    public int getCurrentAutoCapsState() {
+        if (!mSettingsValues.mAutoCap) return Constants.TextUtils.CAP_MODE_OFF;
 
         final EditorInfo ei = getCurrentInputEditorInfo();
-        if (ei == null) return false;
+        if (ei == null) return Constants.TextUtils.CAP_MODE_OFF;
 
         final int inputType = ei.inputType;
-        if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) return true;
+        if ((inputType & InputType.TYPE_TEXT_FLAG_CAP_CHARACTERS) != 0) {
+            return TextUtils.CAP_MODE_CHARACTERS;
+        }
 
         final boolean noNeedToCheckCapsMode = (inputType & (InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
                 | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0;
-        if (noNeedToCheckCapsMode) return false;
+        if (noNeedToCheckCapsMode) return Constants.TextUtils.CAP_MODE_OFF;
 
         final InputConnection ic = getCurrentInputConnection();
-        if (ic == null) return false;
+        if (ic == null) return Constants.TextUtils.CAP_MODE_OFF;
         // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls.
         // Note: getCursorCapsMode() returns the current capitalization mode that is any
         // combination of CAP_MODE_CHARACTERS, CAP_MODE_WORDS, and CAP_MODE_SENTENCES. 0 means none
         // of them.
-        return ic.getCursorCapsMode(inputType) != 0;
+        return ic.getCursorCapsMode(inputType);
     }
 
     // "ic" may be null
@@ -1522,7 +1524,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             if (ic != null) {
                 // If it's the first letter, make note of auto-caps state
                 if (mWordComposer.size() == 1) {
-                    mWordComposer.setAutoCapitalized(getCurrentAutoCapsState());
+                    mWordComposer.setAutoCapitalized(
+                            getCurrentAutoCapsState() != Constants.TextUtils.CAP_MODE_OFF);
                 }
                 ic.setComposingText(getTextWithUnderline(mWordComposer.getTypedWord()), 1);
             }
diff --git a/java/src/com/android/inputmethod/latin/ResearchLogger.java b/java/src/com/android/inputmethod/latin/ResearchLogger.java
index 566af7061fb1133c8d34ca2aa68c1c6d279a68a3..aa979a66f3b05d70352308ab83b3cf91f07095b2 100644
--- a/java/src/com/android/inputmethod/latin/ResearchLogger.java
+++ b/java/src/com/android/inputmethod/latin/ResearchLogger.java
@@ -444,7 +444,7 @@ public class ResearchLogger implements SharedPreferences.OnSharedPreferenceChang
     }
 
     public static void keyboardState_onCodeInput(
-            final int code, final boolean isSinglePointer, final boolean autoCaps,
+            final int code, final boolean isSinglePointer, final int autoCaps,
             final KeyboardState keyboardState) {
         if (UnsLogGroup.KEYBOARDSTATE_ONCODEINPUT_ENABLED) {
             final String s = "onCodeInput: code=" + Keyboard.printableCode(code)
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
index 0e6caaf8772ebf569060989a18f60535a829a4f5..c2408c9c5b37a00f4a6857fea674d2ba7842a00a 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
@@ -206,8 +206,8 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
 
     // Chording input in automatic upper case.
     public void testChordingAutomaticUpperCase() {
-        // Set auto caps mode on.
-        setAutoCapsMode(AUTO_CAPS);
+        // Set capitalize the first character of all words mode.
+        setAutoCapsMode(CAP_MODE_WORDS);
 
         // Update shift state with auto caps enabled.
         pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED);
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
index de2a50fcf5776ae3762c1813a3021889ea76529e..b9f53184ad28a3e3f58c65ceb06ff2aa9c13434c 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateSingleTouchTests.java
@@ -202,8 +202,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
 
     // Automatic upper case test
     public void testAutomaticUpperCase() {
-        // Set auto caps mode on.
-        setAutoCapsMode(AUTO_CAPS);
+        // Set capitalize the first character of all words mode.
+        setAutoCapsMode(CAP_MODE_WORDS);
         // Load keyboard, should be in automatic shifted.
         loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
 
@@ -239,7 +239,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
     // Long press shift key.
     public void testLongPressShift() {
         // Set auto caps mode off.
-        setAutoCapsMode(NO_AUTO_CAPS);
+        setAutoCapsMode(CAP_MODE_OFF);
         // Load keyboard, should be in alphabet.
         loadKeyboard(ALPHABET_UNSHIFTED);
         // Long press shift key, enter alphabet shift locked.
@@ -268,8 +268,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
         // Press/release shift key, back to alphabet.
         pressAndReleaseKey(CODE_SHIFT, ALPHABET_SHIFT_LOCK_SHIFTED, ALPHABET_UNSHIFTED);
 
-        // Set auto caps mode on.
-        setAutoCapsMode(AUTO_CAPS);
+        // Set capitalize the first character of all words mode.
+        setAutoCapsMode(CAP_MODE_WORDS);
         // Load keyboard, should be in automatic shifted.
         loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
         // Long press shift key, enter alphabet shift locked.
@@ -303,8 +303,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
         // Second shift key tap.
         secondPressAndReleaseKey(CODE_SHIFT, ALPHABET_UNSHIFTED, ALPHABET_UNSHIFTED);
 
-        // Set auto caps mode on.
-        setAutoCapsMode(AUTO_CAPS);
+        // Set capitalize the first character of all words mode.
+        setAutoCapsMode(CAP_MODE_WORDS);
         // Load keyboard, should be in automatic shifted.
         loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
 
@@ -322,7 +322,7 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
     // Update shift state.
     public void testUpdateShiftState() {
         // Set auto caps mode off.
-        setAutoCapsMode(NO_AUTO_CAPS);
+        setAutoCapsMode(CAP_MODE_OFF);
         // Load keyboard, should be in alphabet.
         loadKeyboard(ALPHABET_UNSHIFTED);
         // Update shift state, remained in alphabet.
@@ -350,8 +350,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
         // Update shift state, remained in symbols shifted.
         updateShiftState(SYMBOLS_SHIFTED);
 
-        // Set auto caps mode on.
-        setAutoCapsMode(AUTO_CAPS);
+        // Set capitalize the first character of all words mode.
+        setAutoCapsMode(CAP_MODE_WORDS);
         // Load keyboard, should be in automatic shifted.
         loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
         // Update shift state, remained in automatic shifted.
@@ -592,11 +592,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
 
     // Change focus to auto caps text field.
     public void testChangeFocusAutoCaps() {
-        // Set auto caps mode on.
-        setAutoCapsMode(AUTO_CAPS);
-
-        // Update shift state.
-        updateShiftState(ALPHABET_AUTOMATIC_SHIFTED);
+        // Set capitalize the first character of all words mode.
+        setAutoCapsMode(CAP_MODE_WORDS);
         // Change focus to new text field.
         loadKeyboard(ALPHABET_AUTOMATIC_SHIFTED);
 
@@ -735,8 +732,8 @@ public class KeyboardStateSingleTouchTests extends KeyboardStateTestsBase {
         // Rapidly press/release letter key.
         secondPressAndReleaseKey('J', ALPHABET_MANUAL_SHIFTED, ALPHABET_UNSHIFTED);
 
-        // Set auto caps mode on.
-        setAutoCapsMode(AUTO_CAPS);
+        // Set capitalize the first character of all words mode.
+        setAutoCapsMode(CAP_MODE_WORDS);
         // Press/release auto caps trigger letter to enter alphabet automatic shifted.
         pressAndReleaseKey(CODE_AUTO_CAPS_TRIGGER, ALPHABET_UNSHIFTED, ALPHABET_AUTOMATIC_SHIFTED);
         // Press/release shift key
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
index 96a54668cae82c2c5e60cea415c82e9679d90e06..bbe0dbde53d2f4aff8f305ac5c3c9c3bde9e64ac 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
@@ -29,12 +29,12 @@ public class KeyboardStateTestsBase extends AndroidTestCase
         super.setUp();
 
         mSwitcher = new MockKeyboardSwitcher();
-        mSwitcher.setAutoCapsMode(NO_AUTO_CAPS);
+        mSwitcher.setAutoCapsMode(CAP_MODE_OFF);
 
         loadKeyboard(ALPHABET_UNSHIFTED);
     }
 
-    public void setAutoCapsMode(boolean autoCaps) {
+    public void setAutoCapsMode(int autoCaps) {
         mSwitcher.setAutoCapsMode(autoCaps);
     }
 
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index 999e08a8dc1b2bb444d81ba53b3b1d8894029076..485ea61e7ee5d5cc666bb8f43c3181e0130fad62 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -16,6 +16,8 @@
 
 package com.android.inputmethod.keyboard.internal;
 
+import android.text.TextUtils;
+
 import com.android.inputmethod.keyboard.Keyboard;
 
 public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
@@ -26,8 +28,10 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
         // Argument for {@link KeyboardState#onCodeInput}.
         public static final boolean SINGLE = true;
         public static final boolean MULTI = false;
-        public static final boolean NO_AUTO_CAPS = false;
-        public static final boolean AUTO_CAPS = true;
+        public static final int CAP_MODE_OFF =
+                com.android.inputmethod.latin.Constants.TextUtils.CAP_MODE_OFF;
+        public static final int CAP_MODE_WORDS = TextUtils.CAP_MODE_WORDS;
+        public static final int CAP_MODE_CHARACTERS = TextUtils.CAP_MODE_CHARACTERS;
 
         public static final int CODE_SHIFT = Keyboard.CODE_SHIFT;
         public static final int CODE_SYMBOL = Keyboard.CODE_SWITCH_ALPHA_SYMBOL;
@@ -45,9 +49,9 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
 
     private int mLayout = Constants.ALPHABET_UNSHIFTED;
 
-    private boolean mAutoCapsMode = Constants.NO_AUTO_CAPS;
+    private int mAutoCapsMode = Constants.CAP_MODE_OFF;
     // Following InputConnection's behavior. Simulating InputType.TYPE_TEXT_FLAG_CAP_WORDS.
-    private boolean mAutoCapsState = true;
+    private int mAutoCapsState = Constants.CAP_MODE_OFF;
 
     private boolean mIsInDoubleTapTimeout;
     private int mLongPressTimeoutCode;
@@ -71,8 +75,9 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
         }
     }
 
-    public void setAutoCapsMode(boolean autoCaps) {
+    public void setAutoCapsMode(int autoCaps) {
         mAutoCapsMode = autoCaps;
+        mAutoCapsState = autoCaps;
     }
 
     public void expireDoubleTapTimeout() {
@@ -116,7 +121,7 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
 
     @Override
     public void requestUpdatingShiftState() {
-        mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState);
+        mState.onUpdateShiftState(mAutoCapsState);
     }
 
     @Override
@@ -158,7 +163,7 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
     }
 
     public void updateShiftState() {
-        mState.onUpdateShiftState(mAutoCapsMode && mAutoCapsState);
+        mState.onUpdateShiftState(mAutoCapsState);
     }
 
     public void loadKeyboard(String layoutSwitchBackSymbols) {
@@ -181,10 +186,15 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
     }
 
     public void onCodeInput(int code, boolean isSinglePointer) {
-        if (Keyboard.isLetterCode(code)) {
-            mAutoCapsState = (code == Constants.CODE_AUTO_CAPS_TRIGGER);
+        if (mAutoCapsMode == Constants.CAP_MODE_WORDS) {
+            if (Keyboard.isLetterCode(code)) {
+                mAutoCapsState = (code == Constants.CODE_AUTO_CAPS_TRIGGER)
+                        ? mAutoCapsMode : Constants.CAP_MODE_OFF;
+            }
+        } else {
+            mAutoCapsState = mAutoCapsMode;
         }
-        mState.onCodeInput(code, isSinglePointer, mAutoCapsMode && mAutoCapsState);
+        mState.onCodeInput(code, isSinglePointer, mAutoCapsState);
     }
 
     public void onCancelInput(boolean isSinglePointer) {