diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 8f918040fb0121066be2e793e7bb31d873562c67..a2ecc107fa8e316b130ceea0347a1c988bda8a28 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -219,8 +219,10 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                 latinIme.onEndBatchInputAsyncInternal((SuggestedWords) msg.obj);
                 break;
             case MSG_RESET_CACHES:
-                latinIme.retryResetCaches(msg.arg1 == 1 /* tryResumeSuggestions */,
-                        msg.arg2 /* remainingTries */);
+                latinIme.mInputLogic.retryResetCaches(latinIme.mSettings.getCurrent(),
+                        msg.arg1 == 1 /* tryResumeSuggestions */,
+                        msg.arg2 /* remainingTries */,
+                        latinIme.mKeyboardSwitcher, this);
                 break;
             }
         }
@@ -812,7 +814,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         mInputLogic.mLastSelectionEnd = editorInfo.initialSelEnd;
         // In some cases (namely, after rotation of the device) editorInfo.initialSelStart is lying
         // so we try using some heuristics to find out about these and fix them.
-        tryFixLyingCursorPosition();
+        mInputLogic.tryFixLyingCursorPosition();
 
         mHandler.cancelUpdateSuggestionStrip();
         mHandler.cancelDoubleSpacePeriodTimer();
@@ -831,44 +833,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         if (TRACE) Debug.startMethodTracing("/data/trace/latinime");
     }
 
-    /**
-     * Try to get the text from the editor to expose lies the framework may have been
-     * telling us. Concretely, when the device rotates, the frameworks tells us about where the
-     * cursor used to be initially in the editor at the time it first received the focus; this
-     * may be completely different from the place it is upon rotation. Since we don't have any
-     * means to get the real value, try at least to ask the text view for some characters and
-     * detect the most damaging cases: when the cursor position is declared to be much smaller
-     * than it really is.
-     */
-    private void tryFixLyingCursorPosition() {
-        final CharSequence textBeforeCursor = mInputLogic.mConnection.getTextBeforeCursor(
-                Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
-        if (null == textBeforeCursor) {
-            mInputLogic.mLastSelectionStart = mInputLogic.mLastSelectionEnd =
-                    Constants.NOT_A_CURSOR_POSITION;
-        } else {
-            final int textLength = textBeforeCursor.length();
-            if (textLength > mInputLogic.mLastSelectionStart
-                    || (textLength < Constants.EDITOR_CONTENTS_CACHE_SIZE
-                            && mInputLogic.mLastSelectionStart <
-                                    Constants.EDITOR_CONTENTS_CACHE_SIZE)) {
-                // It should not be possible to have only one of those variables be
-                // NOT_A_CURSOR_POSITION, so if they are equal, either the selection is zero-sized
-                // (simple cursor, no selection) or there is no cursor/we don't know its pos
-                final boolean wasEqual =
-                        mInputLogic.mLastSelectionStart == mInputLogic.mLastSelectionEnd;
-                mInputLogic.mLastSelectionStart = textLength;
-                // We can't figure out the value of mLastSelectionEnd :(
-                // But at least if it's smaller than mLastSelectionStart something is wrong,
-                // and if they used to be equal we also don't want to make it look like there is a
-                // selection.
-                if (wasEqual || mInputLogic.mLastSelectionStart > mInputLogic.mLastSelectionEnd) {
-                    mInputLogic.mLastSelectionEnd = mInputLogic.mLastSelectionStart;
-                }
-            }
-        }
-    }
-
     @Override
     public void onWindowHidden() {
         super.onWindowHidden();
@@ -1894,31 +1858,6 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         mHandler.showSuggestionStripWithTypedWord(suggestedWords, typedWord);
     }
 
-    /**
-     * Retry resetting caches in the rich input connection.
-     *
-     * When the editor can't be accessed we can't reset the caches, so we schedule a retry.
-     * This method handles the retry, and re-schedules a new retry if we still can't access.
-     * We only retry up to 5 times before giving up.
-     *
-     * @param tryResumeSuggestions Whether we should resume suggestions or not.
-     * @param remainingTries How many times we may try again before giving up.
-     */
-    private void retryResetCaches(final boolean tryResumeSuggestions, final int remainingTries) {
-        if (!mInputLogic.mConnection.resetCachesUponCursorMoveAndReturnSuccess(
-                mInputLogic.mLastSelectionStart, mInputLogic.mLastSelectionEnd, false)) {
-            if (0 < remainingTries) {
-                mHandler.postResetCaches(tryResumeSuggestions, remainingTries - 1);
-                return;
-            }
-            // If remainingTries is 0, we should stop waiting for new tries, but it's still
-            // better to load the keyboard (less things will be broken).
-        }
-        tryFixLyingCursorPosition();
-        mKeyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), mSettings.getCurrent());
-        if (tryResumeSuggestions) mHandler.postResumeSuggestions();
-    }
-
     // TODO: Make this private
     // Outside LatinIME, only used by the {@link InputTestsBase} test suite.
     @UsedForTesting
diff --git a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
index 5f3297794494e7d73ef93986c8e51aed7ff0f42f..8f7bb95fb8dd6879075089009d8d9bf5af1ad4e6 100644
--- a/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
+++ b/java/src/com/android/inputmethod/latin/inputlogic/InputLogic.java
@@ -1528,4 +1528,72 @@ public final class InputLogic {
             mWordComposer.discardPreviousWordForSuggestion();
         }
     }
+
+    /**
+     * Try to get the text from the editor to expose lies the framework may have been
+     * telling us. Concretely, when the device rotates, the frameworks tells us about where the
+     * cursor used to be initially in the editor at the time it first received the focus; this
+     * may be completely different from the place it is upon rotation. Since we don't have any
+     * means to get the real value, try at least to ask the text view for some characters and
+     * detect the most damaging cases: when the cursor position is declared to be much smaller
+     * than it really is.
+     */
+    // TODO: make this private
+    public void tryFixLyingCursorPosition() {
+        final CharSequence textBeforeCursor = mConnection.getTextBeforeCursor(
+                Constants.EDITOR_CONTENTS_CACHE_SIZE, 0);
+        if (null == textBeforeCursor) {
+            mLastSelectionStart = mLastSelectionEnd = Constants.NOT_A_CURSOR_POSITION;
+        } else {
+            final int textLength = textBeforeCursor.length();
+            if (textLength > mLastSelectionStart
+                    || (textLength < Constants.EDITOR_CONTENTS_CACHE_SIZE
+                            && mLastSelectionStart < Constants.EDITOR_CONTENTS_CACHE_SIZE)) {
+                // It should not be possible to have only one of those variables be
+                // NOT_A_CURSOR_POSITION, so if they are equal, either the selection is zero-sized
+                // (simple cursor, no selection) or there is no cursor/we don't know its pos
+                final boolean wasEqual = mLastSelectionStart == mLastSelectionEnd;
+                mLastSelectionStart = textLength;
+                // We can't figure out the value of mLastSelectionEnd :(
+                // But at least if it's smaller than mLastSelectionStart something is wrong,
+                // and if they used to be equal we also don't want to make it look like there is a
+                // selection.
+                if (wasEqual || mLastSelectionStart > mLastSelectionEnd) {
+                    mLastSelectionEnd = mLastSelectionStart;
+                }
+            }
+        }
+    }
+
+    /**
+     * Retry resetting caches in the rich input connection.
+     *
+     * When the editor can't be accessed we can't reset the caches, so we schedule a retry.
+     * This method handles the retry, and re-schedules a new retry if we still can't access.
+     * We only retry up to 5 times before giving up.
+     *
+     * @param settingsValues the current values of the settings.
+     * @param tryResumeSuggestions Whether we should resume suggestions or not.
+     * @param remainingTries How many times we may try again before giving up.
+     */
+    // TODO: make this private
+    public void retryResetCaches(final SettingsValues settingsValues,
+            final boolean tryResumeSuggestions, final int remainingTries,
+            // TODO: remove these arguments
+            final KeyboardSwitcher keyboardSwitcher, final LatinIME.UIHandler handler) {
+        if (!mConnection.resetCachesUponCursorMoveAndReturnSuccess(
+                mLastSelectionStart, mLastSelectionEnd, false)) {
+            if (0 < remainingTries) {
+                handler.postResetCaches(tryResumeSuggestions, remainingTries - 1);
+                return;
+            }
+            // If remainingTries is 0, we should stop waiting for new tries, but it's still
+            // better to load the keyboard (less things will be broken).
+        }
+        tryFixLyingCursorPosition();
+        keyboardSwitcher.loadKeyboard(getCurrentInputEditorInfo(), settingsValues);
+        if (tryResumeSuggestions) {
+            handler.postResumeSuggestions();
+        }
+    }
 }