Move functions related to LanguageSwitcher to LatinIMESubtypeSwitcher

Change-Id: I5fa306cf311063ff96b6d45faaca2ffe84cddbf9
diff --git a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java b/java/src/com/android/inputmethod/latin/BaseKeyboardView.java
index f2edd6b..61978e4 100644
--- a/java/src/com/android/inputmethod/latin/BaseKeyboardView.java
+++ b/java/src/com/android/inputmethod/latin/BaseKeyboardView.java
@@ -925,17 +925,14 @@
     public void showPreview(int keyIndex, PointerTracker tracker) {
         int oldKeyIndex = mOldPreviewKeyIndex;
         mOldPreviewKeyIndex = keyIndex;
-        final boolean isLanguageSwitchEnabled = (mKeyboard instanceof LatinKeyboard)
-                && ((LatinKeyboard)mKeyboard).isLanguageSwitchEnabled();
         // We should re-draw popup preview when 1) we need to hide the preview, 2) we will show
         // the space key preview and 3) pointer moves off the space key to other letter key, we
         // should hide the preview of the previous key.
         final boolean hidePreviewOrShowSpaceKeyPreview = (tracker == null)
                 || tracker.isSpaceKey(keyIndex) || tracker.isSpaceKey(oldKeyIndex);
         // If key changed and preview is on or the key is space (language switch is enabled)
-        if (oldKeyIndex != keyIndex
-                && (mShowPreview
-                        || (hidePreviewOrShowSpaceKeyPreview && isLanguageSwitchEnabled))) {
+        if (oldKeyIndex != keyIndex && (mShowPreview || (hidePreviewOrShowSpaceKeyPreview
+                && SubtypeSwitcher.getInstance().isLanguageSwitchEnabled()))) {
             if (keyIndex == NOT_A_KEY) {
                 mHandler.cancelPopupPreview();
                 mHandler.dismissPreview(mDelayAfterPreview);
diff --git a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
index 3478703..bc0a40d 100644
--- a/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
+++ b/java/src/com/android/inputmethod/latin/KeyboardSwitcher.java
@@ -71,9 +71,10 @@
     private static final int SYMBOLS_MODE_STATE_BEGIN = 1;
     private static final int SYMBOLS_MODE_STATE_SYMBOL = 2;
 
+    private SubtypeSwitcher mSubtypeSwitcher;
+
     private LatinKeyboardView mInputView;
-    private final LatinIME mInputMethodService;
-    private final LanguageSwitcher mLanguageSwitcher;
+    private LatinIME mInputMethodService;
 
     private ShiftKeyState mShiftState = new ShiftKeyState();
     private ModifierKeyState mSymbolKeyState = new ModifierKeyState();
@@ -107,17 +108,27 @@
 
     private int mLayoutId;
 
-    public KeyboardSwitcher(LatinIME ims, LanguageSwitcher languageSwitcher) {
-        mInputMethodService = ims;
-        mLanguageSwitcher = languageSwitcher;
+    private static final KeyboardSwitcher sInstance = new KeyboardSwitcher();
+
+    public static KeyboardSwitcher getInstance() {
+        return sInstance;
+    }
+
+    private KeyboardSwitcher() {
+    }
+
+    public static void init(LatinIME ims) {
+        sInstance.mInputMethodService = ims;
+        sInstance.mSubtypeSwitcher = SubtypeSwitcher.getInstance();
 
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(ims);
-        mLayoutId = Integer.valueOf(prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID));
-        prefs.registerOnSharedPreferenceChangeListener(this);
+        sInstance.mLayoutId = Integer.valueOf(
+                prefs.getString(PREF_KEYBOARD_LAYOUT, DEFAULT_LAYOUT_ID));
+        prefs.registerOnSharedPreferenceChangeListener(sInstance);
     }
 
     private void makeSymbolsKeyboardIds() {
-        final Locale locale = mLanguageSwitcher.getInputLocale();
+        final Locale locale = mSubtypeSwitcher.getInputLocale();
         final int orientation = mInputMethodService.getResources().getConfiguration().orientation;
         final int mode = mMode;
         final int colorScheme = getCharColorId();
@@ -278,17 +289,15 @@
         LatinKeyboard keyboard = (ref == null) ? null : ref.get();
         if (keyboard == null) {
             final Resources res = mInputMethodService.getResources();
-            final Configuration conf = res.getConfiguration();
-            final Locale saveLocale = conf.locale;
-            conf.locale = mLanguageSwitcher.getInputLocale();
-            res.updateConfiguration(conf, null);
+            final Locale savedLocale =  mSubtypeSwitcher.changeSystemLocale(
+                    mSubtypeSwitcher.getInputLocale());
 
             final int xml = id.getXmlId();
             keyboard = new LatinKeyboard(mInputMethodService, id);
             keyboard.setVoiceMode(
                     hasVoiceKey(xml == R.xml.kbd_symbols || xml == R.xml.kbd_symbols_black),
                     mVoiceButtonEnabled);
-            keyboard.setLanguageSwitcher(mLanguageSwitcher);
+            keyboard.setLanguageSwitcher(mSubtypeSwitcher.getLanguageSwitcher());
             keyboard.setImeOptions(res, id.mMode, id.mImeOptions);
             keyboard.setColorOfSymbolIcons(isBlackSym(id.mColorScheme));
 
@@ -301,8 +310,7 @@
                 Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": "
                         + ((ref == null) ? "LOAD" : "GCed") + " id=" + id);
 
-            conf.locale = saveLocale;
-            res.updateConfiguration(conf, null);
+            mSubtypeSwitcher.changeSystemLocale(savedLocale);
         } else if (DEBUG) {
             Log.d(TAG, "keyboard cache size=" + mKeyboardCache.size() + ": HIT  id=" + id);
         }
@@ -326,7 +334,7 @@
             enableShiftLock = mode == MODE_PHONE ? false : true;
         }
         final int orientation = mInputMethodService.getResources().getConfiguration().orientation;
-        final Locale locale = mLanguageSwitcher.getInputLocale();
+        final Locale locale = mSubtypeSwitcher.getInputLocale();
         return new KeyboardId(locale, orientation, mode, xmlArray,
                 charColorId, mHasSettingsKey, hasVoiceKey, imeOptions, enableShiftLock);
     }
diff --git a/java/src/com/android/inputmethod/latin/LatinIME.java b/java/src/com/android/inputmethod/latin/LatinIME.java
index 7809e2a..9a800ba 100644
--- a/java/src/com/android/inputmethod/latin/LatinIME.java
+++ b/java/src/com/android/inputmethod/latin/LatinIME.java
@@ -18,7 +18,6 @@
 
 import com.android.inputmethod.latin.LatinIMEUtil.RingCharBuffer;
 import com.android.inputmethod.voice.FieldContext;
-import com.android.inputmethod.voice.SettingsUtil;
 import com.android.inputmethod.voice.VoiceInput;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -63,6 +62,7 @@
 import android.view.inputmethod.ExtractedTextRequest;
 import android.view.inputmethod.InputConnection;
 import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.InputMethodSubtype;
 import android.widget.LinearLayout;
 
 import java.io.FileDescriptor;
@@ -70,7 +70,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Locale;
@@ -109,20 +108,6 @@
     private static final String PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE =
             "has_used_voice_input_unsupported_locale";
 
-    // A list of locales which are supported by default for voice input, unless we get a
-    // different list from Gservices.
-    public static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES =
-            "en " +
-            "en_US " +
-            "en_GB " +
-            "en_AU " +
-            "en_CA " +
-            "en_IE " +
-            "en_IN " +
-            "en_NZ " +
-            "en_SG " +
-            "en_ZA ";
-
     // The private IME option used to indicate that no microphone should be shown for a
     // given text field. For instance this is specified by the search dialog when the
     // dialog is already showing a voice search button.
@@ -174,6 +159,7 @@
     private AlertDialog mVoiceWarningDialog;
 
     private KeyboardSwitcher mKeyboardSwitcher;
+    private SubtypeSwitcher mSubtypeSwitcher;
 
     private UserDictionary mUserDictionary;
     private UserBigramDictionary mUserBigramDictionary;
@@ -184,10 +170,6 @@
 
     private Resources mResources;
 
-    private String mInputLocale;
-    private String mSystemLocale;
-    private LanguageSwitcher mLanguageSwitcher;
-
     private final StringBuilder mComposing = new StringBuilder();
     private WordComposer mWord = new WordComposer();
     private int mCommittedLength;
@@ -394,20 +376,15 @@
     @Override
     public void onCreate() {
         LatinImeLogger.init(this);
+        SubtypeSwitcher.init(this);
+        KeyboardSwitcher.init(this);
         super.onCreate();
         //setStatusIcon(R.drawable.ime_qwerty);
         mResources = getResources();
         final Configuration conf = mResources.getConfiguration();
         final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
-        mLanguageSwitcher = new LanguageSwitcher(this);
-        mLanguageSwitcher.loadLocales(prefs);
-        mKeyboardSwitcher = new KeyboardSwitcher(this, mLanguageSwitcher);
-        mSystemLocale = conf.locale.toString();
-        mLanguageSwitcher.setSystemLocale(conf.locale);
-        String inputLanguage = mLanguageSwitcher.getInputLanguage();
-        if (inputLanguage == null) {
-            inputLanguage = conf.locale.toString();
-        }
+        mSubtypeSwitcher = SubtypeSwitcher.getInstance();
+        mKeyboardSwitcher = KeyboardSwitcher.getInstance();
         mReCorrectionEnabled = prefs.getBoolean(PREF_RECORRECTION_ENABLED,
                 getResources().getBoolean(R.bool.default_recorrection_enabled));
 
@@ -415,10 +392,10 @@
         boolean tryGC = true;
         for (int i = 0; i < LatinIMEUtil.GCUtils.GC_TRY_LOOP_MAX && tryGC; ++i) {
             try {
-                initSuggest(inputLanguage);
+                initSuggest();
                 tryGC = false;
             } catch (OutOfMemoryError e) {
-                tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait(inputLanguage, e);
+                tryGC = LatinIMEUtil.GCUtils.getInstance().tryGCOrWait("InitSuggest", e);
             }
         }
 
@@ -483,14 +460,12 @@
         return dict;
     }
 
-    private void initSuggest(String locale) {
-        mInputLocale = locale;
+    private void initSuggest() {
+        updateAutoTextEnabled();
+        String locale = mSubtypeSwitcher.getInputLanguage();
 
         Resources orig = getResources();
-        Configuration conf = orig.getConfiguration();
-        Locale saveLocale = conf.locale;
-        conf.locale = new Locale(locale);
-        orig.updateConfiguration(conf, orig.getDisplayMetrics());
+        Locale savedLocale = mSubtypeSwitcher.changeSystemLocale(new Locale(locale));
         if (mSuggest != null) {
             mSuggest.close();
         }
@@ -500,21 +475,19 @@
         int[] dictionaries = getDictionary(orig);
         mSuggest = new Suggest(this, dictionaries);
         loadAndSetAutoCompletionThreshold(sp);
-        updateAutoTextEnabled(saveLocale);
         if (mUserDictionary != null) mUserDictionary.close();
-        mUserDictionary = new UserDictionary(this, mInputLocale);
+        mUserDictionary = new UserDictionary(this, locale);
         if (mContactsDictionary == null) {
             mContactsDictionary = new ContactsDictionary(this, Suggest.DIC_CONTACTS);
         }
         if (mAutoDictionary != null) {
             mAutoDictionary.close();
         }
-        mAutoDictionary = new AutoDictionary(this, this, mInputLocale, Suggest.DIC_AUTO);
+        mAutoDictionary = new AutoDictionary(this, this, locale, Suggest.DIC_AUTO);
         if (mUserBigramDictionary != null) {
             mUserBigramDictionary.close();
         }
-        mUserBigramDictionary = new UserBigramDictionary(this, this, mInputLocale,
-                Suggest.DIC_USER);
+        mUserBigramDictionary = new UserBigramDictionary(this, this, locale, Suggest.DIC_USER);
         mSuggest.setUserBigramDictionary(mUserBigramDictionary);
         mSuggest.setUserDictionary(mUserDictionary);
         mSuggest.setContactsDictionary(mContactsDictionary);
@@ -523,8 +496,7 @@
         mWordSeparators = mResources.getString(R.string.word_separators);
         mSentenceSeparators = mResources.getString(R.string.sentence_separators);
 
-        conf.locale = saveLocale;
-        orig.updateConfiguration(conf, orig.getDisplayMetrics());
+        mSubtypeSwitcher.changeSystemLocale(savedLocale);
     }
 
     @Override
@@ -546,18 +518,9 @@
 
     @Override
     public void onConfigurationChanged(Configuration conf) {
-        // If the system locale changes and is different from the saved
-        // locale (mSystemLocale), then reload the input locale list from the
-        // latin ime settings (shared prefs) and reset the input locale
-        // to the first one.
-        final String systemLocale = conf.locale.toString();
-        if (!TextUtils.equals(systemLocale, mSystemLocale)) {
-            mSystemLocale = systemLocale;
-            mLanguageSwitcher.loadLocales(
-                    PreferenceManager.getDefaultSharedPreferences(this));
-            mLanguageSwitcher.setSystemLocale(conf.locale);
-            toggleLanguage(true, true);
-        }
+        mSubtypeSwitcher.onConfigurationChanged(conf);
+        updateAutoTextEnabled();
+
         // If orientation changed while predicting, commit the change
         if (conf.orientation != mOrientation) {
             InputConnection ic = getCurrentInputConnection();
@@ -1637,11 +1600,7 @@
         // Clear N-best suggestions
         clearSuggestions();
 
-        FieldContext context = new FieldContext(
-            getCurrentInputConnection(),
-            getCurrentInputEditorInfo(),
-            mLanguageSwitcher.getInputLanguage(),
-            mLanguageSwitcher.getEnabledLanguages());
+        FieldContext context = makeFieldContext();
         mVoiceInput.startListening(context, swipe);
         switchToRecognitionStatusView();
     }
@@ -2218,30 +2177,21 @@
     }
 
     private void toggleLanguage(boolean reset, boolean next) {
-        if (reset) {
-            mLanguageSwitcher.reset();
-        } else {
-            if (next) {
-                mLanguageSwitcher.next();
-            } else {
-                mLanguageSwitcher.prev();
-            }
-        }
+        mSubtypeSwitcher.toggleLanguage(reset, next);
         KeyboardSwitcher switcher = mKeyboardSwitcher;
         final int mode = switcher.getKeyboardMode();
         final EditorInfo attribute = getCurrentInputEditorInfo();
         final int imeOptions = (attribute != null) ? attribute.imeOptions : 0;
         switcher.loadKeyboard(mode, imeOptions, mVoiceButtonEnabled,
                 mVoiceButtonOnPrimary);
-        initSuggest(mLanguageSwitcher.getInputLanguage());
-        mLanguageSwitcher.persist();
+        initSuggest();
         switcher.updateShiftState();
     }
 
     public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
             String key) {
+        mSubtypeSwitcher.onSharedPreferenceChanged(sharedPreferences, key);
         if (PREF_SELECTED_LANGUAGES.equals(key)) {
-            mLanguageSwitcher.loadLocales(sharedPreferences);
             mRefreshKeyboardRequired = true;
         } else if (PREF_RECORRECTION_ENABLED.equals(key)) {
             mReCorrectionEnabled = sharedPreferences.getBoolean(PREF_RECORRECTION_ENABLED,
@@ -2267,7 +2217,6 @@
     }
 
     public void swipeUp() {
-        //launchSettings();
     }
 
     public void onPress(int primaryCode) {
@@ -2300,8 +2249,8 @@
         return new FieldContext(
                 getCurrentInputConnection(),
                 getCurrentInputEditorInfo(),
-                mLanguageSwitcher.getInputLanguage(),
-                mLanguageSwitcher.getEnabledLanguages());
+                mSubtypeSwitcher.getInputLanguage(),
+                mSubtypeSwitcher.getEnabledLanguages());
     }
 
     private boolean fieldCanDoVoice(FieldContext fieldContext) {
@@ -2420,11 +2369,10 @@
         }
     }
 
-    private void updateAutoTextEnabled(Locale systemLocale) {
+    private void updateAutoTextEnabled() {
         if (mSuggest == null) return;
-        boolean different =
-                !systemLocale.getLanguage().equalsIgnoreCase(mInputLocale.substring(0, 2));
-        mSuggest.setAutoTextEnabled(!different && mQuickFixes);
+        mSuggest.setAutoTextEnabled(mQuickFixes
+                && SubtypeSwitcher.getInstance().isSystemLocaleSameAsInputLocale());
     }
 
     private void updateSuggestionVisibility(SharedPreferences prefs) {
@@ -2470,19 +2418,8 @@
         mHasUsedVoiceInputUnsupportedLocale =
                 sp.getBoolean(PREF_HAS_USED_VOICE_INPUT_UNSUPPORTED_LOCALE, false);
 
-        // Get the current list of supported locales and check the current locale against that
-        // list. We cache this value so as not to check it every time the user starts a voice
-        // input. Because this method is called by onStartInputView, this should mean that as
-        // long as the locale doesn't change while the user is keeping the IME open, the
-        // value should never be stale.
-        String supportedLocalesString = SettingsUtil.getSettingsString(
-                getContentResolver(),
-                SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
-                DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
-        ArrayList<String> voiceInputSupportedLocales =
-                newArrayList(supportedLocalesString.split("\\s+"));
-
-        mLocaleSupportedForVoiceInput = voiceInputSupportedLocales.contains(mInputLocale);
+        mLocaleSupportedForVoiceInput = SubtypeSwitcher.getInstance().isVoiceSupported(
+                SubtypeSwitcher.getInstance().getInputLanguage());
 
         mAutoCorrectEnabled = isAutoCorrectEnabled(sp);
         mBigramSuggestionEnabled = mAutoCorrectEnabled && isBigramSuggestionEnabled(sp);
@@ -2496,9 +2433,9 @@
             mVoiceButtonOnPrimary = voiceMode.equals(getString(R.string.voice_mode_main));
         }
         updateCorrectionMode();
-        updateAutoTextEnabled(mResources.getConfiguration().locale);
+        updateAutoTextEnabled();
         updateSuggestionVisibility(sp);
-        mLanguageSwitcher.loadLocales(sp);
+        SubtypeSwitcher.getInstance().loadSettings(sp);
     }
 
     /**
@@ -2599,13 +2536,6 @@
         mOptionsDialog.show();
     }
 
-    public static <E> ArrayList<E> newArrayList(E... elements) {
-        int capacity = (elements.length * 110) / 100 + 5;
-        ArrayList<E> list = new ArrayList<E>(capacity);
-        Collections.addAll(list, elements);
-        return list;
-    }
-
     @Override
     protected void dump(FileDescriptor fd, PrintWriter fout, String[] args) {
         super.dump(fd, fout, args);
@@ -2647,4 +2577,9 @@
     public void onAutoCompletionStateChanged(boolean isAutoCompletion) {
         mKeyboardSwitcher.onAutoCompletionStateChanged(isAutoCompletion);
     }
+
+    @Override
+    public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
+        SubtypeSwitcher.getInstance().onCurrentInputMethodSubtypeChanged(subtype);
+    }
 }
diff --git a/java/src/com/android/inputmethod/latin/LatinIMESettings.java b/java/src/com/android/inputmethod/latin/LatinIMESettings.java
index 0f0fe1e..df2cd27 100644
--- a/java/src/com/android/inputmethod/latin/LatinIMESettings.java
+++ b/java/src/com/android/inputmethod/latin/LatinIMESettings.java
@@ -182,13 +182,7 @@
                 // Get the current list of supported locales and check the current locale against
                 // that list, to decide whether to put a warning that voice input will not work in
                 // the current language as part of the pop-up confirmation dialog.
-                String supportedLocalesString = SettingsUtil.getSettingsString(
-                        getContentResolver(),
-                        SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
-                        LatinIME.DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
-                ArrayList<String> voiceInputSupportedLocales =
-                        LatinIME.newArrayList(supportedLocalesString.split("\\s+"));
-                boolean localeSupported = voiceInputSupportedLocales.contains(
+                boolean localeSupported = SubtypeSwitcher.getInstance().isVoiceSupported(
                         Locale.getDefault().toString());
 
                 if (localeSupported) {
diff --git a/java/src/com/android/inputmethod/latin/LatinKeyboard.java b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
index 42faab4..54d8c47 100644
--- a/java/src/com/android/inputmethod/latin/LatinKeyboard.java
+++ b/java/src/com/android/inputmethod/latin/LatinKeyboard.java
@@ -386,10 +386,6 @@
         return mSpaceKey;
     }
 
-    public boolean isLanguageSwitchEnabled() {
-        return mLocale != null;
-    }
-
     private void updateSpaceBarForLocale(boolean isAutoCompletion, boolean isBlack) {
         final Resources res = mRes;
         // If application locales are explicitly selected.
diff --git a/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
new file mode 100644
index 0000000..a295957
--- /dev/null
+++ b/java/src/com/android/inputmethod/latin/SubtypeSwitcher.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2010 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 License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.inputmethod.latin;
+
+import com.android.inputmethod.voice.SettingsUtil;
+
+import android.content.SharedPreferences;
+import android.content.res.Configuration;
+import android.content.res.Resources;
+import android.inputmethodservice.InputMethodService;
+import android.preference.PreferenceManager;
+import android.text.TextUtils;
+import android.view.inputmethod.InputMethodSubtype;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Locale;
+
+public class SubtypeSwitcher {
+    private static final boolean USE_LEGACY_LANGUAGE_SWITCHER = true;
+    private static final String TAG = "SubtypeSwitcher";
+    private static final SubtypeSwitcher sInstance = new SubtypeSwitcher();
+    private InputMethodService mService;
+    private Resources mResources;
+    private Locale mSystemLocale;
+
+    public static SubtypeSwitcher getInstance() {
+        return sInstance;
+    }
+
+    public static void init(LatinIME service) {
+        sInstance.mService = service;
+        sInstance.mResources = service.getResources();
+        sInstance.mSystemLocale = sInstance.mResources.getConfiguration().locale;
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            sInstance.initLanguageSwitcher(service);
+        }
+    }
+
+    private SubtypeSwitcher() {
+    }
+
+    public void onCurrentInputMethodSubtypeChanged(InputMethodSubtype subtype) {
+    }
+
+    //////////////////////////////////
+    // Language Switching functions //
+    //////////////////////////////////
+
+    private int getEnabledKeyboardLocaleCount() {
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            return mLanguageSwitcher.getLocaleCount();
+        }
+        // TODO: Implement for no legacy mode
+        return 0;
+    }
+
+    public boolean isLanguageSwitchEnabled() {
+     // TODO: Takes care of two-char locale such as "en" in addition to "en_US"
+        return !(getEnabledKeyboardLocaleCount() == 1 && getSystemLocale().getLanguage(
+                ).equalsIgnoreCase(getInputLocale().getLanguage()));
+    }
+
+    public Locale getInputLocale() {
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            return mLanguageSwitcher.getInputLocale();
+        }
+        // TODO: Implement for no legacy mode
+        return null;
+    }
+
+    public String getInputLanguage() {
+        String inputLanguage = null;
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            inputLanguage = mLanguageSwitcher.getInputLanguage();
+        }
+        // Should return system locale if there is no Language available.
+        if (inputLanguage == null) {
+            inputLanguage = getSystemLocale().getLanguage();
+        }
+        return inputLanguage;
+    }
+
+    public String[] getEnabledLanguages() {
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            return mLanguageSwitcher.getEnabledLanguages();
+        }
+        // TODO: Implement for no legacy mode
+        return null;
+    }
+
+    public Locale getSystemLocale() {
+        return mSystemLocale;
+    }
+
+    public boolean isSystemLocaleSameAsInputLocale() {
+        // TODO: Takes care of two-char locale such as "en" in addition to "en_US"
+        return getSystemLocale().getLanguage().equalsIgnoreCase(
+                getInputLanguage().substring(0, 2));
+    }
+
+    public void onConfigurationChanged(Configuration conf) {
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            // If the system locale changes and is different from the saved
+            // locale (mSystemLocale), then reload the input locale list from the
+            // latin ime settings (shared prefs) and reset the input locale
+            // to the first one.
+            final Locale systemLocale = conf.locale;
+            if (!TextUtils.equals(systemLocale.toString(), mSystemLocale.toString())) {
+                mSystemLocale = systemLocale;
+                mLanguageSwitcher.loadLocales(
+                        PreferenceManager.getDefaultSharedPreferences(mService));
+                mLanguageSwitcher.setSystemLocale(systemLocale);
+                toggleLanguage(true, true);
+            }
+            return;
+        }
+    }
+
+    public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            mLanguageSwitcher.loadLocales(sharedPreferences);
+            return;
+        }
+    }
+
+    public Locale changeSystemLocale(Locale newLocale) {
+        Configuration conf = mResources.getConfiguration();
+        Locale oldLocale = conf.locale;
+        conf.locale = newLocale;
+        mResources.updateConfiguration(conf, mResources.getDisplayMetrics());
+        return oldLocale;
+    }
+
+    ////////////////////////////////////////////
+    // Legacy Language Switch support //
+    ////////////////////////////////////////////
+    private LanguageSwitcher mLanguageSwitcher;
+
+
+    // TODO: This can be an array of String
+    // A list of locales which are supported by default for voice input, unless we get a
+    // different list from Gservices.
+    private static final String DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES =
+            "en " +
+            "en_US " +
+            "en_GB " +
+            "en_AU " +
+            "en_CA " +
+            "en_IE " +
+            "en_IN " +
+            "en_NZ " +
+            "en_SG " +
+            "en_ZA ";
+
+    public boolean isVoiceSupported(String locale) {
+        // Get the current list of supported locales and check the current locale against that
+        // list. We cache this value so as not to check it every time the user starts a voice
+        // input. Because this method is called by onStartInputView, this should mean that as
+        // long as the locale doesn't change while the user is keeping the IME open, the
+        // value should never be stale.
+        String supportedLocalesString = SettingsUtil.getSettingsString(
+                mService.getContentResolver(),
+                SettingsUtil.LATIN_IME_VOICE_INPUT_SUPPORTED_LOCALES,
+                DEFAULT_VOICE_INPUT_SUPPORTED_LOCALES);
+        List<String> voiceInputSupportedLocales = Arrays.asList(
+                supportedLocalesString.split("\\s+"));
+        return voiceInputSupportedLocales.contains(locale);
+    }
+
+    public void loadSettings(SharedPreferences prefs) {
+        if (USE_LEGACY_LANGUAGE_SWITCHER) {
+            mLanguageSwitcher.loadLocales(prefs);
+        }
+    }
+
+    public void toggleLanguage(boolean reset, boolean next) {
+        if (reset) {
+            mLanguageSwitcher.reset();
+        } else {
+            if (next) {
+                mLanguageSwitcher.next();
+            } else {
+                mLanguageSwitcher.prev();
+            }
+        }
+        mLanguageSwitcher.persist();
+    }
+
+    private void initLanguageSwitcher(LatinIME service) {
+        final Configuration conf = service.getResources().getConfiguration();
+        final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(service);
+        mLanguageSwitcher = new LanguageSwitcher(service);
+        mLanguageSwitcher.loadLocales(prefs);
+        mLanguageSwitcher.setSystemLocale(conf.locale);
+    }
+
+    // TODO: remove this function when the refactor for LanguageSwitcher will be finished
+    public LanguageSwitcher getLanguageSwitcher() {
+        return mLanguageSwitcher;
+    }
+}
\ No newline at end of file