diff --git a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
index 4bc82d2ec588a57f8af98b713fed1056daf17fe3..cc10a4ed2a0a402473ba90eaf07f690423446a6a 100644
--- a/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
+++ b/java/src/com/android/inputmethod/compat/InputMethodManagerCompatWrapper.java
@@ -18,14 +18,12 @@ package com.android.inputmethod.compat;
 
 import android.content.Context;
 import android.os.IBinder;
-import android.util.Log;
-import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
+import com.android.inputmethod.latin.ImfUtils;
+
 import java.lang.reflect.Method;
-import java.util.List;
-import java.util.Map;
 
 // TODO: Override this class with the concrete implementation if we need to take care of the
 // performance.
@@ -44,41 +42,20 @@ public class InputMethodManagerCompatWrapper {
     }
 
     public static InputMethodManagerCompatWrapper getInstance() {
-        if (sInstance.mImm == null)
-            Log.w(TAG, "getInstance() is called before initialization");
+        if (sInstance.mImm == null) {
+            throw new RuntimeException(TAG + ".getInstance() is called before initialization");
+        }
         return sInstance;
     }
 
     public static void init(Context context) {
-        sInstance.mImm = (InputMethodManager)context.getSystemService(Context.INPUT_METHOD_SERVICE);
-    }
-
-    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
-        mImm.setAdditionalInputMethodSubtypes(imiId, subtypes);
-    }
-
-    public InputMethodSubtype getCurrentInputMethodSubtype() {
-        return mImm.getCurrentInputMethodSubtype();
+        sInstance.mImm = ImfUtils.getInputMethodManager(context);
     }
 
     public InputMethodSubtype getLastInputMethodSubtype() {
         return mImm.getLastInputMethodSubtype();
     }
 
-    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(
-            InputMethodInfo imi, boolean allowsImplicitlySelectedSubtypes) {
-        return mImm.getEnabledInputMethodSubtypeList(imi, allowsImplicitlySelectedSubtypes);
-    }
-
-    public Map<InputMethodInfo, List<InputMethodSubtype>> getShortcutInputMethodsAndSubtypes() {
-        return mImm.getShortcutInputMethodsAndSubtypes();
-    }
-
-    // We don't call this method when we switch between subtypes within this IME.
-    public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
-        mImm.setInputMethodAndSubtype(token, id, subtype);
-    }
-
     public boolean switchToLastInputMethod(IBinder token) {
         return mImm.switchToLastInputMethod(token);
     }
@@ -88,18 +65,7 @@ public class InputMethodManagerCompatWrapper {
                 onlyCurrentIme);
     }
 
-    public List<InputMethodInfo> getInputMethodList() {
-        if (mImm == null) return null;
-        return mImm.getInputMethodList();
-    }
-
-    public List<InputMethodInfo> getEnabledInputMethodList() {
-        if (mImm == null) return null;
-        return mImm.getEnabledInputMethodList();
-    }
-
     public void showInputMethodPicker() {
-        if (mImm == null) return;
         mImm.showInputMethodPicker();
     }
 }
diff --git a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
index 80a8c040caf28b9d5fed54327ad9b0c94873d5a1..efb0d77eaf687a35d9f5a44d7bafe090d612b5ab 100644
--- a/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/LatinKeyboardView.java
@@ -42,13 +42,13 @@ import com.android.inputmethod.accessibility.AccessibilityUtils;
 import com.android.inputmethod.accessibility.AccessibleKeyboardViewProxy;
 import com.android.inputmethod.keyboard.PointerTracker.DrawingProxy;
 import com.android.inputmethod.keyboard.PointerTracker.TimerProxy;
+import com.android.inputmethod.latin.ImfUtils;
 import com.android.inputmethod.latin.LatinIME;
 import com.android.inputmethod.latin.LatinImeLogger;
 import com.android.inputmethod.latin.R;
 import com.android.inputmethod.latin.ResearchLogger;
 import com.android.inputmethod.latin.StaticInnerHandlerWrapper;
 import com.android.inputmethod.latin.SubtypeLocale;
-import com.android.inputmethod.latin.SubtypeUtils;
 import com.android.inputmethod.latin.Utils;
 import com.android.inputmethod.latin.Utils.UsabilityStudyLogUtils;
 import com.android.inputmethod.latin.define.ProductionFlag;
@@ -877,13 +877,14 @@ public class LatinKeyboardView extends KeyboardView implements PointerTracker.Ke
 
             // Whether space key needs to show the "..." popup hint for special purposes
             if (mIsSpacebarTriggeringPopupByLongPress
-                    && SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(
-                            true /* include aux subtypes */)) {
+                    && ImfUtils.hasMultipleEnabledIMEsOrSubtypes(
+                            getContext(), true /* include aux subtypes */)) {
                 drawKeyPopupHint(key, canvas, paint, params);
             }
         } else if (key.mCode == Keyboard.CODE_LANGUAGE_SWITCH) {
             super.onDrawKeyTopVisuals(key, canvas, paint, params);
-            if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) {
+            if (ImfUtils.hasMultipleEnabledIMEsOrSubtypes(
+                    getContext(), true /* include aux subtypes */)) {
                 drawKeyPopupHint(key, canvas, paint, params);
             }
         } else {
diff --git a/java/src/com/android/inputmethod/latin/SubtypeUtils.java b/java/src/com/android/inputmethod/latin/ImfUtils.java
similarity index 66%
rename from java/src/com/android/inputmethod/latin/SubtypeUtils.java
rename to java/src/com/android/inputmethod/latin/ImfUtils.java
index 30be181dede3df9726f039f52cd584785938aa47..bd7d89fe7b348a7e95f425448ab0d375b5747db4 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeUtils.java
+++ b/java/src/com/android/inputmethod/latin/ImfUtils.java
@@ -18,24 +18,52 @@ package com.android.inputmethod.latin;
 
 import android.content.Context;
 import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
-
 import java.util.Collections;
 import java.util.List;
 
-public class SubtypeUtils {
-    private SubtypeUtils() {
+/**
+ * Utility class for Input Method Framework
+ */
+public class ImfUtils {
+    private ImfUtils() {
         // This utility class is not publicly instantiable.
     }
 
-    // TODO: Cache my InputMethodInfo and/or InputMethodSubtype list.
-    public static boolean checkIfSubtypeBelongsToThisIme(Context context, InputMethodSubtype ims) {
-        final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance();
-        if (imm == null) return false;
+    private static InputMethodManager sInputMethodManager;
+
+    public static InputMethodManager getInputMethodManager(Context context) {
+        if (sInputMethodManager == null) {
+            sInputMethodManager = (InputMethodManager)context.getSystemService(
+                    Context.INPUT_METHOD_SERVICE);
+        }
+        return sInputMethodManager;
+    }
 
-        final InputMethodInfo myImi = getInputMethodInfo(context.getPackageName());
+    private static InputMethodInfo sInputMethodInfoOfThisIme;
+
+    public static InputMethodInfo getInputMethodInfoOfThisIme(Context context) {
+        if (sInputMethodInfoOfThisIme == null) {
+            final InputMethodManager imm = getInputMethodManager(context);
+            final String packageName = context.getPackageName();
+            for (final InputMethodInfo imi : imm.getInputMethodList()) {
+                if (imi.getPackageName().equals(packageName))
+                    return imi;
+            }
+            throw new RuntimeException("Can not find input method id for " + packageName);
+        }
+        return sInputMethodInfoOfThisIme;
+    }
+
+    public static String getInputMethodIdOfThisIme(Context context) {
+        return getInputMethodInfoOfThisIme(context).getId();
+    }
+
+    public static boolean checkIfSubtypeBelongsToThisIme(Context context, InputMethodSubtype ims) {
+        final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
+        final InputMethodManager imm = getInputMethodManager(context);
         final List<InputMethodSubtype> subtypes = imm.getEnabledInputMethodSubtypeList(myImi, true);
         for (final InputMethodSubtype subtype : subtypes) {
             if (subtype.equals(ims)) {
@@ -45,26 +73,23 @@ public class SubtypeUtils {
         return false;
     }
 
-    public static boolean hasMultipleEnabledIMEsOrSubtypes(
+    public static boolean hasMultipleEnabledIMEsOrSubtypes(Context context,
             final boolean shouldIncludeAuxiliarySubtypes) {
-        final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance();
-        if (imm == null) return false;
-
+        final InputMethodManager imm = getInputMethodManager(context);
         final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList();
-        return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis);
+        return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, enabledImis);
     }
 
     public static boolean hasMultipleEnabledSubtypesInThisIme(Context context,
             final boolean shouldIncludeAuxiliarySubtypes) {
-        final InputMethodInfo myImi = getInputMethodInfo(context.getPackageName());
+        final InputMethodInfo myImi = getInputMethodInfoOfThisIme(context);
         final List<InputMethodInfo> imiList = Collections.singletonList(myImi);
-        return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList);
+        return hasMultipleEnabledSubtypes(context, shouldIncludeAuxiliarySubtypes, imiList);
     }
 
-    private static boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes,
-            List<InputMethodInfo> imiList) {
-        final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance();
-        if (imm == null) return false;
+    private static boolean hasMultipleEnabledSubtypes(Context context,
+            final boolean shouldIncludeAuxiliarySubtypes, List<InputMethodInfo> imiList) {
+        final InputMethodManager imm = getInputMethodManager(context);
 
         // Number of the filtered IMEs
         int filteredImisCount = 0;
@@ -113,26 +138,9 @@ public class SubtypeUtils {
         return keyboardCount > 1;
     }
 
-    public static String getInputMethodId(String packageName) {
-        return getInputMethodInfo(packageName).getId();
-    }
-
-    public static InputMethodInfo getInputMethodInfo(String packageName) {
-        final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance();
-        if (imm == null) {
-            throw new RuntimeException("Input method manager not found");
-        }
-
-        for (final InputMethodInfo imi : imm.getInputMethodList()) {
-            if (imi.getPackageName().equals(packageName))
-                return imi;
-        }
-        throw new RuntimeException("Can not find input method id for " + packageName);
-    }
-
     public static InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(
             Context context, String localeString, String keyboardLayoutSetName) {
-        final InputMethodInfo imi = getInputMethodInfo(context.getPackageName());
+        final InputMethodInfo imi = getInputMethodInfoOfThisIme(context);
         final int count = imi.getSubtypeCount();
         for (int i = 0; i < count; i++) {
             final InputMethodSubtype subtype = imi.getSubtypeAt(i);
@@ -148,11 +156,8 @@ public class SubtypeUtils {
 
     public static void setAdditionalInputMethodSubtypes(Context context,
             InputMethodSubtype[] subtypes) {
-        final InputMethodManagerCompatWrapper imm = InputMethodManagerCompatWrapper.getInstance();
-        if (imm == null) {
-            throw new RuntimeException("Input method manager not found");
-        }
-        final String imiId = getInputMethodId(context.getPackageName());
+        final InputMethodManager imm = getInputMethodManager(context);
+        final String imiId = getInputMethodIdOfThisIme(context);
         imm.setAdditionalInputMethodSubtypes(imiId, subtypes);
     }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index deb95675332e43f150b07cd93a79a3d2e45eb04a..aea6add56a23a054fe3816bb97b10422bae5030c 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -441,7 +441,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
 
         loadSettings();
 
-        SubtypeUtils.setAdditionalInputMethodSubtypes(
+        ImfUtils.setAdditionalInputMethodSubtypes(
                 this, mSettingsValues.getPrefefinedAdditionalSubtypes());
 
         // TODO: remove the following when it's not needed by updateCorrectionMode() any more
@@ -1134,7 +1134,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         if (isShowingOptionDialog()) return false;
         switch (requestCode) {
         case CODE_SHOW_INPUT_METHOD_PICKER:
-            if (SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(true /* include aux subtypes */)) {
+            if (ImfUtils.hasMultipleEnabledIMEsOrSubtypes(
+                    this, true /* include aux subtypes */)) {
                 mImm.showInputMethodPicker();
                 return true;
             }
@@ -1169,7 +1170,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
         final IBinder token = getWindow().getWindow().getAttributes().token;
         if (mShouldSwitchToLastSubtype) {
             final InputMethodSubtype lastSubtype = mImm.getLastInputMethodSubtype();
-            final boolean lastSubtypeBelongsToThisIme = SubtypeUtils.checkIfSubtypeBelongsToThisIme(
+            final boolean lastSubtypeBelongsToThisIme = ImfUtils.checkIfSubtypeBelongsToThisIme(
                     this, lastSubtype);
             if ((includesOtherImes || lastSubtypeBelongsToThisIme)
                     && mImm.switchToLastInputMethod(token)) {
@@ -2299,6 +2300,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                 getString(R.string.language_selection_title),
                 getString(R.string.english_ime_settings),
         };
+        final Context context = this;
         final DialogInterface.OnClickListener listener = new DialogInterface.OnClickListener() {
             @Override
             public void onClick(DialogInterface di, int position) {
@@ -2306,7 +2308,7 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
                 switch (position) {
                 case 0:
                     Intent intent = CompatUtils.getInputLanguageSelectionIntent(
-                            SubtypeUtils.getInputMethodId(getPackageName()),
+                            ImfUtils.getInputMethodIdOfThisIme(context),
                             Intent.FLAG_ACTIVITY_NEW_TASK
                             | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
                             | Intent.FLAG_ACTIVITY_CLEAR_TOP);
diff --git a/java/src/com/android/inputmethod/latin/SettingsValues.java b/java/src/com/android/inputmethod/latin/SettingsValues.java
index b961a768d2e22ca2d9c908344c8fcf566e3cb768..539ac59638c986e43eff88487c322ea3562eec39 100644
--- a/java/src/com/android/inputmethod/latin/SettingsValues.java
+++ b/java/src/com/android/inputmethod/latin/SettingsValues.java
@@ -306,9 +306,10 @@ public class SettingsValues {
             return false;
         }
         if (mIncludesOtherImesInLanguageSwitchList) {
-            return SubtypeUtils.hasMultipleEnabledIMEsOrSubtypes(/* include aux subtypes */false);
+            return ImfUtils.hasMultipleEnabledIMEsOrSubtypes(
+                    context, /* include aux subtypes */false);
         } else {
-            return SubtypeUtils.hasMultipleEnabledSubtypesInThisIme(
+            return ImfUtils.hasMultipleEnabledSubtypesInThisIme(
                     context, /* include aux subtypes */false);
         }
     }
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
index a2b8254a6201bf9380c77830ecb5ca71ef29acef..cf95a7e1a8eb784575c369768b125159c90b005c 100644
--- a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -28,9 +28,9 @@ import android.os.IBinder;
 import android.text.TextUtils;
 import android.util.Log;
 import android.view.inputmethod.InputMethodInfo;
+import android.view.inputmethod.InputMethodManager;
 import android.view.inputmethod.InputMethodSubtype;
 
-import com.android.inputmethod.compat.InputMethodManagerCompatWrapper;
 import com.android.inputmethod.keyboard.KeyboardSwitcher;
 
 import java.util.ArrayList;
@@ -52,7 +52,7 @@ public class SubtypeSwitcher {
 
     private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
     private /* final */ LatinIME mService;
-    private /* final */ InputMethodManagerCompatWrapper mImm;
+    private /* final */ InputMethodManager mImm;
     private /* final */ Resources mResources;
     private /* final */ ConnectivityManager mConnectivityManager;
     private final ArrayList<InputMethodSubtype> mEnabledKeyboardSubtypesOfCurrentInputMethod =
@@ -94,7 +94,7 @@ public class SubtypeSwitcher {
     private void initialize(LatinIME service) {
         mService = service;
         mResources = service.getResources();
-        mImm = InputMethodManagerCompatWrapper.getInstance();
+        mImm = ImfUtils.getInputMethodManager(service);
         mConnectivityManager = (ConnectivityManager) service.getSystemService(
                 Context.CONNECTIVITY_SERVICE);
         mEnabledKeyboardSubtypesOfCurrentInputMethod.clear();
@@ -104,7 +104,7 @@ public class SubtypeSwitcher {
         mInputLocaleStr = null;
         mCurrentSubtype = mImm.getCurrentInputMethodSubtype();
         mAllEnabledSubtypesOfCurrentInputMethod = null;
-        mNoLanguageSubtype = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+        mNoLanguageSubtype = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 service, SubtypeLocale.NO_LANGUAGE, AdditionalSubtype.QWERTY);
 
         final NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
@@ -277,7 +277,7 @@ public class SubtypeSwitcher {
         if (token == null) {
             return;
         }
-        final InputMethodManagerCompatWrapper imm = mImm;
+        final InputMethodManager imm = mImm;
         new AsyncTask<Void, Void, Void>() {
             @Override
             protected Void doInBackground(Void... params) {
diff --git a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
index 79f14052eaddf843fd83242361f2f65872df9f84..12711c137a8002e7c3c2ea4adfb380b78c9617a2 100644
--- a/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
+++ b/tests/src/com/android/inputmethod/latin/SubtypeLocaleTests.java
@@ -114,17 +114,17 @@ public class SubtypeLocaleTests extends AndroidTestCase {
 
     public void testSampleSubtypes() {
         final Context context = getContext();
-        final InputMethodSubtype EN_US = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+        final InputMethodSubtype EN_US = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, Locale.US.toString(), AdditionalSubtype.QWERTY);
-        final InputMethodSubtype EN_GB = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+        final InputMethodSubtype EN_GB = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, Locale.UK.toString(), AdditionalSubtype.QWERTY);
-        final InputMethodSubtype FR = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+        final InputMethodSubtype FR = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, Locale.FRENCH.toString(), AdditionalSubtype.AZERTY);
-        final InputMethodSubtype FR_CA = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+        final InputMethodSubtype FR_CA = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, Locale.CANADA_FRENCH.toString(), AdditionalSubtype.QWERTY);
-        final InputMethodSubtype DE = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+        final InputMethodSubtype DE = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, Locale.GERMAN.toString(), AdditionalSubtype.QWERTZ);
-        final InputMethodSubtype ZZ = SubtypeUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
+        final InputMethodSubtype ZZ = ImfUtils.findSubtypeByLocaleAndKeyboardLayoutSet(
                 context, SubtypeLocale.NO_LANGUAGE, AdditionalSubtype.QWERTY);
 
         assertFalse(AdditionalSubtype.isAdditionalSubtype(EN_US));