diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 60f8ce8d8daba86adfddf095775530332bc87417..d2b1e9bca8e97d372e93bc2ae7d0f02152b204b8 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -1071,7 +1071,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
     public void commitTyped(final InputConnection ic) {
         if (!mWordComposer.isComposingWord()) return;
         final CharSequence typedWord = mWordComposer.getTypedWord();
-        mWordComposer.onCommitWord();
+        mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_USER_TYPED_WORD);
         if (typedWord.length() > 0) {
             if (ic != null) {
                 ic.commitText(typedWord, 1);
@@ -1802,7 +1802,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
             }
             Utils.Stats.onAutoCorrection(typedWord, autoCorrection.toString(), separatorCodePoint);
             mExpectingUpdateSelection = true;
-            commitBestWord(autoCorrection);
+            commitChosenWord(autoCorrection, WordComposer.COMMIT_TYPE_DECIDED_WORD);
             // Add the word to the user unigram dictionary if it's not a known word
             addToUserUnigramAndBigramDictionaries(autoCorrection,
                     UserUnigramDictionary.FREQUENCY_FOR_TYPED);
@@ -1868,7 +1868,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
             return;
         }
         mExpectingUpdateSelection = true;
-        commitBestWord(suggestion);
+        commitChosenWord(suggestion, WordComposer.COMMIT_TYPE_MANUAL_PICK);
         // Add the word to the auto dictionary if it's not a known word
         if (index == 0) {
             addToUserUnigramAndBigramDictionaries(suggestion,
@@ -1927,7 +1927,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
     /**
      * Commits the chosen word to the text field and saves it for later retrieval.
      */
-    private void commitBestWord(CharSequence bestWord) {
+    private void commitChosenWord(final CharSequence bestWord, final int commitType) {
         final KeyboardSwitcher switcher = mKeyboardSwitcher;
         if (!switcher.isKeyboardAvailable())
             return;
@@ -1942,7 +1942,11 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
                 ic.commitText(bestWord, 1);
             }
         }
-        mWordComposer.onCommitWord();
+        // TODO: figure out here if this is an auto-correct or if the best word is actually
+        // what user typed. Note: currently this is done much later in
+        // WordComposer#didAutoCorrectToAnotherWord by string equality of the remembered
+        // strings.
+        mWordComposer.onCommitWord(commitType);
     }
 
     private static final WordComposer sEmptyWordComposer = new WordComposer();
@@ -2118,7 +2122,7 @@ public class LatinIME extends InputMethodServiceCompatWrapper implements Keyboar
         // Re-insert the separator
         ic.commitText(separator, 1);
         mWordComposer.deleteAutoCorrection();
-        mWordComposer.onCommitWord();
+        mWordComposer.onCommitWord(WordComposer.COMMIT_TYPE_CANCEL_AUTO_CORRECT);
         Utils.Stats.onSeparator(separator.charAt(0), WordComposer.NOT_A_COORDINATE,
                 WordComposer.NOT_A_COORDINATE);
         mHandler.cancelUpdateBigramPredictions();
diff --git a/java/src/com/android/inputmethod/latin/WordComposer.java b/java/src/com/android/inputmethod/latin/WordComposer.java
index 54d9080111e43962ab3ba02ea3eac6cddf0e08c9..7e844e9f4000d7dc4f218f23655802d533045253 100644
--- a/java/src/com/android/inputmethod/latin/WordComposer.java
+++ b/java/src/com/android/inputmethod/latin/WordComposer.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (C) 2008 The Android Open Source Project
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
  * use this file except in compliance with the License. You may obtain a copy of
  * the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
@@ -33,6 +33,23 @@ public class WordComposer {
     public static final int NOT_A_CODE = KeyDetector.NOT_A_CODE;
     public static final int NOT_A_COORDINATE = -1;
 
+    // TODO: Straighten out commit behavior so that the flags here are more understandable,
+    // and possibly adjust their names.
+    // COMMIT_TYPE_USER_TYPED_WORD is used when the word committed is the exact typed word, with
+    // no hinting from the IME. It happens when some external event happens (rotating the device,
+    // for example) or when auto-correction is off by settings or editor attributes.
+    public static final int COMMIT_TYPE_USER_TYPED_WORD = 0;
+    // COMMIT_TYPE_MANUAL_PICK is used when the user pressed a field in the suggestion strip.
+    public static final int COMMIT_TYPE_MANUAL_PICK = 1;
+    // COMMIT_TYPE_DECIDED_WORD is used when the IME commits the word it decided was best
+    // for the current user input. It may be different from what the user typed (true auto-correct)
+    // or it may be exactly what the user typed if it's in the dictionary or the IME does not have
+    // enough confidence in any suggestion to auto-correct (auto-correct to typed word).
+    public static final int COMMIT_TYPE_DECIDED_WORD = 2;
+    // COMMIT_TYPE_CANCEL_AUTO_CORRECT is used upon committing back the old word upon cancelling
+    // an auto-correction.
+    public static final int COMMIT_TYPE_CANCEL_AUTO_CORRECT = 3;
+
     // Storage for all the info about the current input.
     private static class CharacterStore {
         /**
@@ -291,7 +308,7 @@ public class WordComposer {
         return mCapsCount > 1;
     }
 
-    /** 
+    /**
      * Saves the reason why the word is capitalized - whether it was automatic or
      * due to the user hitting shift in the middle of a sentence.
      * @param auto whether it was an automatic capitalization due to start of sentence
@@ -329,10 +346,23 @@ public class WordComposer {
         return mCurrentWord.mAutoCorrection;
     }
 
-    // TODO: pass the information about what was committed and how. Was it an auto-correction?
-    // Was it a completion? Was is what the user typed?
-    public void onCommitWord() {
+    // `type' should be one of the COMMIT_TYPE_* constants above.
+    public void onCommitWord(final int type) {
         mCommittedWordSavedForSuggestionResuming = mCurrentWord;
+        // Note: currently, we come here whenever we commit a word. If it's any *other* kind that
+        // DECIDED_WORD, we should reset mAutoCorrection so that we don't attempt to cancel later.
+        // If it's a DECIDED_WORD, it may be an actual auto-correction by the IME, or what the user
+        // typed because the IME decided *not* to auto-correct for whatever reason.
+        // Ideally we would also null it when it was a DECIDED_WORD that was not an auto-correct.
+        // As it happens these two cases should behave differently, because the former can be
+        // canceled while the latter can't. Currently, we figure this out in
+        // #didAutoCorrectToAnotherWord with #equals(). It would be marginally cleaner to do it
+        // here, but it would be slower (since we would #equals() for each commit, instead of
+        // only on cancel), and ultimately we want to figure it out even earlier anyway.
+        if (type != COMMIT_TYPE_DECIDED_WORD) {
+            // Only ever revert an auto-correct.
+            mCommittedWordSavedForSuggestionResuming.mAutoCorrection = null;
+        }
         // TODO: improve performance by swapping buffers instead of creating a new object.
         mCurrentWord = new CharacterStore();
     }