Merge "Add action key test for Lxx theme"
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 66ee57c..deaf6cd 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -640,14 +640,10 @@
 
     @Override
     public void onConfigurationChanged(final Configuration conf) {
-        // If orientation changed while predicting, commit the change
         final SettingsValues settingsValues = mSettings.getCurrent();
         if (settingsValues.mDisplayOrientation != conf.orientation) {
             mHandler.startOrientationChanging();
-            mInputLogic.mConnection.beginBatchEdit();
-            mInputLogic.commitTyped(mSettings.getCurrent(), LastComposedWord.NOT_A_SEPARATOR);
-            mInputLogic.mConnection.finishComposingText();
-            mInputLogic.mConnection.endBatchEdit();
+            mInputLogic.finishInput();
         }
         PersonalizationDictionarySessionRegistrar.onConfigurationChanged(this, conf,
                 mDictionaryFacilitator);
diff --git a/java/src/com/android/inputmethod/latin/RichInputConnection.java b/java/src/com/android/inputmethod/latin/RichInputConnection.java
index 9d72c64..96476b2 100644
--- a/java/src/com/android/inputmethod/latin/RichInputConnection.java
+++ b/java/src/com/android/inputmethod/latin/RichInputConnection.java
@@ -891,4 +891,8 @@
     public boolean hasSelection() {
         return mExpectedSelEnd != mExpectedSelStart;
     }
+
+    public boolean isCursorPositionKnown() {
+        return INVALID_CURSOR_POSITION != mExpectedSelStart;
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 370f045..7030ee3 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -319,8 +319,16 @@
                 || !mWordComposer.isComposingWord(); // safe to reset
         final boolean hasOrHadSelection = (oldSelStart != oldSelEnd || newSelStart != newSelEnd);
         final int moveAmount = newSelStart - oldSelStart;
-        if (selectionChangedOrSafeToReset && (hasOrHadSelection
-                || !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) {
+        // As an added small gift from the framework, it happens upon rotation when there
+        // is a selection that we get a wrong cursor position delivered to startInput() that
+        // does not get reflected in the oldSel{Start,End} parameters to the next call to
+        // onUpdateSelection. In this case, we may have set a composition, and when we're here
+        // we realize we shouldn't have. In theory, in this case, selectionChangedOrSafeToReset
+        // should be true, but that is if the framework had taken that wrong cursor position
+        // into account, which means we have to reset the entire composing state whenever there
+        // is or was a selection regardless of whether it changed or not.
+        if (hasOrHadSelection || (selectionChangedOrSafeToReset
+                && !mWordComposer.moveCursorByAndReturnIfInsideComposingWord(moveAmount))) {
             // If we are composing a word and moving the cursor, we would want to set a
             // suggestion span for recorrection to work correctly. Unfortunately, that
             // would involve the keyboard committing some new text, which would move the
@@ -1922,9 +1930,11 @@
             final boolean tryResumeSuggestions, final int remainingTries,
             // TODO: remove these arguments
             final LatinIME.UIHandler handler) {
+        final boolean shouldFinishComposition = mConnection.hasSelection()
+                || !mConnection.isCursorPositionKnown();
         if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(
                 mConnection.getExpectedSelectionStart(), mConnection.getExpectedSelectionEnd(),
-                false /* shouldFinishComposition */)) {
+                shouldFinishComposition)) {
             if (0 < remainingTries) {
                 handler.postResetCaches(tryResumeSuggestions, remainingTries - 1);
                 return false;