1d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka/* 2d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Copyright (C) 2013 The Android Open Source Project 3d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * 4d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Licensed under the Apache License, Version 2.0 (the "License"); 5d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * you may not use this file except in compliance with the License. 6d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * You may obtain a copy of the License at 7d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * 8d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * http://www.apache.org/licenses/LICENSE-2.0 9d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * 10d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * Unless required by applicable law or agreed to in writing, software 11d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * distributed under the License is distributed on an "AS IS" BASIS, 12d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * See the License for the specific language governing permissions and 14d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * limitations under the License. 15d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka */ 16d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 17d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokapackage com.android.internal.inputmethod; 18d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 19b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawaimport android.annotation.Nullable; 20d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport android.content.Context; 21d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport android.content.pm.PackageManager; 22d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport android.text.TextUtils; 239b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawaimport android.util.Log; 24d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawaimport android.util.Printer; 25d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokaimport android.util.Slog; 26d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokaimport android.view.inputmethod.InputMethodInfo; 27d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokaimport android.view.inputmethod.InputMethodSubtype; 28d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 294013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawaimport com.android.internal.annotations.VisibleForTesting; 304013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawaimport com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings; 314013940b62ae2227c9b30d8761d7533ee6190a9fYohei Yukawa 32d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.ArrayList; 33d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.Collections; 34d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.Comparator; 35d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.HashMap; 36d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.HashSet; 37d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.List; 38d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.Locale; 3907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawaimport java.util.Objects; 40d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport java.util.TreeMap; 41d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 42d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka/** 43d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka * InputMethodSubtypeSwitchingController controls the switching behavior of the subtypes. 445a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa * <p> 455a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa * This class is designed to be used from and only from {@link InputMethodManagerService} by using 465a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa * {@link InputMethodManagerService#mMethodMap} as a global lock. 475a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa * </p> 48d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka */ 49d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokapublic class InputMethodSubtypeSwitchingController { 50d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka private static final String TAG = InputMethodSubtypeSwitchingController.class.getSimpleName(); 51d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka private static final boolean DEBUG = false; 52d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID; 53d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 54d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public static class ImeSubtypeListItem implements Comparable<ImeSubtypeListItem> { 55d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public final CharSequence mImeName; 56d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public final CharSequence mSubtypeName; 57d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public final InputMethodInfo mImi; 58d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public final int mSubtypeId; 5971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa public final boolean mIsSystemLocale; 6071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa public final boolean mIsSystemLanguage; 61d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 62d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public ImeSubtypeListItem(CharSequence imeName, CharSequence subtypeName, 63d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka InputMethodInfo imi, int subtypeId, String subtypeLocale, String systemLocale) { 64d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mImeName = imeName; 65d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSubtypeName = subtypeName; 66d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mImi = imi; 67d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSubtypeId = subtypeId; 68d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (TextUtils.isEmpty(subtypeLocale)) { 69d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mIsSystemLocale = false; 70d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mIsSystemLanguage = false; 71d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } else { 72d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mIsSystemLocale = subtypeLocale.equals(systemLocale); 7371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa if (mIsSystemLocale) { 7471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa mIsSystemLanguage = true; 7571cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa } else { 7671cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa // TODO: Use Locale#getLanguage or Locale#toLanguageTag 7771cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa final String systemLanguage = parseLanguageFromLocaleString(systemLocale); 7871cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa final String subtypeLanguage = parseLanguageFromLocaleString(subtypeLocale); 7971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa mIsSystemLanguage = systemLanguage.length() >= 2 && 8071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa systemLanguage.equals(subtypeLanguage); 8171cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa } 8271cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa } 8371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa } 8471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa 8571cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa /** 8671cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa * Returns the language component of a given locale string. 8771cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa * TODO: Use {@link Locale#getLanguage()} instead. 8871cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa */ 8971cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa private static String parseLanguageFromLocaleString(final String locale) { 9071cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa final int idx = locale.indexOf('_'); 9171cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa if (idx < 0) { 9271cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa return locale; 9371cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa } else { 9471cf0a32d0d9a45653704a671154f26a8bc3132bYohei Yukawa return locale.substring(0, idx); 95d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 96d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 97d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 98d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka @Override 99d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public int compareTo(ImeSubtypeListItem other) { 100d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (TextUtils.isEmpty(mImeName)) { 101d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return 1; 102d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 103d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (TextUtils.isEmpty(other.mImeName)) { 104d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return -1; 105d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 106d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (!TextUtils.equals(mImeName, other.mImeName)) { 107d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return mImeName.toString().compareTo(other.mImeName.toString()); 108d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 109d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (TextUtils.equals(mSubtypeName, other.mSubtypeName)) { 110d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return 0; 111d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 112d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (mIsSystemLocale) { 113d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return -1; 114d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 115d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (other.mIsSystemLocale) { 116d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return 1; 117d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 118d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (mIsSystemLanguage) { 119d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return -1; 120d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 121d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (other.mIsSystemLanguage) { 122d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return 1; 123d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 124d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (TextUtils.isEmpty(mSubtypeName)) { 125d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return 1; 126d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 127d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (TextUtils.isEmpty(other.mSubtypeName)) { 128d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return -1; 129d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 130d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return mSubtypeName.toString().compareTo(other.mSubtypeName.toString()); 131d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 1321c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa 1331c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa @Override 1341c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa public String toString() { 1351c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa return "ImeSubtypeListItem{" 1361c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa + "mImeName=" + mImeName 1371c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa + " mSubtypeName=" + mSubtypeName 1381c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa + " mSubtypeId=" + mSubtypeId 1391c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa + " mIsSystemLocale=" + mIsSystemLocale 1401c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa + " mIsSystemLanguage=" + mIsSystemLanguage 1411c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa + "}"; 1421c63079b55cbb161ec6bed731a751943e6ac5736Yohei Yukawa } 14307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 14407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa @Override 14507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa public boolean equals(Object o) { 14607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (o == this) { 14707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return true; 14807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 14907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (o instanceof ImeSubtypeListItem) { 15007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa final ImeSubtypeListItem that = (ImeSubtypeListItem)o; 15107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (!Objects.equals(this.mImi, that.mImi)) { 15207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return false; 15307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 15407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (this.mSubtypeId != that.mSubtypeId) { 15507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return false; 15607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 15707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return true; 15807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 15907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return false; 16007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 161d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 162d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 163d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa private static class InputMethodAndSubtypeList { 164d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka private final Context mContext; 165d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // Used to load label 166d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka private final PackageManager mPm; 167d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka private final String mSystemLocaleStr; 168d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka private final InputMethodSettings mSettings; 169d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 170d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa public InputMethodAndSubtypeList(Context context, InputMethodSettings settings) { 171d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mContext = context; 172d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSettings = settings; 173d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mPm = context.getPackageManager(); 174d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka final Locale locale = context.getResources().getConfiguration().locale; 175d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSystemLocaleStr = locale != null ? locale.toString() : ""; 176d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 177d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 178d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka private final TreeMap<InputMethodInfo, List<InputMethodSubtype>> mSortedImmis = 1797025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawa new TreeMap<>( 180d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka new Comparator<InputMethodInfo>() { 181d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka @Override 182d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public int compare(InputMethodInfo imi1, InputMethodInfo imi2) { 183d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (imi2 == null) 184d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return 0; 185d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (imi1 == null) 186d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return 1; 187d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (mPm == null) { 188d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return imi1.getId().compareTo(imi2.getId()); 189d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 190d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka CharSequence imiId1 = imi1.loadLabel(mPm) + "/" + imi1.getId(); 191d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka CharSequence imiId2 = imi2.loadLabel(mPm) + "/" + imi2.getId(); 192d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return imiId1.toString().compareTo(imiId2.toString()); 193d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 194d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka }); 195d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 196d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeList( 1975f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa boolean includeAuxiliarySubtypes, boolean isScreenLocked) { 1987025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawa final ArrayList<ImeSubtypeListItem> imList = new ArrayList<>(); 199d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis = 200d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked( 201d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mContext); 202d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (immis == null || immis.size() == 0) { 203d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return Collections.emptyList(); 204d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 20514e139179be7daab6ed452105387a3922752c219Seigo Nonaka if (isScreenLocked && includeAuxiliarySubtypes) { 20614e139179be7daab6ed452105387a3922752c219Seigo Nonaka if (DEBUG) { 20714e139179be7daab6ed452105387a3922752c219Seigo Nonaka Slog.w(TAG, "Auxiliary subtypes are not allowed to be shown in lock screen."); 20814e139179be7daab6ed452105387a3922752c219Seigo Nonaka } 20914e139179be7daab6ed452105387a3922752c219Seigo Nonaka includeAuxiliarySubtypes = false; 21014e139179be7daab6ed452105387a3922752c219Seigo Nonaka } 211d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSortedImmis.clear(); 212d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSortedImmis.putAll(immis); 213d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka for (InputMethodInfo imi : mSortedImmis.keySet()) { 214d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (imi == null) { 215d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka continue; 216d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 217d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypeList = immis.get(imi); 2187025964d1230e4fc064658e1911fea9aab3def68Yohei Yukawa HashSet<String> enabledSubtypeSet = new HashSet<>(); 219d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka for (InputMethodSubtype subtype : explicitlyOrImplicitlyEnabledSubtypeList) { 220d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka enabledSubtypeSet.add(String.valueOf(subtype.hashCode())); 221d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 222d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka final CharSequence imeLabel = imi.loadLabel(mPm); 2235f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa if (enabledSubtypeSet.size() > 0) { 224d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka final int subtypeCount = imi.getSubtypeCount(); 225d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (DEBUG) { 226d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka Slog.v(TAG, "Add subtypes: " + subtypeCount + ", " + imi.getId()); 227d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 228d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka for (int j = 0; j < subtypeCount; ++j) { 229d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka final InputMethodSubtype subtype = imi.getSubtypeAt(j); 230d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka final String subtypeHashCode = String.valueOf(subtype.hashCode()); 231d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // We show all enabled IMEs and subtypes when an IME is shown. 232d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka if (enabledSubtypeSet.contains(subtypeHashCode) 23314e139179be7daab6ed452105387a3922752c219Seigo Nonaka && (includeAuxiliarySubtypes || !subtype.isAuxiliary())) { 234d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka final CharSequence subtypeLabel = 235d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka subtype.overridesImplicitlyEnabledSubtype() ? null : subtype 236d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka .getDisplayName(mContext, imi.getPackageName(), 237d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka imi.getServiceInfo().applicationInfo); 238d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka imList.add(new ImeSubtypeListItem(imeLabel, 239d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka subtypeLabel, imi, j, subtype.getLocale(), mSystemLocaleStr)); 240d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 241d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // Removing this subtype from enabledSubtypeSet because we no 242d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // longer need to add an entry of this subtype to imList to avoid 243d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka // duplicated entries. 244d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka enabledSubtypeSet.remove(subtypeHashCode); 245d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 246d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 247d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } else { 248d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka imList.add(new ImeSubtypeListItem(imeLabel, null, imi, NOT_A_SUBTYPE_ID, null, 249d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSystemLocaleStr)); 250d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 251d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 252d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka Collections.sort(imList); 253d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka return imList; 254d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 255d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 256d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 2579b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private static int calculateSubtypeId(InputMethodInfo imi, InputMethodSubtype subtype) { 2589b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return subtype != null ? InputMethodUtils.getSubtypeIdFromHashCode(imi, 2599b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa subtype.hashCode()) : NOT_A_SUBTYPE_ID; 2609b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 261d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa 2629b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private static class StaticRotationList { 2639b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private final List<ImeSubtypeListItem> mImeSubtypeList; 2649b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa public StaticRotationList(final List<ImeSubtypeListItem> imeSubtypeList) { 2659b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa mImeSubtypeList = imeSubtypeList; 266d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa } 2679b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 2689b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa /** 2699b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa * Returns the index of the specified input method and subtype in the given list. 2709b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa * @param imi The {@link InputMethodInfo} to be searched. 2719b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa * @param subtype The {@link InputMethodSubtype} to be searched. null if the input method 2729b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa * does not have a subtype. 2739b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa * @return The index in the given list. -1 if not found. 2749b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa */ 2759b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private int getIndex(InputMethodInfo imi, InputMethodSubtype subtype) { 2769b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final int currentSubtypeId = calculateSubtypeId(imi, subtype); 2779b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final int N = mImeSubtypeList.size(); 2789b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa for (int i = 0; i < N; ++i) { 2799b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final ImeSubtypeListItem isli = mImeSubtypeList.get(i); 2809b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa // Skip until the current IME/subtype is found. 2819b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (imi.equals(isli.mImi) && isli.mSubtypeId == currentSubtypeId) { 2829b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return i; 2839b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 2849b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 2859b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return -1; 286d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa } 2879b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 288b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa /** 289b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * Provides the basic operation to implement bi-directional IME rotation. 290b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param onlyCurrentIme {@code true} to limit the search space to IME subtypes that belong 291b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * to {@code imi}. 292b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param imi {@link InputMethodInfo} that will be used in conjunction with {@code subtype} 293b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * from which we find the adjacent IME subtype. 294b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param subtype {@link InputMethodSubtype} that will be used in conjunction with 295b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * {@code imi} from which we find the next IME subtype. {@code null} if the input method 296b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * does not have a subtype. 297b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param forward {@code true} to do forward search the next IME subtype. Specify 298b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * {@code false} to do backward search. 299b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @return The IME subtype found. {@code null} if no IME subtype is found. 300b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa */ 301b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa @Nullable 3029b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, 303b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa InputMethodInfo imi, @Nullable InputMethodSubtype subtype, boolean forward) { 3049b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (imi == null) { 3059b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return null; 306a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa } 3079b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (mImeSubtypeList.size() <= 1) { 3089b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return null; 3099b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 3109b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final int currentIndex = getIndex(imi, subtype); 3119b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (currentIndex < 0) { 3129b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return null; 3139b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 3149b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final int N = mImeSubtypeList.size(); 315d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa for (int i = 1; i < N; ++i) { 316b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa // Start searching the next IME/subtype from +/- 1 indices. 317d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa final int offset = forward ? i : N - i; 3189b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final int candidateIndex = (currentIndex + offset) % N; 3199b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final ImeSubtypeListItem candidate = mImeSubtypeList.get(candidateIndex); 320a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa // Skip if searching inside the current IME only, but the candidate is not 321a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa // the current IME. 3229b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (onlyCurrentIme && !imi.equals(candidate.mImi)) { 323a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa continue; 324d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa } 325a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa return candidate; 326d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa } 327a1223cfe6f2e04da1ab6e0ad781068687446ee56Yohei Yukawa return null; 328d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa } 329d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa 330d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa protected void dump(final Printer pw, final String prefix) { 331d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa final int N = mImeSubtypeList.size(); 332d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa for (int i = 0; i < N; ++i) { 333d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa final int rank = i; 334d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa final ImeSubtypeListItem item = mImeSubtypeList.get(i); 335d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa pw.println(prefix + "rank=" + rank + " item=" + item); 336d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 337d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 338d1da11529813f6d3f51518b5fe028e0b8084f5ccYohei Yukawa } 339d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 340a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa private static class DynamicRotationList { 341a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa private static final String TAG = DynamicRotationList.class.getSimpleName(); 342a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa private final List<ImeSubtypeListItem> mImeSubtypeList; 343a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa private final int[] mUsageHistoryOfSubtypeListItemIndex; 344a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 34507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa private DynamicRotationList(final List<ImeSubtypeListItem> imeSubtypeListItems) { 346a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mImeSubtypeList = imeSubtypeListItems; 347a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mUsageHistoryOfSubtypeListItemIndex = new int[mImeSubtypeList.size()]; 348a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int N = mImeSubtypeList.size(); 349a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa for (int i = 0; i < N; i++) { 350a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mUsageHistoryOfSubtypeListItemIndex[i] = i; 351a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 352a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 353a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 354a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa /** 355a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa * Returns the index of the specified object in 356a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa * {@link #mUsageHistoryOfSubtypeListItemIndex}. 357a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa * <p>We call the index of {@link #mUsageHistoryOfSubtypeListItemIndex} as "Usage Rank" 358a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa * so as not to be confused with the index in {@link #mImeSubtypeList}. 359a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa * @return -1 when the specified item doesn't belong to {@link #mImeSubtypeList} actually. 360a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa */ 361a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa private int getUsageRank(final InputMethodInfo imi, InputMethodSubtype subtype) { 362a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int currentSubtypeId = calculateSubtypeId(imi, subtype); 363a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int N = mUsageHistoryOfSubtypeListItemIndex.length; 364a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa for (int usageRank = 0; usageRank < N; usageRank++) { 365a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int subtypeListItemIndex = mUsageHistoryOfSubtypeListItemIndex[usageRank]; 366a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final ImeSubtypeListItem subtypeListItem = 367a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mImeSubtypeList.get(subtypeListItemIndex); 368a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (subtypeListItem.mImi.equals(imi) && 369a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa subtypeListItem.mSubtypeId == currentSubtypeId) { 370a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return usageRank; 371a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 372a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 373a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // Not found in the known IME/Subtype list. 374a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return -1; 375a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 376a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 377a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa public void onUserAction(InputMethodInfo imi, InputMethodSubtype subtype) { 378a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int currentUsageRank = getUsageRank(imi, subtype); 379a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa // Do nothing if currentUsageRank == -1 (not found), or currentUsageRank == 0 380a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (currentUsageRank <= 0) { 381a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return; 382a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 383a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int currentItemIndex = mUsageHistoryOfSubtypeListItemIndex[currentUsageRank]; 384a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa System.arraycopy(mUsageHistoryOfSubtypeListItemIndex, 0, 385a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mUsageHistoryOfSubtypeListItemIndex, 1, currentUsageRank); 386a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mUsageHistoryOfSubtypeListItemIndex[0] = currentItemIndex; 387a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 388a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 389b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa /** 390b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * Provides the basic operation to implement bi-directional IME rotation. 391b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param onlyCurrentIme {@code true} to limit the search space to IME subtypes that belong 392b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * to {@code imi}. 393b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param imi {@link InputMethodInfo} that will be used in conjunction with {@code subtype} 394b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * from which we find the adjacent IME subtype. 395b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param subtype {@link InputMethodSubtype} that will be used in conjunction with 396b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * {@code imi} from which we find the next IME subtype. {@code null} if the input method 397b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * does not have a subtype. 398b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param forward {@code true} to do forward search the next IME subtype. Specify 399b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * {@code false} to do backward search. 400b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @return The IME subtype found. {@code null} if no IME subtype is found. 401b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa */ 402b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa @Nullable 403a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, 404b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa InputMethodInfo imi, @Nullable InputMethodSubtype subtype, boolean forward) { 405a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa int currentUsageRank = getUsageRank(imi, subtype); 406a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (currentUsageRank < 0) { 407a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (DEBUG) { 408a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa Slog.d(TAG, "IME/subtype is not found: " + imi.getId() + ", " + subtype); 409a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 410a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return null; 411a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 412a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int N = mUsageHistoryOfSubtypeListItemIndex.length; 413a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa for (int i = 1; i < N; i++) { 414d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa final int offset = forward ? i : N - i; 415d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa final int subtypeListItemRank = (currentUsageRank + offset) % N; 416a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final int subtypeListItemIndex = 417a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mUsageHistoryOfSubtypeListItemIndex[subtypeListItemRank]; 418a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa final ImeSubtypeListItem subtypeListItem = 419a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mImeSubtypeList.get(subtypeListItemIndex); 420a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (onlyCurrentIme && !imi.equals(subtypeListItem.mImi)) { 421a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa continue; 422a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 423a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return subtypeListItem; 424a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 425a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return null; 426a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 427d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa 428d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa protected void dump(final Printer pw, final String prefix) { 429d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa for (int i = 0; i < mUsageHistoryOfSubtypeListItemIndex.length; ++i) { 430d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa final int rank = mUsageHistoryOfSubtypeListItemIndex[i]; 431d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa final ImeSubtypeListItem item = mImeSubtypeList.get(i); 432d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa pw.println(prefix + "rank=" + rank + " item=" + item); 433d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 434d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 435a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 436a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 4379b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa @VisibleForTesting 4389b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa public static class ControllerImpl { 43907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa private final DynamicRotationList mSwitchingAwareRotationList; 44007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa private final StaticRotationList mSwitchingUnawareRotationList; 44107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 44207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa public static ControllerImpl createFrom(final ControllerImpl currentInstance, 44307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa final List<ImeSubtypeListItem> sortedEnabledItems) { 44407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa DynamicRotationList switchingAwareRotationList = null; 44507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa { 44607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa final List<ImeSubtypeListItem> switchingAwareImeSubtypes = 44707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa filterImeSubtypeList(sortedEnabledItems, 44807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa true /* supportsSwitchingToNextInputMethod */); 44907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (currentInstance != null && 45007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa currentInstance.mSwitchingAwareRotationList != null && 45107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa Objects.equals(currentInstance.mSwitchingAwareRotationList.mImeSubtypeList, 45207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa switchingAwareImeSubtypes)) { 45307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa // Can reuse the current instance. 45407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa switchingAwareRotationList = currentInstance.mSwitchingAwareRotationList; 45507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 45607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (switchingAwareRotationList == null) { 45707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa switchingAwareRotationList = new DynamicRotationList(switchingAwareImeSubtypes); 45807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 45907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 46007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 46107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa StaticRotationList switchingUnawareRotationList = null; 46207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa { 46307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa final List<ImeSubtypeListItem> switchingUnawareImeSubtypes = filterImeSubtypeList( 46407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa sortedEnabledItems, false /* supportsSwitchingToNextInputMethod */); 46507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (currentInstance != null && 46607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa currentInstance.mSwitchingUnawareRotationList != null && 46707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa Objects.equals( 46807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa currentInstance.mSwitchingUnawareRotationList.mImeSubtypeList, 46907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa switchingUnawareImeSubtypes)) { 47007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa // Can reuse the current instance. 47107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa switchingUnawareRotationList = currentInstance.mSwitchingUnawareRotationList; 47207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 47307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (switchingUnawareRotationList == null) { 47407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa switchingUnawareRotationList = 47507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa new StaticRotationList(switchingUnawareImeSubtypes); 47607bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 47707bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 47807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 47907bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return new ControllerImpl(switchingAwareRotationList, switchingUnawareRotationList); 48007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 48107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa 48207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa private ControllerImpl(final DynamicRotationList switchingAwareRotationList, 48307bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa final StaticRotationList switchingUnawareRotationList) { 48407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mSwitchingAwareRotationList = switchingAwareRotationList; 48507bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mSwitchingUnawareRotationList = switchingUnawareRotationList; 4869b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 4879b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 488b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa /** 489b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * Provides the basic operation to implement bi-directional IME rotation. 490b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param onlyCurrentIme {@code true} to limit the search space to IME subtypes that belong 491b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * to {@code imi}. 492b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param imi {@link InputMethodInfo} that will be used in conjunction with {@code subtype} 493b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * from which we find the adjacent IME subtype. 494b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param subtype {@link InputMethodSubtype} that will be used in conjunction with 495b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * {@code imi} from which we find the next IME subtype. {@code null} if the input method 496b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * does not have a subtype. 497b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @param forward {@code true} to do forward search the next IME subtype. Specify 498b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * {@code false} to do backward search. 499b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa * @return The IME subtype found. {@code null} if no IME subtype is found. 500b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa */ 501b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa @Nullable 5029b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa public ImeSubtypeListItem getNextInputMethod(boolean onlyCurrentIme, InputMethodInfo imi, 503b1e2f4fc3a7b6676aa2c19f470338d6d57ff0ce6Yohei Yukawa @Nullable InputMethodSubtype subtype, boolean forward) { 5049b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (imi == null) { 5059b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return null; 5069b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5079b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (imi.supportsSwitchingToNextInputMethod()) { 50807bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return mSwitchingAwareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi, 509d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa subtype, forward); 5109b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } else { 51107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa return mSwitchingUnawareRotationList.getNextInputMethodLocked(onlyCurrentIme, imi, 512d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa subtype, forward); 5139b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5149b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5159b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 516a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) { 517a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (imi == null) { 518a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return; 519a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 52007bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa if (imi.supportsSwitchingToNextInputMethod()) { 52107bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mSwitchingAwareRotationList.onUserAction(imi, subtype); 52207bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa } 523a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 524a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa 5259b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private static List<ImeSubtypeListItem> filterImeSubtypeList( 5269b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final List<ImeSubtypeListItem> items, 5279b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final boolean supportsSwitchingToNextInputMethod) { 5289b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final ArrayList<ImeSubtypeListItem> result = new ArrayList<>(); 5299b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final int ALL_ITEMS_COUNT = items.size(); 5309b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa for (int i = 0; i < ALL_ITEMS_COUNT; i++) { 5319b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa final ImeSubtypeListItem item = items.get(i); 5329b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (item.mImi.supportsSwitchingToNextInputMethod() == 5339b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa supportsSwitchingToNextInputMethod) { 5349b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa result.add(item); 5359b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5369b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5379b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return result; 5389b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 539d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa 540d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa protected void dump(final Printer pw) { 541d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa pw.println(" mSwitchingAwareRotationList:"); 542d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa mSwitchingAwareRotationList.dump(pw, " "); 543d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa pw.println(" mSwitchingUnawareRotationList:"); 544d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa mSwitchingUnawareRotationList.dump(pw, " "); 545d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 5469b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5479b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5489b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private final InputMethodSettings mSettings; 5499b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private InputMethodAndSubtypeList mSubtypeList; 5509b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa private ControllerImpl mController; 5519b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa 5525a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa private InputMethodSubtypeSwitchingController(InputMethodSettings settings, Context context) { 553d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka mSettings = settings; 5545a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa resetCircularListLocked(context); 5555a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa } 5565a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa 5575a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa public static InputMethodSubtypeSwitchingController createInstanceLocked( 5585a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa InputMethodSettings settings, Context context) { 5595a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa return new InputMethodSubtypeSwitchingController(settings, context); 560d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 561d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka 5620297051162193ef2b7d906409868e404f77e4c31Yohei Yukawa public void onUserActionLocked(InputMethodInfo imi, InputMethodSubtype subtype) { 563a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (mController == null) { 564a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa if (DEBUG) { 565a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa Log.e(TAG, "mController shouldn't be null."); 566a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 567a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa return; 568a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa } 569a9bda774276f1c5a1fc6fd67a7782a06e696be8fYohei Yukawa mController.onUserActionLocked(imi, subtype); 570d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka } 571d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 572d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka public void resetCircularListLocked(Context context) { 5735a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa mSubtypeList = new InputMethodAndSubtypeList(context, mSettings); 57407bd732034fbf4ce0e51b99c7199edf20dff1565Yohei Yukawa mController = ControllerImpl.createFrom(mController, 575e512f85002379c5949f65daeffdcae3198964dadYohei Yukawa mSubtypeList.getSortedInputMethodAndSubtypeList( 576e512f85002379c5949f65daeffdcae3198964dadYohei Yukawa false /* includeAuxiliarySubtypes */, false /* isScreenLocked */)); 577d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 578d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 5799b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa public ImeSubtypeListItem getNextInputMethodLocked(boolean onlyCurrentIme, InputMethodInfo imi, 580d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa InputMethodSubtype subtype, boolean forward) { 5819b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (mController == null) { 5829b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa if (DEBUG) { 5839b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa Log.e(TAG, "mController shouldn't be null."); 5849b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 5859b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa return null; 5869b29d04565e1faf0a49054f538ed1881cb24fe12Yohei Yukawa } 587d39ae854820edebe3f1cb8580117c451ffa5c4ecYohei Yukawa return mController.getNextInputMethod(onlyCurrentIme, imi, subtype, forward); 588d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 589d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka 5905f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa public List<ImeSubtypeListItem> getSortedInputMethodAndSubtypeListLocked( 59114e139179be7daab6ed452105387a3922752c219Seigo Nonaka boolean includingAuxiliarySubtypes, boolean isScreenLocked) { 5925a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa return mSubtypeList.getSortedInputMethodAndSubtypeList( 5935f8e731f18c5cbfd345236c691db0b09aceb7c5dYohei Yukawa includingAuxiliarySubtypes, isScreenLocked); 594d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka } 595d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa 596d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa public void dump(final Printer pw) { 597d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa if (mController != null) { 598d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa mController.dump(pw); 599d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } else { 600d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa pw.println(" mController=null"); 601d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 602d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa } 603d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka} 604