16fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka/* 26fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * Copyright (C) 2012 The Android Open Source Project 36fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * 46fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * Licensed under the Apache License, Version 2.0 (the "License"); 56fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * you may not use this file except in compliance with the License. 66fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * You may obtain a copy of the License at 76fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * 86fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * http://www.apache.org/licenses/LICENSE-2.0 96fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * 106fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * Unless required by applicable law or agreed to in writing, software 116fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * distributed under the License is distributed on an "AS IS" BASIS, 126fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 136fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * See the License for the specific language governing permissions and 146fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * limitations under the License. 156fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka */ 166fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 176fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokapackage com.android.inputmethod.latin; 186fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 196fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport static com.android.inputmethod.latin.Constants.Subtype.KEYBOARD_MODE; 206fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 216fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport android.content.Context; 2285e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaokaimport android.content.SharedPreferences; 236fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport android.os.IBinder; 24f90fc105ab1159f43f536bcacdd1224c2c05bacbTadashi G. Takaokaimport android.preference.PreferenceManager; 2585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaokaimport android.util.Log; 266fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport android.view.inputmethod.InputMethodInfo; 276fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport android.view.inputmethod.InputMethodManager; 286fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport android.view.inputmethod.InputMethodSubtype; 296fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 306fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport com.android.inputmethod.compat.InputMethodManagerCompatWrapper; 31a7d2fc6befa1b16883200a653fc01deb4d94944dKen Wakasaimport com.android.inputmethod.latin.settings.Settings; 32a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaokaimport com.android.inputmethod.latin.utils.AdditionalSubtypeUtils; 33e28eba5074664d5716b8e58b8d0a235746b261ebKen Wakasaimport com.android.inputmethod.latin.utils.CollectionUtils; 34a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaokaimport com.android.inputmethod.latin.utils.SubtypeLocaleUtils; 356fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 366fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport java.util.Collections; 37ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalardimport java.util.HashMap; 386fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokaimport java.util.List; 396fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 406fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka/** 416fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka * Enrichment class for InputMethodManager to simplify interaction and add functionality. 426fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka */ 436fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaokapublic final class RichInputMethodManager { 446fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private static final String TAG = RichInputMethodManager.class.getSimpleName(); 456fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 466fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private RichInputMethodManager() { 476fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // This utility class is not publicly instantiable. 486fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 496fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 506fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private static final RichInputMethodManager sInstance = new RichInputMethodManager(); 516fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 526fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private InputMethodManagerCompatWrapper mImmWrapper; 536fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private InputMethodInfo mInputMethodInfoOfThisIme; 54ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final HashMap<InputMethodInfo, List<InputMethodSubtype>> 55ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard mSubtypeListCacheWithImplicitlySelectedSubtypes = CollectionUtils.newHashMap(); 56ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final HashMap<InputMethodInfo, List<InputMethodSubtype>> 57ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard mSubtypeListCacheWithoutImplicitlySelectedSubtypes = CollectionUtils.newHashMap(); 586fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 5985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private static final int INDEX_NOT_FOUND = -1; 6085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 616fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public static RichInputMethodManager getInstance() { 626fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka sInstance.checkInitialized(); 636fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return sInstance; 646fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 656fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 66f90fc105ab1159f43f536bcacdd1224c2c05bacbTadashi G. Takaoka public static void init(final Context context) { 67f90fc105ab1159f43f536bcacdd1224c2c05bacbTadashi G. Takaoka final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 6885e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka sInstance.initInternal(context, prefs); 6985e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka } 7085e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka 7185e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka private boolean isInitialized() { 7285e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka return mImmWrapper != null; 736fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 746fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 756fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private void checkInitialized() { 7685e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka if (!isInitialized()) { 776fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka throw new RuntimeException(TAG + " is used before initialization"); 786fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 796fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 806fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 8185e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka private void initInternal(final Context context, final SharedPreferences prefs) { 8285e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka if (isInitialized()) { 8385e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka return; 8485e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka } 856fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka mImmWrapper = new InputMethodManagerCompatWrapper(context); 866fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka mInputMethodInfoOfThisIme = getInputMethodInfoOfThisIme(context); 8785e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka 8885e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka // Initialize additional subtypes. 89a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaoka SubtypeLocaleUtils.init(context); 90d3b0ecec22cda883150851dced32c1eda2910a66Tadashi G. Takaoka final String prefAdditionalSubtypes = Settings.readPrefAdditionalSubtypes( 9185e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka prefs, context.getResources()); 9285e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka final InputMethodSubtype[] additionalSubtypes = 93a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaoka AdditionalSubtypeUtils.createAdditionalSubtypesArray(prefAdditionalSubtypes); 9485e397cd1060f3878d9a55373b7409641175179aTadashi G. Takaoka setAdditionalInputMethodSubtypes(additionalSubtypes); 956fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 966fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 976fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public InputMethodManager getInputMethodManager() { 986fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka checkInitialized(); 996fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return mImmWrapper.mImm; 1006fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 1016fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 1026fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private InputMethodInfo getInputMethodInfoOfThisIme(final Context context) { 1036fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final String packageName = context.getPackageName(); 1046fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka for (final InputMethodInfo imi : mImmWrapper.mImm.getInputMethodList()) { 1056fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (imi.getPackageName().equals(packageName)) { 1066fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return imi; 1076fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 1086fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 1096fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka throw new RuntimeException("Input method id for " + packageName + " not found."); 1106fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 1116fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 112b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka public List<InputMethodSubtype> getMyEnabledInputMethodSubtypeList( 113b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka boolean allowsImplicitlySelectedSubtypes) { 114ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard return getEnabledInputMethodSubtypeList(mInputMethodInfoOfThisIme, 115ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard allowsImplicitlySelectedSubtypes); 116b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka } 117b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka 1186fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public boolean switchToNextInputMethod(final IBinder token, final boolean onlyCurrentIme) { 11985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (mImmWrapper.switchToNextInputMethod(token, onlyCurrentIme)) { 12085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return true; 12185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 12285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka // Was not able to call {@link InputMethodManager#switchToNextInputMethodIBinder,boolean)} 12385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka // because the current device is running ICS or previous and lacks the API. 12485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (switchToNextInputSubtypeInThisIme(token, onlyCurrentIme)) { 12585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return true; 12685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 12785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return switchToNextInputMethodAndSubtype(token); 12885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 12985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 13085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private boolean switchToNextInputSubtypeInThisIme(final IBinder token, 13185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final boolean onlyCurrentIme) { 13285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodManager imm = mImmWrapper.mImm; 13385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodSubtype currentSubtype = imm.getCurrentInputMethodSubtype(); 134b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka final List<InputMethodSubtype> enabledSubtypes = getMyEnabledInputMethodSubtypeList( 135b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka true /* allowsImplicitlySelectedSubtypes */); 13685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int currentIndex = getSubtypeIndexInList(currentSubtype, enabledSubtypes); 13785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (currentIndex == INDEX_NOT_FOUND) { 13885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka Log.w(TAG, "Can't find current subtype in enabled subtypes: subtype=" 139a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaoka + SubtypeLocaleUtils.getSubtypeNameForLogging(currentSubtype)); 1406fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return false; 1416fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 14285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int nextIndex = (currentIndex + 1) % enabledSubtypes.size(); 14385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (nextIndex <= currentIndex && !onlyCurrentIme) { 14485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka // The current subtype is the last or only enabled one and it needs to switch to 14585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka // next IME. 14685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return false; 14785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 14885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodSubtype nextSubtype = enabledSubtypes.get(nextIndex); 14985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka setInputMethodAndSubtype(token, nextSubtype); 15085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return true; 15185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 15285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 15385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private boolean switchToNextInputMethodAndSubtype(final IBinder token) { 15485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodManager imm = mImmWrapper.mImm; 15585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final List<InputMethodInfo> enabledImis = imm.getEnabledInputMethodList(); 15685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int currentIndex = getImiIndexInList(mInputMethodInfoOfThisIme, enabledImis); 15785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (currentIndex == INDEX_NOT_FOUND) { 15885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka Log.w(TAG, "Can't find current IME in enabled IMEs: IME package=" 15985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka + mInputMethodInfoOfThisIme.getPackageName()); 16085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return false; 16185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 16285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodInfo nextImi = getNextNonAuxiliaryIme(currentIndex, enabledImis); 163ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final List<InputMethodSubtype> enabledSubtypes = getEnabledInputMethodSubtypeList(nextImi, 164ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard true /* allowsImplicitlySelectedSubtypes */); 16585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (enabledSubtypes.isEmpty()) { 16685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka // The next IME has no subtype. 16785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka imm.setInputMethod(token, nextImi.getId()); 16885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return true; 16985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 17085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodSubtype firstSubtype = enabledSubtypes.get(0); 17185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka imm.setInputMethodAndSubtype(token, nextImi.getId(), firstSubtype); 17285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return true; 17385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 17485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 17585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private static int getImiIndexInList(final InputMethodInfo inputMethodInfo, 17685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final List<InputMethodInfo> imiList) { 17785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int count = imiList.size(); 17885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka for (int index = 0; index < count; index++) { 17985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodInfo imi = imiList.get(index); 18085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (imi.equals(inputMethodInfo)) { 18185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return index; 18285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 18385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 18485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return INDEX_NOT_FOUND; 18585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 18685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 18785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka // This method mimics {@link InputMethodManager#switchToNextInputMethod(IBinder,boolean)}. 18885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private static InputMethodInfo getNextNonAuxiliaryIme(final int currentIndex, 18985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final List<InputMethodInfo> imiList) { 19085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int count = imiList.size(); 19185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka for (int i = 1; i < count; i++) { 19285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int nextIndex = (currentIndex + i) % count; 19385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodInfo nextImi = imiList.get(nextIndex); 19485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (!isAuxiliaryIme(nextImi)) { 19585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return nextImi; 19685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 19785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 19885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return imiList.get(currentIndex); 19985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 20085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 20185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka // Copied from {@link InputMethodInfo}. See how auxiliary of IME is determined. 20285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private static boolean isAuxiliaryIme(final InputMethodInfo imi) { 20385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int count = imi.getSubtypeCount(); 20485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (count == 0) { 20585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return false; 20685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 20785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka for (int index = 0; index < count; index++) { 20885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodSubtype subtype = imi.getSubtypeAt(index); 20985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka if (!subtype.isAuxiliary()) { 21085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return false; 21185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 21285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 2136fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return true; 2146fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2156fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2166fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public InputMethodInfo getInputMethodInfoOfThisIme() { 2176fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return mInputMethodInfoOfThisIme; 2186fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2196fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2206fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public String getInputMethodIdOfThisIme() { 2216fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return mInputMethodInfoOfThisIme.getId(); 2226fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2236fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 22476d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka public boolean checkIfSubtypeBelongsToThisImeAndEnabled(final InputMethodSubtype subtype) { 22576d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka return checkIfSubtypeBelongsToImeAndEnabled(mInputMethodInfoOfThisIme, subtype); 22676d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka } 22776d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka 22876d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka public boolean checkIfSubtypeBelongsToThisImeAndImplicitlyEnabled( 22976d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka final InputMethodSubtype subtype) { 23076d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka final boolean subtypeEnabled = checkIfSubtypeBelongsToThisImeAndEnabled(subtype); 23176d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka final boolean subtypeExplicitlyEnabled = checkIfSubtypeBelongsToList( 232b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka subtype, getMyEnabledInputMethodSubtypeList( 233b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka false /* allowsImplicitlySelectedSubtypes */)); 23476d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka return subtypeEnabled && !subtypeExplicitlyEnabled; 2356fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2366fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2376fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public boolean checkIfSubtypeBelongsToImeAndEnabled(final InputMethodInfo imi, 23876d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka final InputMethodSubtype subtype) { 239ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard return checkIfSubtypeBelongsToList(subtype, getEnabledInputMethodSubtypeList(imi, 240ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard true /* allowsImplicitlySelectedSubtypes */)); 24176d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka } 24276d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka 24376d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka private static boolean checkIfSubtypeBelongsToList(final InputMethodSubtype subtype, 24476d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka final List<InputMethodSubtype> subtypes) { 24585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return getSubtypeIndexInList(subtype, subtypes) != INDEX_NOT_FOUND; 24685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 24785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 24885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private static int getSubtypeIndexInList(final InputMethodSubtype subtype, 24985629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final List<InputMethodSubtype> subtypes) { 25085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int count = subtypes.size(); 25185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka for (int index = 0; index < count; index++) { 25285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodSubtype ims = subtypes.get(index); 25376d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka if (ims.equals(subtype)) { 25485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return index; 2556fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2566fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 25785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return INDEX_NOT_FOUND; 2586fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2596fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 26076d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka public boolean checkIfSubtypeBelongsToThisIme(final InputMethodSubtype subtype) { 26185629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return getSubtypeIndexInIme(subtype, mInputMethodInfoOfThisIme) != INDEX_NOT_FOUND; 26285629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka } 26385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka 26485629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka private static int getSubtypeIndexInIme(final InputMethodSubtype subtype, 26585629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodInfo imi) { 26685629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final int count = imi.getSubtypeCount(); 26785629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka for (int index = 0; index < count; index++) { 26885629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka final InputMethodSubtype ims = imi.getSubtypeAt(index); 26976d4ffeebfd084913a8c1b7433dff48f5b2063dfTadashi G. Takaoka if (ims.equals(subtype)) { 27085629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return index; 2716fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2726fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 27385629debaaaa576047a4f01430411f0d7b41762dTadashi G. Takaoka return INDEX_NOT_FOUND; 2746fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2756fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2766fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public InputMethodSubtype getCurrentInputMethodSubtype( 2776fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final InputMethodSubtype defaultSubtype) { 2786fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final InputMethodSubtype currentSubtype = mImmWrapper.mImm.getCurrentInputMethodSubtype(); 2796fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return (currentSubtype != null) ? currentSubtype : defaultSubtype; 2806fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2816fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2826fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public boolean hasMultipleEnabledIMEsOrSubtypes(final boolean shouldIncludeAuxiliarySubtypes) { 2836fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final List<InputMethodInfo> enabledImis = mImmWrapper.mImm.getEnabledInputMethodList(); 2846fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, enabledImis); 2856fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2866fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2876fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public boolean hasMultipleEnabledSubtypesInThisIme( 2886fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final boolean shouldIncludeAuxiliarySubtypes) { 2896fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final List<InputMethodInfo> imiList = Collections.singletonList(mInputMethodInfoOfThisIme); 2906fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return hasMultipleEnabledSubtypes(shouldIncludeAuxiliarySubtypes, imiList); 2916fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 2926fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2936fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka private boolean hasMultipleEnabledSubtypes(final boolean shouldIncludeAuxiliarySubtypes, 2946fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final List<InputMethodInfo> imiList) { 2956fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // Number of the filtered IMEs 2966fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka int filteredImisCount = 0; 2976fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 2986fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka for (InputMethodInfo imi : imiList) { 2996fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // We can return true immediately after we find two or more filtered IMEs. 3006fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (filteredImisCount > 1) return true; 301ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final List<InputMethodSubtype> subtypes = getEnabledInputMethodSubtypeList(imi, true); 3026fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // IMEs that have no subtypes should be counted. 3036fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (subtypes.isEmpty()) { 3046fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka ++filteredImisCount; 3056fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka continue; 3066fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3076fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 3086fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka int auxCount = 0; 3096fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka for (InputMethodSubtype subtype : subtypes) { 3106fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (subtype.isAuxiliary()) { 3116fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka ++auxCount; 3126fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3136fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3146fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final int nonAuxCount = subtypes.size() - auxCount; 3156fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 3166fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // IMEs that have one or more non-auxiliary subtypes should be counted. 3176fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // If shouldIncludeAuxiliarySubtypes is true, IMEs that have two or more auxiliary 3186fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // subtypes should be counted as well. 3196fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (nonAuxCount > 0 || (shouldIncludeAuxiliarySubtypes && auxCount > 1)) { 3206fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka ++filteredImisCount; 3216fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka continue; 3226fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3236fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3246fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 3256fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (filteredImisCount > 1) { 3266fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return true; 3276fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 328b902109000bcef184e69daac7dc3906fc969791eSatoshi Kataoka final List<InputMethodSubtype> subtypes = getMyEnabledInputMethodSubtypeList(true); 3296fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka int keyboardCount = 0; 3306fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // imm.getEnabledInputMethodSubtypeList(null, true) will return the current IME's 3316fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // both explicitly and implicitly enabled input method subtype. 3326fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka // (The current IME should be LatinIME.) 3336fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka for (InputMethodSubtype subtype : subtypes) { 3346fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (KEYBOARD_MODE.equals(subtype.getMode())) { 3356fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka ++keyboardCount; 3366fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3376fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3386fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return keyboardCount > 1; 3396fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3406fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 3416fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public InputMethodSubtype findSubtypeByLocaleAndKeyboardLayoutSet(final String localeString, 3426fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final String keyboardLayoutSetName) { 3436fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final InputMethodInfo myImi = mInputMethodInfoOfThisIme; 3446fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final int count = myImi.getSubtypeCount(); 3456fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka for (int i = 0; i < count; i++) { 3466fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka final InputMethodSubtype subtype = myImi.getSubtypeAt(i); 347a410cb48eab0cd75aa27e20f60e47a29a59fb9ffTadashi G. Takaoka final String layoutName = SubtypeLocaleUtils.getKeyboardLayoutSetName(subtype); 3486fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka if (localeString.equals(subtype.getLocale()) 3496fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka && keyboardLayoutSetName.equals(layoutName)) { 3506fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return subtype; 3516fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3526fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3536fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka return null; 3546fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3556fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka 3561931c1cab1c2b077030210f2dd7a1839da7211bcTadashi G. Takaoka public void setInputMethodAndSubtype(final IBinder token, final InputMethodSubtype subtype) { 3571931c1cab1c2b077030210f2dd7a1839da7211bcTadashi G. Takaoka mImmWrapper.mImm.setInputMethodAndSubtype( 3581931c1cab1c2b077030210f2dd7a1839da7211bcTadashi G. Takaoka token, mInputMethodInfoOfThisIme.getId(), subtype); 3591931c1cab1c2b077030210f2dd7a1839da7211bcTadashi G. Takaoka } 3601931c1cab1c2b077030210f2dd7a1839da7211bcTadashi G. Takaoka 3616fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka public void setAdditionalInputMethodSubtypes(final InputMethodSubtype[] subtypes) { 3626fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka mImmWrapper.mImm.setAdditionalInputMethodSubtypes( 3636fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka mInputMethodInfoOfThisIme.getId(), subtypes); 364ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard // Clear the cache so that we go read the subtypes again next time. 365ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard clearSubtypeCaches(); 366ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard } 367ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard 368ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard private List<InputMethodSubtype> getEnabledInputMethodSubtypeList(final InputMethodInfo imi, 369ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final boolean allowsImplicitlySelectedSubtypes) { 370ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final HashMap<InputMethodInfo, List<InputMethodSubtype>> cache = 371ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard allowsImplicitlySelectedSubtypes 372ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard ? mSubtypeListCacheWithImplicitlySelectedSubtypes 373ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard : mSubtypeListCacheWithoutImplicitlySelectedSubtypes; 374ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final List<InputMethodSubtype> cachedList = cache.get(imi); 375ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard if (null != cachedList) return cachedList; 376ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard final List<InputMethodSubtype> result = mImmWrapper.mImm.getEnabledInputMethodSubtypeList( 377ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard imi, allowsImplicitlySelectedSubtypes); 378ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard cache.put(imi, result); 379ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard return result; 380ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard } 381ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard 382ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard public void clearSubtypeCaches() { 383ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard mSubtypeListCacheWithImplicitlySelectedSubtypes.clear(); 384ff6445ed0eac57f9daf573178ffe9f4e1e2b246aJean Chalard mSubtypeListCacheWithoutImplicitlySelectedSubtypes.clear(); 3856fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka } 3866fbbab3b8442ad010c53dc53a09535f7b0ef0323Tadashi G. Takaoka} 387