diff --git a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
index bd54238f809d9c6b3e7c7970ea0e94e7fcb9738c..4e8a10b1fd94b2ae93d49bc3740e9e5ea99b5f5b 100644
--- a/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
+++ b/java-overridable/src/com/android/inputmethod/latin/settings/AdditionalFeaturesSettingUtils.java
@@ -47,6 +47,7 @@ public class AdditionalFeaturesSettingUtils {
         // do nothing.
     }
 
+    @Nonnull
     public static RichInputMethodSubtype createRichInputMethodSubtype(
             @Nonnull final RichInputMethodManager imm,
             @Nonnull final InputMethodSubtype subtype,
diff --git a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
index e8bd275233b3e7910546d8d4565887ce9ccfb541..5e3a5f17cbe1d2d55ba1848bcf71d2608668fbfa 100644
--- a/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/keyboard/KeyboardSwitcher.java
@@ -114,7 +114,7 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
         final int keyboardWidth = ResourceUtils.getDefaultKeyboardWidth(res);
         final int keyboardHeight = ResourceUtils.getKeyboardHeight(res, settingsValues);
         builder.setKeyboardGeometry(keyboardWidth, keyboardHeight);
-        builder.setSubtype(mSubtypeSwitcher.getCurrentSubtype());
+        builder.setSubtype(RichInputMethodManager.getInstance().getCurrentSubtype());
         builder.setVoiceInputKeyEnabled(settingsValues.mShowsVoiceInputKey);
         builder.setLanguageSwitchKeyEnabled(mLatinIME.shouldShowLanguageSwitchKey());
         builder.setSplitLayoutEnabledByUser(ProductionFlags.IS_SPLIT_KEYBOARD_SUPPORTED
@@ -123,7 +123,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
         try {
             mState.onLoadKeyboard(currentAutoCapsState, currentRecapitalizeState);
             // TODO: revisit this for multi-lingual input
-            mKeyboardTextsSet.setLocale(mSubtypeSwitcher.getCurrentSubtypeLocales()[0],
+            mKeyboardTextsSet.setLocale(
+                    RichInputMethodManager.getInstance().getCurrentSubtypeLocales()[0],
                     mThemeContext);
         } catch (KeyboardLayoutSetException e) {
             Log.w(TAG, "loading keyboard failed: " + e.mKeyboardId, e.getCause());
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 1d00c1c64f989a39420c5962eb0f3539bc09e1f5..29de8db3d93bab92701aeffb9125177597a9bc1c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -603,7 +603,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     // Has to be package-visible for unit tests
     @UsedForTesting
     void loadSettings() {
-        final Locale[] locales = mSubtypeSwitcher.getCurrentSubtypeLocales();
+        final Locale[] locales = mRichImm.getCurrentSubtypeLocales();
         final EditorInfo editorInfo = getCurrentInputEditorInfo();
         final InputAttributes inputAttributes = new InputAttributes(
                 editorInfo, isFullscreenMode(), getPackageName());
@@ -657,7 +657,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     }
 
     void resetDictionaryFacilitatorIfNecessary() {
-        final Locale[] subtypeSwitcherLocales = mSubtypeSwitcher.getCurrentSubtypeLocales();
+        final Locale[] subtypeSwitcherLocales = mRichImm.getCurrentSubtypeLocales();
         if (mDictionaryFacilitator.isForLocales(subtypeSwitcherLocales)) {
             return;
         }
@@ -909,7 +909,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         // Update to a gesture consumer with the current editor and IME state.
         mGestureConsumer = GestureConsumer.newInstance(editorInfo,
                 mInputLogic.getPrivateCommandPerformer(),
-                Arrays.asList(mSubtypeSwitcher.getCurrentSubtypeLocales()),
+                Arrays.asList(mRichImm.getCurrentSubtypeLocales()),
                 switcher.getKeyboard());
 
         // Forward this event to the accessibility utilities, if enabled.
@@ -947,7 +947,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
             // span, so we should reset our state unconditionally, even if restarting is true.
             // We also tell the input logic about the combining rules for the current subtype, so
             // it can adjust its combiners if needed.
-            mInputLogic.startInput(mSubtypeSwitcher.getCombiningRulesExtraValueOfCurrentSubtype(),
+            mInputLogic.startInput(mRichImm.getCombiningRulesExtraValueOfCurrentSubtype(),
                     currentSettingsValues);
 
             resetDictionaryFacilitatorIfNecessary();
@@ -1468,7 +1468,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
     public void onStartBatchInput() {
         mInputLogic.onStartBatchInput(mSettings.getCurrent(), mKeyboardSwitcher, mHandler);
         mGestureConsumer.onGestureStarted(
-                Arrays.asList(mSubtypeSwitcher.getCurrentSubtypeLocales()),
+                Arrays.asList(mRichImm.getCurrentSubtypeLocales()),
                 mKeyboardSwitcher.getKeyboard());
     }
 
@@ -1590,7 +1590,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                 // We should clear the contextual strip if there is no suggestion from dictionaries.
                 || noSuggestionsFromDictionaries) {
             mSuggestionStripView.setSuggestions(suggestedWords,
-                    mSubtypeSwitcher.getCurrentSubtype().isRtlSubtype());
+                    mRichImm.getCurrentSubtype().isRtlSubtype());
         }
     }
 
diff --git a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
index 2485978d30ec8c6025019c4b95facc6274357b47..a1ac55a20c6d5a2055da2bae5641f1f265e834cc 100644
--- a/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
+++ b/java/src/com/android/inputmethod/latin/RichInputMethodManager.java
@@ -34,6 +34,7 @@ import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 import com.android.inputmethod.latin.settings.AdditionalFeaturesSettingUtils;
@@ -68,6 +69,7 @@ public class RichInputMethodManager {
     private Context mContext;
     private InputMethodManagerCompatWrapper mImmWrapper;
     private InputMethodInfoCache mInputMethodInfoCache;
+    private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
     private InputMethodInfo mShortcutInputMethodInfo;
     private InputMethodSubtype mShortcutSubtype;
     private boolean mIsNetworkConnected;
@@ -323,11 +325,48 @@ public class RichInputMethodManager {
         return INDEX_NOT_FOUND;
     }
 
+    @Nonnull
+    public RichInputMethodSubtype onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) {
+        final RichInputMethodSubtype richSubtype = createCurrentRichInputMethodSubtype(newSubtype);
+        if (DEBUG) {
+            Log.w(TAG, "onSubtypeChanged: " + richSubtype.getNameForLogging());
+        }
+        mCurrentRichInputMethodSubtype = richSubtype;
+        return richSubtype;
+    }
+
+    private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
+
+    @UsedForTesting
+    static void forceSubtype(final InputMethodSubtype subtype) {
+        sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
+    }
+
+    public Locale[] getCurrentSubtypeLocales() {
+        if (null != sForcedSubtypeForTesting) {
+            return sForcedSubtypeForTesting.getLocales();
+        }
+        return getCurrentSubtype().getLocales();
+    }
+
+    public RichInputMethodSubtype getCurrentSubtype() {
+        if (null != sForcedSubtypeForTesting) {
+            return sForcedSubtypeForTesting;
+        }
+        return mCurrentRichInputMethodSubtype;
+    }
+
+
+    public String getCombiningRulesExtraValueOfCurrentSubtype() {
+        return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
+    }
+
     @Nonnull
     public InputMethodSubtype getCurrentRawSubtype() {
         return mImmWrapper.mImm.getCurrentInputMethodSubtype();
     }
 
+    @Nonnull
     public RichInputMethodSubtype createCurrentRichInputMethodSubtype(
             @Nonnull final InputMethodSubtype rawSubtype) {
         return AdditionalFeaturesSettingUtils.createRichInputMethodSubtype(this, rawSubtype,
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index 8a7ef89ac4604510610d4c070e0efc82d7ef70f4..b2766e27a4fb9fa1f5a961b3e5d17cf08bf13bae 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -18,12 +18,9 @@ package com.android.inputmethod.latin;
 
 import android.content.Context;
 import android.content.res.Resources;
-import android.util.Log;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.annotations.UsedForTesting;
 import com.android.inputmethod.keyboard.internal.LanguageOnSpacebarHelper;
-import com.android.inputmethod.latin.define.DebugFlags;
 import com.android.inputmethod.latin.utils.SubtypeLocaleUtils;
 
 import java.util.List;
@@ -32,9 +29,6 @@ import java.util.Locale;
 import javax.annotation.Nonnull;
 
 public final class SubtypeSwitcher {
-    private static boolean DBG = DebugFlags.DEBUG_ENABLED;
-    private static final String TAG = SubtypeSwitcher.class.getSimpleName();
-
     private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
 
     private /* final */ RichInputMethodManager mRichImm;
@@ -42,7 +36,6 @@ public final class SubtypeSwitcher {
 
     private final LanguageOnSpacebarHelper mLanguageOnSpacebarHelper =
             new LanguageOnSpacebarHelper();
-    private RichInputMethodSubtype mCurrentRichInputMethodSubtype;
 
     public static SubtypeSwitcher getInstance() {
         return sInstance;
@@ -82,12 +75,7 @@ public final class SubtypeSwitcher {
 
     // Update the current subtype. LatinIME.onCurrentInputMethodSubtypeChanged calls this function.
     public void onSubtypeChanged(@Nonnull final InputMethodSubtype newSubtype) {
-        final RichInputMethodSubtype richSubtype =
-                mRichImm.createCurrentRichInputMethodSubtype(newSubtype);
-        if (DBG) {
-            Log.w(TAG, "onSubtypeChanged: " + richSubtype.getNameForLogging());
-        }
-        mCurrentRichInputMethodSubtype = richSubtype;
+        final RichInputMethodSubtype richSubtype = mRichImm.onSubtypeChanged(newSubtype);
         final Locale[] newLocales = richSubtype.getLocales();
         if (newLocales.length > 1) {
             // In multi-locales mode, the system language is never the same as the input language
@@ -109,29 +97,4 @@ public final class SubtypeSwitcher {
     public int getLanguageOnSpacebarFormatType(final RichInputMethodSubtype subtype) {
         return mLanguageOnSpacebarHelper.getLanguageOnSpacebarFormatType(subtype);
     }
-
-    private static RichInputMethodSubtype sForcedSubtypeForTesting = null;
-
-    @UsedForTesting
-    static void forceSubtype(final InputMethodSubtype subtype) {
-        sForcedSubtypeForTesting = new RichInputMethodSubtype(subtype);
-    }
-
-    public Locale[] getCurrentSubtypeLocales() {
-        if (null != sForcedSubtypeForTesting) {
-            return sForcedSubtypeForTesting.getLocales();
-        }
-        return getCurrentSubtype().getLocales();
-    }
-
-    public RichInputMethodSubtype getCurrentSubtype() {
-        if (null != sForcedSubtypeForTesting) {
-            return sForcedSubtypeForTesting;
-        }
-        return mCurrentRichInputMethodSubtype;
-    }
-
-    public String getCombiningRulesExtraValueOfCurrentSubtype() {
-        return SubtypeLocaleUtils.getCombiningRulesExtraValue(getCurrentSubtype().getRawSubtype());
-    }
 }
diff --git a/tests/src/com/android/inputmethod/latin/InputTestsBase.java b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
index 926a2d3e1e87e354c7eef441ba43cddc95401fff..6df15a1a95817d50cdcf561483877efbc2e026ae 100644
--- a/tests/src/com/android/inputmethod/latin/InputTestsBase.java
+++ b/tests/src/com/android/inputmethod/latin/InputTestsBase.java
@@ -387,7 +387,7 @@ public class InputTestsBase extends ServiceTestCase<LatinIMEForTests> {
                 false /* isAuxiliary */,
                 false /* overridesImplicitlyEnabledSubtype */,
                 0 /* id */);
-        SubtypeSwitcher.forceSubtype(subtype);
+        RichInputMethodManager.forceSubtype(subtype);
         mLatinIME.onCurrentInputMethodSubtypeChanged(subtype);
         runMessages();
         mKeyboard = mLatinIME.mKeyboardSwitcher.getKeyboard();