diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index e50d922eabcc12582a76734c52c0993880f4e7ae..37fa674c24bae13ada323552cb1f73107b169e1a 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -71,7 +71,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
 
     private InputView mCurrentInputView;
     private LatinKeyboardView mKeyboardView;
-    private LatinIME mInputMethodService;
+    private LatinIME mLatinIME;
     private Resources mResources;
 
     private KeyboardState mState;
@@ -95,17 +95,17 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
         // Intentional empty constructor for singleton.
     }
 
-    public static void init(LatinIME ims, SharedPreferences prefs) {
-        sInstance.initInternal(ims, prefs);
+    public static void init(LatinIME latinIme, SharedPreferences prefs) {
+        sInstance.initInternal(latinIme, prefs);
     }
 
-    private void initInternal(LatinIME ims, SharedPreferences prefs) {
-        mInputMethodService = ims;
-        mResources = ims.getResources();
+    private void initInternal(LatinIME latinIme, SharedPreferences prefs) {
+        mLatinIME = latinIme;
+        mResources = latinIme.getResources();
         mPrefs = prefs;
         mSubtypeSwitcher = SubtypeSwitcher.getInstance();
         mState = new KeyboardState(this);
-        setContextThemeWrapper(ims, getKeyboardTheme(ims, prefs));
+        setContextThemeWrapper(latinIme, getKeyboardTheme(latinIme, prefs));
         mForceNonDistinctMultitouch = prefs.getBoolean(
                 DebugSettings.FORCE_NON_DISTINCT_MULTITOUCH_KEY, false);
     }
@@ -194,14 +194,14 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
      * Update keyboard shift state triggered by connected EditText status change.
      */
     public void updateShiftState() {
-        mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
+        mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
     }
 
     public void onPressKey(int code) {
         if (isVibrateAndSoundFeedbackRequired()) {
-            mInputMethodService.hapticAndAudioFeedback(code);
+            mLatinIME.hapticAndAudioFeedback(code);
         }
-        mState.onPressKey(code);
+        mState.onPressKey(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
     }
 
     public void onReleaseKey(int code, boolean withSliding) {
@@ -257,7 +257,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void requestUpdatingShiftState() {
-        mState.onUpdateShiftState(mInputMethodService.getCurrentAutoCapsState());
+        mState.onUpdateShiftState(mLatinIME.getCurrentAutoCapsState());
     }
 
     // Implements {@link KeyboardState.SwitchActions}.
@@ -311,7 +311,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
     // Implements {@link KeyboardState.SwitchActions}.
     @Override
     public void hapticAndAudioFeedback(int code) {
-        mInputMethodService.hapticAndAudioFeedback(code);
+        mLatinIME.hapticAndAudioFeedback(code);
     }
 
     public void onLongPressTimeout(int code) {
@@ -338,7 +338,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
      * Updates state machine to figure out when to automatically switch back to the previous mode.
      */
     public void onCodeInput(int code) {
-        mState.onCodeInput(code, isSinglePointer(), mInputMethodService.getCurrentAutoCapsState());
+        mState.onCodeInput(code, isSinglePointer(), mLatinIME.getCurrentAutoCapsState());
     }
 
     public LatinKeyboardView getKeyboardView() {
@@ -354,7 +354,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
         boolean tryGC = true;
         for (int i = 0; i < Utils.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
             try {
-                setContextThemeWrapper(mInputMethodService, mKeyboardTheme);
+                setContextThemeWrapper(mLatinIME, mKeyboardTheme);
                 mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
                         R.layout.input_view, null);
                 tryGC = false;
@@ -368,7 +368,7 @@ public class KeyboardSwitcher implements KeyboardState.SwitchActions {
         }
 
         mKeyboardView = (LatinKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
-        mKeyboardView.setKeyboardActionListener(mInputMethodService);
+        mKeyboardView.setKeyboardActionListener(mLatinIME);
         if (mForceNonDistinctMultitouch) {
             mKeyboardView.setDistinctMultitouch(false);
         }
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardView.java b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
index 2045b0c828255edefdbb27c881863de78cdfb060..51a0f537fe60f08bb61592d2b87b3d3b4c44a9a5 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardView.java
@@ -389,11 +389,6 @@ public class KeyboardView extends View implements PointerTracker.DrawingProxy {
      * @param keyboard the keyboard to display in this view
      */
     public void setKeyboard(Keyboard keyboard) {
-        // Remove any pending messages.
-        mDrawingHandler.cancelAllMessages();
-        if (mKeyboard != null) {
-            PointerTracker.dismissAllKeyPreviews();
-        }
         mKeyboard = keyboard;
         LatinImeLogger.onSetKeyboard(keyboard);
         requestLayout();
diff --git a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
index e3661a9f8d669f5ac87a5c5ae33b98913b4d1a51..c85122ad3e78d7872433f7b5a702c4e7f39fe1e9 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/KeyboardState.java
@@ -30,7 +30,7 @@ import com.android.inputmethod.latin.define.ProductionFlag;
  * This class contains all keyboard state transition logic.
  *
  * The input events are {@link #onLoadKeyboard(String)}, {@link #onSaveKeyboardState()},
- * {@link #onPressKey(int)}, {@link #onReleaseKey(int, boolean)},
+ * {@link #onPressKey(int, boolean, int)}, {@link #onReleaseKey(int, boolean)},
  * {@link #onCodeInput(int, boolean, int)}, {@link #onCancelInput(boolean)},
  * {@link #onUpdateShiftState(int)}, {@link #onLongPressTimeout(int)}.
  *
@@ -297,9 +297,10 @@ public class KeyboardState {
         mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
     }
 
-    public void onPressKey(int code) {
+    public void onPressKey(int code, boolean isSinglePointer, int autoCaps) {
         if (DEBUG_EVENT) {
-            Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code) + " " + this);
+            Log.d(TAG, "onPressKey: code=" + Keyboard.printableCode(code)
+                   + " single=" + isSinglePointer + " autoCaps=" + autoCaps + " " + this);
         }
         if (ProductionFlag.IS_EXPERIMENTAL) {
             ResearchLogger.keyboardState_onPressKey(code, this);
@@ -313,6 +314,21 @@ public class KeyboardState {
             mSwitchActions.cancelLongPressTimer();
             mShiftKeyState.onOtherKeyPressed();
             mSymbolKeyState.onOtherKeyPressed();
+            // It is required to reset the auto caps state when all of the following conditions
+            // are met:
+            // 1) two or more fingers are in action
+            // 2) in alphabet layout
+            // 3) not in all characters caps mode
+            // As for #3, please note that it's required to check even when the auto caps mode is
+            // off because, for example, we may be in the #1 state within the manual temporary
+            // shifted mode.
+            if (!isSinglePointer && mIsAlphabetMode && autoCaps != TextUtils.CAP_MODE_CHARACTERS) {
+                final boolean needsToResetAutoCaps = mAlphabetShiftState.isAutomaticShifted()
+                        || (mAlphabetShiftState.isManualShifted() && mShiftKeyState.isReleasing());
+                if (needsToResetAutoCaps) {
+                    mSwitchActions.setAlphabetKeyboard();
+                }
+            }
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index e26b2dc2547b0af463ddc17f68136dd670e7287f..b474a8558d39e1a189b93d09276186c8604d8675 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1056,6 +1056,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                 | InputType.TYPE_TEXT_FLAG_CAP_WORDS)) == 0;
         if (noNeedToCheckCapsMode) return Constants.TextUtils.CAP_MODE_OFF;
 
+        // Avoid making heavy round-trip IPC calls of {@link InputConnection#getCursorCapsMode}
+        // unless needed.
+        if (mWordComposer.isComposingWord()) return Constants.TextUtils.CAP_MODE_OFF;
+
         final InputConnection ic = getCurrentInputConnection();
         if (ic == null) return Constants.TextUtils.CAP_MODE_OFF;
         // TODO: This blocking IPC call is heavy. Consider doing this without using IPC calls.
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
index 5c62c11c5f5d8dd3ab648518bfc2ae6305206d9c..dc098db1e82cdb40431432c9f384e599275311aa 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateMultiTouchTests.java
@@ -268,13 +268,12 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
 
         // Press 'X' key and hold
         pressKey('X', ALPHABET_MANUAL_SHIFTED);
-        // TODO: The following test fails due to a bug. Temporarily commented out.
-//        // Press 'z' key and hold, switch back to alphabet unshifted.
-//        chordingPressKey('z', ALPHABET_UNSHIFTED);
-//        // Release 'X' key
-//        releaseKey('X', ALPHABET_UNSHIFTED);
-//        // Release 'z' key
-//        releaseKey('z', ALPHABET_UNSHIFTED);
+        // Press 'z' key and hold, switch back to alphabet unshifted.
+        chordingPressKey('z', ALPHABET_UNSHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_UNSHIFTED);
+        // Release 'z' key
+        releaseKey('z', ALPHABET_UNSHIFTED);
     }
 
     // Multi touch input in automatic upper case.
@@ -286,13 +285,12 @@ public class KeyboardStateMultiTouchTests extends KeyboardStateTestsBase {
 
         // Press 'X' key and hold
         pressKey('X', ALPHABET_AUTOMATIC_SHIFTED);
-        // TODO: The following test fails due to a bug. Temporarily commented out.
-//        // Press 'z' key and hold, switch back to alphabet unshifted.
-//        chordingPressKey('z', ALPHABET_UNSHIFTED);
-//        // Release 'X' key
-//        releaseKey('X', ALPHABET_UNSHIFTED);
-//        // Release 'z' key
-//        releaseKey('z', ALPHABET_UNSHIFTED);
+        // Press 'z' key and hold, switch back to alphabet unshifted.
+        chordingPressKey('z', ALPHABET_UNSHIFTED);
+        // Release 'X' key
+        releaseKey('X', ALPHABET_UNSHIFTED);
+        // Release 'z' key
+        releaseKey('z', ALPHABET_UNSHIFTED);
     }
 
     // Multi touch input in capitalize character mode.
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
index bbe0dbde53d2f4aff8f305ac5c3c9c3bde9e64ac..9472a1fe562a6cd826ea7de75d1ccc6dca6ae455 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/KeyboardStateTestsBase.java
@@ -64,14 +64,14 @@ public class KeyboardStateTestsBase extends AndroidTestCase
         assertLayout(afterRotate, mSwitcher.getLayoutId());
     }
 
-    private void pressKeyWithoutTimerExpire(int code, int afterPress) {
-        mSwitcher.onPressKey(code);
+    private void pressKeyWithoutTimerExpire(int code, boolean isSinglePointer, int afterPress) {
+        mSwitcher.onPressKey(code, isSinglePointer);
         assertLayout(afterPress, mSwitcher.getLayoutId());
     }
 
     public void pressKey(int code, int afterPress) {
         mSwitcher.expireDoubleTapTimeout();
-        pressKeyWithoutTimerExpire(code, afterPress);
+        pressKeyWithoutTimerExpire(code, true, afterPress);
     }
 
     public void releaseKey(int code, int afterRelease) {
@@ -86,7 +86,8 @@ public class KeyboardStateTestsBase extends AndroidTestCase
     }
 
     public void chordingPressKey(int code, int afterPress) {
-        pressKey(code, afterPress);
+        mSwitcher.expireDoubleTapTimeout();
+        pressKeyWithoutTimerExpire(code, false, afterPress);
     }
 
     public void chordingReleaseKey(int code, int afterRelease) {
@@ -114,7 +115,7 @@ public class KeyboardStateTestsBase extends AndroidTestCase
     }
 
     public void secondPressAndReleaseKey(int code, int afterPress, int afterRelease) {
-        pressKeyWithoutTimerExpire(code, afterPress);
+        pressKeyWithoutTimerExpire(code, true, afterPress);
         releaseKey(code, afterRelease);
     }
 }
diff --git a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
index 485ea61e7ee5d5cc666bb8f43c3181e0130fad62..dd4caadf159a0cff3cfdb52b44ff06efc0d7d074 100644
--- a/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
+++ b/tests/src/com/android/inputmethod/keyboard/internal/MockKeyboardSwitcher.java
@@ -174,8 +174,8 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
         mState.onSaveKeyboardState();
     }
 
-    public void onPressKey(int code) {
-        mState.onPressKey(code);
+    public void onPressKey(int code, boolean isSinglePointer) {
+        mState.onPressKey(code, isSinglePointer, mAutoCapsState);
     }
 
     public void onReleaseKey(int code, boolean withSliding) {