InputMethodManagerService.java revision a07557471e43226fd23f6447c1e61177726524c9
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker *
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License at
6ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker *
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0
8ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker *
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * License for the specific language governing permissions and limitations under
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License.
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport com.android.internal.content.PackageMonitor;
19d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
20d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
218e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils;
228e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.os.HandlerCaller;
24758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganovimport com.android.internal.os.SomeArgs;
25e7c6998e0a953ae55487d4fe122739646f9280aasatokimport com.android.internal.util.FastXmlSerializer;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputContext;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethod;
2852a53526265c801b70eaf6dab1acf5c3f628f8a6Michael Wrightimport com.android.internal.view.IInputSessionCallback;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodClient;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodManager;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodSession;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.InputBindResult;
33ef2ea1faf6449f97a2423ecbdecce664c58bcbe1Adam Lesinskiimport com.android.server.statusbar.StatusBarManagerService;
3401038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport com.android.server.wm.WindowManagerService;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
36e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlPullParser;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
38e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlSerializer;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative;
414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.AppGlobals;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog;
434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.IUserSwitchObserver;
44f90a33e92a7c8d4040c0e660a62336eb7293d785satokimport android.app.KeyguardManager;
457cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.Notification;
467cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.NotificationManager;
47dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackbornimport android.app.PendingIntent;
485b927c431f54ea47c3333afb7940d79e2e863f1asatokimport android.content.BroadcastReceiver;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface.OnCancelListener;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
55e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.content.IntentFilter;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ServiceConnection;
576da35a0c1205398b7df4776e359f7794584fb128Brandon Ballingerimport android.content.pm.ApplicationInfo;
584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.content.pm.IPackageManager;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ResolveInfo;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ServiceInfo;
62734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.content.pm.UserInfo;
63e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasaniimport android.content.res.Configuration;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver;
67857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onoratoimport android.inputmethodservice.InputMethodService;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
69e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.os.Environment;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IInterface;
734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.IRemoteCallback;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.Process;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
784df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport android.os.ResultReceiver;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.UserHandle;
82734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.os.UserManager;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
85f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.text.style.SuggestionSpan;
8639606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
88f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.util.LruCache;
89ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.util.Pair;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
92e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Slog;
93e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Xml;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
95c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.view.InputChannel;
9605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.LayoutInflater;
9705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.View;
9805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.ViewGroup;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
100ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.EditorInfo;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputBinding;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethod;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodInfo;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
105ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.InputMethodSubtype;
10605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.ArrayAdapter;
10701038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton;
10801038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton.OnCheckedChangeListener;
10905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.RadioButton;
11001038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.Switch;
11105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.TextView;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
113e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.File;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
115e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileInputStream;
116e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileOutputStream;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
120688bd47fccf1a1373e6287bc49b5b33fad12b7f3satokimport java.util.Collections;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
1235b927c431f54ea47c3333afb7940d79e2e863f1asatokimport java.util.Locale;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides a system service that manages input methods.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InputMethodManagerService extends IInputMethodManager.Stub
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements ServiceConnection, Handler.Callback {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
1316ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    static final String TAG = "InputMethodManagerService";
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_IM_PICKER = 1;
134ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    static final int MSG_SHOW_IM_SUBTYPE_PICKER = 2;
13547a44916e2fb33cf4751906386d5f5c903b28d8bsatok    static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 3;
136217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    static final int MSG_SHOW_IM_CONFIG = 4;
137ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_INPUT = 1000;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_INPUT = 1010;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_SOFT_INPUT = 1020;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_HIDE_SOFT_INPUT = 1030;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_ATTACH_TOKEN = 1040;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_CREATE_SESSION = 1050;
144ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_START_INPUT = 2000;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_RESTART_INPUT = 2010;
147ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_METHOD = 3000;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_METHOD = 3010;
150a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn    static final int MSG_SET_ACTIVE = 3020;
151b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    static final int MSG_SET_CURSOR_ANCHOR_MONITOR_MODE = 3030;
152ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
15301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
15401038492ff0317f0d3cff54d8a7ee36bb31ff175satok
155bcacc322f83de1fe522081a20e0ac36ec8243763Satoshi Kataoka    static final long TIME_TO_RECONNECT = 3 * 1000;
156ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
157f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20;
158f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1598e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
160b6359414adabab2d64acc8ccc9e3b9c1b800b303satok    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
1618e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
1624e4569dab5c75804b01a19b2d6e6101b445c1c68satok
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Context mContext;
1647d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn    final Resources mRes;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Handler mHandler;
166d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final InputMethodSettings mSettings;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final SettingsObserver mSettingsObserver;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IWindowManager mIWindowManager;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HandlerCaller mCaller;
170119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final boolean mHasFeature;
1715ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private InputMethodFileManager mFileManager;
17201038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final HardKeyboardListener mHardKeyboardListener;
17301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final WindowManagerService mWindowManagerService;
174ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
175c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1);
176ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // All known input methods.  mMethodMap also serves as the global
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // lock for this class.
179d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
180d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
181f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
182f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
183d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    private final InputMethodSubtypeSwitchingController mSwitchingController;
184ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1852c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    // Used to bring IME service up to visible adjustment while it is being shown.
1862c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    final ServiceConnection mVisibleConnection = new ServiceConnection() {
1872c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceConnected(ComponentName name, IBinder service) {
1882c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1892c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1902c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceDisconnected(ComponentName name) {
1912c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1922c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    };
1932c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    boolean mVisibleBound = false;
1942c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1957cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    // Ongoing notification
196661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private NotificationManager mNotificationManager;
197661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private KeyguardManager mKeyguardManager;
198661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private StatusBarManagerService mStatusBar;
199661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private Notification mImeSwitcherNotification;
200661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private PendingIntent mImeSwitchPendingIntent;
201b858c732f665fe9610f2d913230ae625f44a8caasatok    private boolean mShowOngoingImeSwitcherForPhones;
2027cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean mNotificationShown;
2030a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok    private final boolean mImeSelectedOnBoot;
2047cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SessionState {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ClientState client;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethod method;
208c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
209c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        IInputMethodSession session;
210c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        InputChannel channel;
211ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "SessionState{uid " + client.uid + " pid " + client.pid
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " method " + Integer.toHexString(
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(method))
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " session " + Integer.toHexString(
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(session))
219c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    + " channel " + channel
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "}";
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState(ClientState _client, IInputMethod _method,
224c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                IInputMethodSession _session, InputChannel _channel) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = _method;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            session = _session;
228c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            channel = _channel;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
231ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
232c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    static final class ClientState {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethodClient client;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputContext inputContext;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int uid;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int pid;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final InputBinding binding;
238ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean sessionRequested;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState curSession;
241ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ClientState{" + Integer.toHexString(
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.identityHashCode(this)) + " uid " + uid
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " pid " + pid + "}";
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState(IInputMethodClient _client, IInputContext _inputContext,
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int _uid, int _pid) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inputContext = _inputContext;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uid = _uid;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pid = _pid;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
258ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, ClientState> mClients
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<IBinder, ClientState>();
261ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
263a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     * Set once the system is ready to run third party code.
264a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     */
265a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    boolean mSystemReady;
266ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
267a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    /**
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Id of the currently selected input method.
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurMethodId;
271ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The current binding sequence number, incremented every time there is
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new bind performed.
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCurSeq;
277ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The client that is currently bound to an input method.
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ClientState mCurClient;
282ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
284b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     * The last window token that gained focus.
285b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     */
286b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    IBinder mCurFocusedWindow;
287ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
288b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    /**
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input context last provided by the current client.
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputContext mCurInputContext;
292ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The attributes last provided by the current client.
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mCurAttribute;
297ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method ID of the input method service that we are currently
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * connected to or in the process of connecting to.
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurId;
303ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
305ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * The current subtype of the current input method.
306ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
307ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private InputMethodSubtype mCurrentSubtype;
308ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3094e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
310f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
311f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes =
312f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
313ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
314e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    // Was the keyguard locked when this client became current?
315e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean mCurClientInKeyguard;
316e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
317ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set to true if our ServiceConnection is currently actively bound to
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a service (whether or not we have gotten its IBinder back yet).
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mHaveConnection;
322ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if the client has asked for the input method to be shown.
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowRequested;
327ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were explicitly told to show the input method.
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowExplicitlyRequested;
332ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were forced to be shown.
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowForced;
337ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we last told the input method to show itself.
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputShown;
342ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The Intent used to connect to the current input method.
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Intent mCurIntent;
347ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The token we have made for the currently active input method, to
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * identify it in the future.
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mCurToken;
353ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If non-null, this is the input method service we are currently connected
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to.
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputMethod mCurMethod;
359ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time that we last initiated a bind to the input method, to determine
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if we should try to disconnect and reconnect to it.
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mLastBindTime;
365ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Have we called mCurMethod.bindInput()?
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mBoundToMethod;
370ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Currently enabled session.  Only touched by service thread, not
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * protected by a lock.
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SessionState mEnabledSession;
376ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * True if the screen is on.  The value is true initially.
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mScreenOn = true;
381ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
382857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
383857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mImeWindowVis;
384857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
38505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog.Builder mDialogBuilder;
38605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog mSwitchingDialog;
38701038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private View mSwitchingDialogTitleView;
38805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private InputMethodInfo[] mIms;
38905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private int[] mSubtypeIds;
3905b927c431f54ea47c3333afb7940d79e2e863f1asatok    private Locale mLastSystemLocale;
3914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
3924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final IPackageManager mIPackageManager;
393ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SettingsObserver extends ContentObserver {
395fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        String mLastEnabled = "";
396fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SettingsObserver(Handler handler) {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(handler);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver resolver = mContext.getContentResolver();
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resolver.registerContentObserver(Settings.Secure.getUriFor(
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
402ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            resolver.registerContentObserver(Settings.Secure.getUriFor(
403b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok                    Settings.Secure.ENABLED_INPUT_METHODS), false, this);
404b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok            resolver.registerContentObserver(Settings.Secure.getUriFor(
405ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
407ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void onChange(boolean selfChange) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
410fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                boolean enabledChanged = false;
411fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                String newEnabled = mSettings.getEnabledInputMethodsStr();
412fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                if (!mLastEnabled.equals(newEnabled)) {
413fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    mLastEnabled = newEnabled;
414fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    enabledChanged = true;
415fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
416fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                updateFromSettingsLocked(enabledChanged);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
420ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
4224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private void updateActive() {
4234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // Inform the current client of the change in active status
4244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (mCurClient != null && mCurClient.client != null) {
4254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
4264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
4274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
4324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String action = intent.getAction();
4334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (Intent.ACTION_SCREEN_ON.equals(action)) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = true;
4353afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                refreshImeWindowVisibilityLocked();
4364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = false;
44015452a487a4c0274f4217cd060aa54446f30a8f3satok                setImeWindowVisibilityStatusHiddenLocked();
4414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
444105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                hideInputMethodMenu();
4454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // No need to updateActive
446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                return;
447734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani            } else if (Intent.ACTION_USER_ADDED.equals(action)
448734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                    || Intent.ACTION_USER_REMOVED.equals(action)) {
4492a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                updateCurrentProfileIds();
450734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                return;
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unexpected intent " + intent);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
456ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
45721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
4584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private boolean isChangingPackagesOfCurrentUser() {
4594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final int userId = getChangingUserId();
4604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final boolean retval = userId == mSettings.getCurrentUserId();
4614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
46281f8b7c66750a0a89c8e6b6037136ca169c96f95satok                if (!retval) {
46381f8b7c66750a0a89c8e6b6037136ca169c96f95satok                    Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
46481f8b7c66750a0a89c8e6b6037136ca169c96f95satok                }
4654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return retval;
4674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
47021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
4714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
4724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return false;
4734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
47421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
4754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
47621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                final int N = mMethodList.size();
47721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curInputMethodId != null) {
47821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    for (int i=0; i<N; i++) {
47921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
48021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (imi.getId().equals(curInputMethodId)) {
48121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            for (String pkg : packages) {
48221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                if (imi.getPackageName().equals(pkg)) {
48321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    if (!doit) {
48421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        return true;
48521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    }
486723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                    resetSelectedInputMethodAndSubtypeLocked("");
48721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    chooseNewDefaultIMELocked();
48821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    return true;
48921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                }
49021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            }
49121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
49221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
49308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                }
49408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu            }
49521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return false;
49621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
497ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
49821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        @Override
49921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
5004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
5014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
5024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
50321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo curIm = null;
5054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int N = mMethodList.size();
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (curInputMethodId != null) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<N; i++) {
50921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
510e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imiId = imi.getId();
511e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (imiId.equals(curInputMethodId)) {
51221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            curIm = imi;
51321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
514e7c6998e0a953ae55487d4fe122739646f9280aasatok
51521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        int change = isPackageDisappearing(imi.getPackageName());
516e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (isPackageModified(imi.getPackageName())) {
517e7c6998e0a953ae55487d4fe122739646f9280aasatok                            mFileManager.deleteAllInputMethodSubtypes(imiId);
518e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
51921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (change == PACKAGE_TEMPORARY_CHANGE
52021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                || change == PACKAGE_PERMANENT_CHANGE) {
5218a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Input method uninstalled, disabling: "
52221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    + imi.getComponent());
52321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            setInputMethodEnabledLocked(imi.getId(), false);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
527ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
528f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(
529f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        mMethodList, mMethodMap, false /* resetDefaultEnabledIme */);
53021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed = false;
532ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
53308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                if (curIm != null) {
53421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    int change = isPackageDisappearing(curIm.getPackageName());
53521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (change == PACKAGE_TEMPORARY_CHANGE
53621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            || change == PACKAGE_PERMANENT_CHANGE) {
53708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        ServiceInfo si = null;
53808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        try {
5394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            si = mIPackageManager.getServiceInfo(
5404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    curIm.getComponent(), 0, mSettings.getCurrentUserId());
5414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        } catch (RemoteException ex) {
54208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
54308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (si == null) {
54408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Uh oh, current input method is no longer around!
54508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Pick another one...
5468a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
54715452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
54821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            if (!chooseNewDefaultIMELocked()) {
54908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                changed = true;
55008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                curIm = null;
5518a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.i(TAG, "Unsetting current input method");
552723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                resetSelectedInputMethodAndSubtypeLocked("");
55308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
55408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
55508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
55621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
557ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
55821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curIm == null) {
55921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // We currently don't have a default input method... is
56021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // one now available?
56121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    changed = chooseNewDefaultIMELocked();
56221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
563ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
56421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (changed) {
565fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(false);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
570ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
571c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private static final class MethodCallback extends IInputSessionCallback.Stub {
572e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard        private final InputMethodManagerService mParentIMMS;
573c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final IInputMethod mMethod;
574c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final InputChannel mChannel;
575ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
576c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        MethodCallback(InputMethodManagerService imms, IInputMethod method,
577c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel) {
578e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard            mParentIMMS = imms;
579c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mMethod = method;
580c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mChannel = channel;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
582ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
583e7c6998e0a953ae55487d4fe122739646f9280aasatok        @Override
584c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        public void sessionCreated(IInputMethodSession session) {
5856b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            long ident = Binder.clearCallingIdentity();
5866b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            try {
5876b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                mParentIMMS.onSessionCreated(mMethod, session, mChannel);
5886b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            } finally {
5896b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                Binder.restoreCallingIdentity(ident);
5906b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
593ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
59401038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private class HardKeyboardListener
59501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            implements WindowManagerService.OnHardKeyboardStatusChangeListener {
59601038492ff0317f0d3cff54d8a7ee36bb31ff175satok        @Override
59701038492ff0317f0d3cff54d8a7ee36bb31ff175satok        public void onHardKeyboardStatusChange(boolean available, boolean enabled) {
59801038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mHandler.sendMessage(mHandler.obtainMessage(
59901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0, enabled ? 1 : 0));
60001038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
60101038492ff0317f0d3cff54d8a7ee36bb31ff175satok
60201038492ff0317f0d3cff54d8a7ee36bb31ff175satok        public void handleHardKeyboardStatusChange(boolean available, boolean enabled) {
60301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            if (DEBUG) {
60401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                Slog.w(TAG, "HardKeyboardStatusChanged: available = " + available + ", enabled = "
60501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        + enabled);
60601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
60701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            synchronized(mMethodMap) {
60801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
60901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        && mSwitchingDialog.isShowing()) {
61001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mSwitchingDialogTitleView.findViewById(
61101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            com.android.internal.R.id.hard_keyboard_section).setVisibility(
61201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    available ? View.VISIBLE : View.GONE);
61301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
61401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
61501038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
61601038492ff0317f0d3cff54d8a7ee36bb31ff175satok    }
61701038492ff0317f0d3cff54d8a7ee36bb31ff175satok
61801038492ff0317f0d3cff54d8a7ee36bb31ff175satok    public InputMethodManagerService(Context context, WindowManagerService windowManager) {
6194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mIPackageManager = AppGlobals.getPackageManager();
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
6217d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn        mRes = context.getResources();
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new Handler(this);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIWindowManager = IWindowManager.Stub.asInterface(
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.WINDOW_SERVICE));
625ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
626e7c6998e0a953ae55487d4fe122739646f9280aasatok            @Override
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void executeMessage(Message msg) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleMessage(msg);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
630ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        }, true /*asyncHandler*/);
63101038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mWindowManagerService = windowManager;
63201038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mHardKeyboardListener = new HardKeyboardListener();
633119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        mHasFeature = context.getPackageManager().hasSystemFeature(
634119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                PackageManager.FEATURE_INPUT_METHODS);
6357cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6367cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification = new Notification();
6377cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
6387cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.when = 0;
6397cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT;
6407cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.tickerText = null;
6417cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.defaults = 0; // please be quiet
6427cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.sound = null;
6437cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.vibrate = null;
644590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
645590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler        // Tag this notification specially so SystemUI knows it's important
646fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
647fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.category = Notification.CATEGORY_SYSTEM;
648590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
6497cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
650683e2383c8549f95e00bade15daed3dbddf13950satok        mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
651b858c732f665fe9610f2d913230ae625f44a8caasatok
652b858c732f665fe9610f2d913230ae625f44a8caasatok        mShowOngoingImeSwitcherForPhones = false;
6537cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final IntentFilter broadcastFilter = new IntentFilter();
6554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
6564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
6574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
658734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
659734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
6604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
661ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
6627cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mNotificationShown = false;
6634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        int userId = 0;
6644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        try {
6654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            ActivityManagerNative.getDefault().registerUserSwitchObserver(
6664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    new IUserSwitchObserver.Stub() {
6674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
6695ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            synchronized(mMethodMap) {
6705ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                                switchUserLocked(newUserId);
6715ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            }
6724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            if (reply != null) {
6734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                try {
6744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    reply.sendResult(null);
6754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                } catch (RemoteException e) {
6764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                }
6774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            }
6784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
6794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
6804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
6824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
6834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    });
6844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
6854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } catch (RemoteException e) {
6864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
6874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
68881f8b7c66750a0a89c8e6b6037136ca169c96f95satok        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
689913a8925c07e854a80bf5df87561f290d3a56d61satok
690d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        // mSettings should be created before buildInputMethodListLocked
691df31ae6a3011d47421a6ac10021f9649dc34a156satok        mSettings = new InputMethodSettings(
6924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
6932a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
6945ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, userId);
6955a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
6965a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
6975a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSettings, context);
6985a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
6990a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
7000a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        // Just checking if defaultImiId is empty or not
7014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
702f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (DEBUG) {
703f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "Initial default ime = " + defaultImiId);
704f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
7050a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
7060a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
7075a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
7085a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            buildInputMethodListLocked(mMethodList, mMethodMap,
7095a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
7105a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
711d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        mSettings.enableAllIMEsIfThereIsNoEnabledIME();
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7130a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!mImeSelectedOnBoot) {
7140a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            Slog.w(TAG, "No IME selected. Choose the most applicable IME.");
7155a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            synchronized (mMethodMap) {
7165a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                resetDefaultImeLocked(context);
7175a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
7185b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7195b927c431f54ea47c3333afb7940d79e2e863f1asatok
7205b927c431f54ea47c3333afb7940d79e2e863f1asatok        mSettingsObserver = new SettingsObserver(mHandler);
7215a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
7225a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            updateFromSettingsLocked(true);
7235a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
7245b927c431f54ea47c3333afb7940d79e2e863f1asatok
7255b927c431f54ea47c3333afb7940d79e2e863f1asatok        // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
7265b927c431f54ea47c3333afb7940d79e2e863f1asatok        // according to the new system locale.
7275b927c431f54ea47c3333afb7940d79e2e863f1asatok        final IntentFilter filter = new IntentFilter();
7285b927c431f54ea47c3333afb7940d79e2e863f1asatok        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
7295b927c431f54ea47c3333afb7940d79e2e863f1asatok        mContext.registerReceiver(
7305b927c431f54ea47c3333afb7940d79e2e863f1asatok                new BroadcastReceiver() {
7315b927c431f54ea47c3333afb7940d79e2e863f1asatok                    @Override
7325b927c431f54ea47c3333afb7940d79e2e863f1asatok                    public void onReceive(Context context, Intent intent) {
7335b927c431f54ea47c3333afb7940d79e2e863f1asatok                        synchronized(mMethodMap) {
734ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            resetStateIfCurrentLocaleChangedLocked();
7359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
7369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7375b927c431f54ea47c3333afb7940d79e2e863f1asatok                }, filter);
7385b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7395b927c431f54ea47c3333afb7940d79e2e863f1asatok
7405b927c431f54ea47c3333afb7940d79e2e863f1asatok    private void resetDefaultImeLocked(Context context) {
7415b927c431f54ea47c3333afb7940d79e2e863f1asatok        // Do not reset the default (current) IME when it is a 3rd-party IME
7428e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        if (mCurMethodId != null
7438e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
7445b927c431f54ea47c3333afb7940d79e2e863f1asatok            return;
7455b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7465b927c431f54ea47c3333afb7940d79e2e863f1asatok
7475b927c431f54ea47c3333afb7940d79e2e863f1asatok        InputMethodInfo defIm = null;
7485b927c431f54ea47c3333afb7940d79e2e863f1asatok        for (InputMethodInfo imi : mMethodList) {
7495b927c431f54ea47c3333afb7940d79e2e863f1asatok            if (defIm == null) {
7508e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                if (InputMethodUtils.isValidSystemDefaultIme(
7518e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSystemReady, imi, context)) {
7525b927c431f54ea47c3333afb7940d79e2e863f1asatok                    defIm = imi;
7535b927c431f54ea47c3333afb7940d79e2e863f1asatok                    Slog.i(TAG, "Selected default: " + imi.getId());
7545b927c431f54ea47c3333afb7940d79e2e863f1asatok                }
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7565b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7575b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm == null && mMethodList.size() > 0) {
7588e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            defIm = InputMethodUtils.getMostApplicableDefaultIME(
7598e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
7605b927c431f54ea47c3333afb7940d79e2e863f1asatok            Slog.i(TAG, "No default found, using " + defIm.getId());
7615b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7625b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm != null) {
7635b927c431f54ea47c3333afb7940d79e2e863f1asatok            setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
7645b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7655b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7665b927c431f54ea47c3333afb7940d79e2e863f1asatok
7677f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka    private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
7687f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            final boolean resetDefaultEnabledIme) {
7694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!mSystemReady) {
7704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // not system ready
7714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
7724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
7734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final Locale newLocale = mRes.getConfiguration().locale;
7744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!updateOnlyWhenLocaleChanged
7754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
7764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                hideCurrentInputLocked(0, null);
7784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurMethodId = null;
7792ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
7804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
7814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
7824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.i(TAG, "Locale has been changed to " + newLocale);
7834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
7847f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            buildInputMethodListLocked(mMethodList, mMethodMap, resetDefaultEnabledIme);
7854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selectedImiId = mSettings.getSelectedInputMethod();
7874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (TextUtils.isEmpty(selectedImiId)) {
7884e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // This is the first time of the user switch and
7894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // set the current ime to the proper one.
7904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    resetDefaultImeLocked(mContext);
7914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
792d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka            } else {
793d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                // If the locale is changed, needs to reset the default ime
794d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                resetDefaultImeLocked(mContext);
7954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
796fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            updateFromSettingsLocked(true);
7974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            mLastSystemLocale = newLocale;
7984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                try {
8004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    startInputInnerLocked();
8014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } catch (RuntimeException e) {
8024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    Slog.w(TAG, "Unexpected exception", e);
8034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
8044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
8054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
8064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
808ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka    private void resetStateIfCurrentLocaleChangedLocked() {
8097f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */,
8107f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka                true /* resetDefaultImeLocked */);
8114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8135ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private void switchUserLocked(int newUserId) {
8144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mSettings.setCurrentUserId(newUserId);
8152a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
8165ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        // InputMethodFileManager should be reset when the user is changed
8175ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
8187f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
8197c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // For secondary users, the list of enabled IMEs may not have been updated since the
8207c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // callbacks to PackageMonitor are ignored for the secondary user. Here, defaultImiId may
8217c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // not be empty even if the IME has been uninstalled by the primary user.
8227c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // Even in such cases, IMMS works fine because it will find the most applicable
8237c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // IME for that user.
824ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
8257f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        if (DEBUG) {
8267f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId);
8277f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        }
8287f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(false  /* updateOnlyWhenLocaleChanged */,
829ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                initialUserSwitch /* needsToResetDefaultIme */);
830ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        if (initialUserSwitch) {
831ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka            InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(),
832ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
833ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        }
8344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8362a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy    void updateCurrentProfileIds() {
8372a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        List<UserInfo> profiles =
8382a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
8392a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
8402a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        for (int i = 0; i < currentProfileIds.length; i++) {
8412a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy            currentProfileIds[i] = profiles.get(i).id;
842734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        }
8432a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        mSettings.setCurrentProfileIds(currentProfileIds);
844734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani    }
845734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws RemoteException {
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.onTransact(code, data, reply, flags);
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The input method manager only throws security exceptions, so let's
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // log all others.
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!(e instanceof SecurityException)) {
855164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf(TAG, "Input Method Manager Crash", e);
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
861a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning(StatusBarManagerService statusBar) {
862a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        synchronized (mMethodMap) {
8634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
8644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "--- systemReady");
8654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
866a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            if (!mSystemReady) {
867a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn                mSystemReady = true;
8684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mKeyguardManager =
8694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
870661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mNotificationManager = (NotificationManager)
871661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
872661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mStatusBar = statusBar;
873661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                statusBar.setIconVisibility("ime", false);
874661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                updateImeWindowStatusLocked();
875b858c732f665fe9610f2d913230ae625f44a8caasatok                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
876b858c732f665fe9610f2d913230ae625f44a8caasatok                        com.android.internal.R.bool.show_ongoing_ime_switcher);
87701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mShowOngoingImeSwitcherForPhones) {
87801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mWindowManagerService.setOnHardKeyboardStatusChangeListener(
87901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mHardKeyboardListener);
88001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
881f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(mMethodList, mMethodMap,
882f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
8830a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (!mImeSelectedOnBoot) {
8840a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                    Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
885ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    resetStateIfCurrentLocaleChangedLocked();
886ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
887ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mContext.getPackageManager(),
888ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mSettings.getEnabledInputMethodListLocked());
8890a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
8900a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                mLastSystemLocale = mRes.getConfiguration().locale;
891cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                try {
892cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    startInputInnerLocked();
893cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                } catch (RuntimeException e) {
8948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Unexpected exception", e);
895cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
896a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            }
897a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
899ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
90015452a487a4c0274f4217cd060aa54446f30a8f3satok    private void setImeWindowVisibilityStatusHiddenLocked() {
90115452a487a4c0274f4217cd060aa54446f30a8f3satok        mImeWindowVis = 0;
90215452a487a4c0274f4217cd060aa54446f30a8f3satok        updateImeWindowStatusLocked();
90315452a487a4c0274f4217cd060aa54446f30a8f3satok    }
90415452a487a4c0274f4217cd060aa54446f30a8f3satok
9053afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    private void refreshImeWindowVisibilityLocked() {
9063afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final Configuration conf = mRes.getConfiguration();
9073afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean haveHardKeyboard = conf.keyboard
9083afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                != Configuration.KEYBOARD_NOKEYS;
9093afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean hardKeyShown = haveHardKeyboard
9103afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                && conf.hardKeyboardHidden
9113afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                        != Configuration.HARDKEYBOARDHIDDEN_YES;
912e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
913e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean isScreenLocked = isKeyguardLocked();
914e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean inputActive = !isScreenLocked && (mInputShown || hardKeyShown);
91536439b43121751ae94e703da52b2763aa17d0720John Spurlock        // We assume the softkeyboard is shown when the input is active as long as the
91636439b43121751ae94e703da52b2763aa17d0720John Spurlock        // hard keyboard is not shown.
91736439b43121751ae94e703da52b2763aa17d0720John Spurlock        final boolean inputVisible = inputActive && !hardKeyShown;
91836439b43121751ae94e703da52b2763aa17d0720John Spurlock        mImeWindowVis = (inputActive ? InputMethodService.IME_ACTIVE : 0)
91936439b43121751ae94e703da52b2763aa17d0720John Spurlock                | (inputVisible ? InputMethodService.IME_VISIBLE : 0);
9203afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        updateImeWindowStatusLocked();
9213afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    }
9223afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok
92315452a487a4c0274f4217cd060aa54446f30a8f3satok    private void updateImeWindowStatusLocked() {
924dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok        setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
925661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    }
926661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn
9274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // ---------------------------------------------------------------------------------------
9284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
9294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 1) it comes from the system process
9304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 2) the calling process' user id is identical to the current user id IMMS thinks.
9314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean calledFromValidUser() {
9324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int uid = Binder.getCallingUid();
9334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int userId = UserHandle.getUserId(uid);
9344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
9354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
9364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
9374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + " calling userId = " + userId + ", foreground user id = "
93887c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
93987c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + InputMethodUtils.getApiCallStack());
9404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9412a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
9424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return true;
9434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
944135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka
945135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
946135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // foreground user, not for the user of that process. Accordingly InputMethodManagerService
947135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // must not manage background users' states in any functions.
948135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Note that privacy-sensitive IPCs, such as setInputMethod, are still securely guarded
949135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // by a token.
950135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        if (mContext.checkCallingOrSelfPermission(
951135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
952135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        == PackageManager.PERMISSION_GRANTED) {
953135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            if (DEBUG) {
954135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                Slog.d(TAG, "--- Access granted because the calling process has "
955135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        + "the INTERACT_ACROSS_USERS_FULL permission");
956135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            }
957135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            return true;
958135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        }
9590766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka        Slog.w(TAG, "--- IPC called from background users. Ignore. \n"
9600766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                + InputMethodUtils.getStackTrace());
961135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        return false;
9624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
96422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
96522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    /**
96622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * Returns true iff the caller is identified to be the current input method with the token.
96722c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @param token The window token given to the input method when it was started.
96822c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @return true if and only if non-null valid token is specified.
96922c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     */
97022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    private boolean calledWithValidToken(IBinder token) {
97122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        if (token == null || mCurToken != token) {
97222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            return false;
97322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        }
97422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        return true;
97522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    }
97622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
9774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean bindCurrentInputMethodService(
9784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Intent service, ServiceConnection conn, int flags) {
9794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (service == null || conn == null) {
9804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
9814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
9824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
98327b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani        return mContext.bindServiceAsUser(service, conn, flags,
98427b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                new UserHandle(mSettings.getCurrentUserId()));
9854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
987e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getInputMethodList() {
9894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
9904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
9914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
9924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ArrayList<InputMethodInfo>(mMethodList);
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
998e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getEnabledInputMethodList() {
10004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
10014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
10034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1005d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return mSettings.getEnabledInputMethodListLocked();
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10098e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    /**
1010b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka     * @param imiId if null, returns enabled subtypes for the current imi
10118e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     * @return enabled subtypes of the specified imi
10128e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     */
1013e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1014b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
101516331c8a1d33defccc5cbb18694def79196c921bsatok            boolean allowsImplicitlySelectedSubtypes) {
10164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
10174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
1018b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            return Collections.<InputMethodSubtype>emptyList();
10194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
102067ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        synchronized (mMethodMap) {
1021b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            final InputMethodInfo imi;
1022b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imiId == null && mCurMethodId != null) {
10238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                imi = mMethodMap.get(mCurMethodId);
1024b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            } else {
1025b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                imi = mMethodMap.get(imiId);
1026b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            }
1027b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imi == null) {
1028b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                return Collections.<InputMethodSubtype>emptyList();
10298e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            }
10308e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            return mSettings.getEnabledInputMethodSubtypeListLocked(
10318e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mContext, imi, allowsImplicitlySelectedSubtypes);
103267ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        }
103367ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok    }
103467ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok
1035e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addClient(IInputMethodClient client,
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IInputContext inputContext, int uid, int pid) {
10384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClients.put(client.asBinder(), new ClientState(client,
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    inputContext, uid, pid));
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1046ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1047e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeClient(IInputMethodClient client) {
10494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1053c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ClientState cs = mClients.remove(client.asBinder());
1054c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (cs != null) {
1055c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
1056c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1059ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void executeOrSendMessage(IInterface target, Message msg) {
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         if (target.asBinder() instanceof Binder) {
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             mCaller.sendMessage(msg);
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         } else {
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             handleMessage(msg);
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             msg.recycle();
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         }
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1068ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1069b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void unbindCurrentClientLocked() {
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != null) {
10718a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client = "
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurClient.client.asBinder());
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBoundToMethod) {
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBoundToMethod = false;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_INPUT, mCurMethod));
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1080a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn
1081a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1082a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    MSG_SET_ACTIVE, 0, mCurClient));
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient.sessionRequested = false;
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient = null;
1087ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1088105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1091ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getImeShowFlags() {
10939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_FORCED
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    | InputMethod.SHOW_EXPLICIT;
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mShowExplicitlyRequested) {
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_EXPLICIT;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1102ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getAppShowFlags() {
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_FORCED;
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mShowExplicitlyRequested) {
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_IMPLICIT;
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1112ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11137663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult attachNewInputLocked(boolean initial) {
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBoundToMethod) {
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBoundToMethod = true;
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SessionState session = mCurClient.curSession;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initial) {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_START_INPUT, session, mCurInputContext, mCurAttribute));
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_RESTART_INPUT, session, mCurInputContext, mCurAttribute));
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowRequested) {
11288a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
11294df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            showCurrentInputLocked(getAppShowFlags(), null);
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11311951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown        return new InputBindResult(session.session,
11321951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                session.channel != null ? session.channel.dup() : null, mCurId, mCurSeq);
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1134ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBindResult startInputLocked(IInputMethodClient client,
11367663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If no method is currently selected, do nothing.
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethodId == null) {
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNoBinding;
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1141ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState cs = mClients.get(client.asBinder());
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cs == null) {
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("unknown client "
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + client.asBinder());
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1147ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check with the window manager to make sure this client actually
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // has a window with focus.  If not, reject.  This is thread safe
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // because if the focus changes some time before or after, the
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // next client receiving focus that has any interest in input will
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // be calling through here after that change happens.
11558a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Starting input on non-focused client " + cs.client
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1161ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11627663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
11637663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    }
11647663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11657663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult startInputUncheckedLocked(ClientState cs,
11667663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11677663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        // If no method is currently selected, do nothing.
11687663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        if (mCurMethodId == null) {
11697663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            return mNoBinding;
11707663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        }
11717663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != cs) {
1173e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            // Was the keyguard locked when switching over to the new client?
1174e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            mCurClientInKeyguard = isKeyguardLocked();
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the client is changing, we need to switch over to the new
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // one.
1177b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
11788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "switching to client: client = "
1179e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the screen is on, inform the new client it is active
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mScreenOn) {
1183a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                executeOrSendMessage(cs.client, mCaller.obtainMessageIO(
1184a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, cs));
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1187ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Bump up the sequence for this client and attach it.
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurSeq++;
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurSeq <= 0) mCurSeq = 1;
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurClient = cs;
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurInputContext = inputContext;
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurAttribute = attribute;
1194ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check if the input method is changing.
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurId != null && mCurId.equals(mCurMethodId)) {
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cs.curSession != null) {
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Fast case: if we are already connected to the input method,
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // then just return it.
12007663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return attachNewInputLocked(
12017663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mHaveConnection) {
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Return to client, and we will get back with it when
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we have had a session made for it.
1207c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(cs);
1208c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return new InputBindResult(null, null, mCurId, mCurSeq);
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (SystemClock.uptimeMillis()
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        < (mLastBindTime+TIME_TO_RECONNECT)) {
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // In this case we have connected to the service, but
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // don't yet have its interface.  If it hasn't been too
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // long since we did the connection, we'll return to
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the client and wait to get the service interface so
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we can report back.  If it has been too long, we want
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to fall through so we can try a disconnect/reconnect
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to see if we can get back in touch with the service.
1218c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return new InputBindResult(null, null, mCurId, mCurSeq);
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1220ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                    EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
1221ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                            mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1225ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1226a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        return startInputInnerLocked();
1227a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    }
1228ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1229a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    InputBindResult startInputInnerLocked() {
1230a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (mCurMethodId == null) {
1231a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            return mNoBinding;
1232a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1233ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1234a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (!mSystemReady) {
1235a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // If the system is not yet ready, we shouldn't be running third
1236a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // party code.
1237c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return new InputBindResult(null, null, mCurMethodId, mCurSeq);
1238a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1239ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(mCurMethodId);
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1244ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12452ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn        unbindCurrentMethodLocked(false, true);
1246ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent.setComponent(info.getComponent());
1249dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1250dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                com.android.internal.R.string.input_method_binding_label);
1251dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1252dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
12534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
1254f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND
1255f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_SHOWING_UI)) {
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastBindTime = SystemClock.uptimeMillis();
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHaveConnection = true;
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurId = info.getId();
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurToken = new Binder();
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
1261ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIWindowManager.addWindowToken(mCurToken,
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1266c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return new InputBindResult(null, null, mCurId, mCurSeq);
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIntent = null;
12698a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Failure connecting to input method service: "
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurIntent);
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1274ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1275e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBindResult startInput(IInputMethodClient client,
12777663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
12784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
12794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
12804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final long ident = Binder.clearCallingIdentity();
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
12847663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return startInputLocked(client, inputContext, attribute, controlFlags);
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1290ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1291e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishInput(IInputMethodClient client) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1294ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1295e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceConnected(ComponentName name, IBinder service) {
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCurMethod = IInputMethod.Stub.asInterface(service);
1300cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                if (mCurToken == null) {
13018a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Service connected without a token!");
13022ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                    unbindCurrentMethodLocked(false, false);
1303cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    return;
1304cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1305e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
1306cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
1307cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1309c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
1310c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(mCurClient);
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1316c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void onSessionCreated(IInputMethod method, IInputMethodSession session,
1317c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel channel) {
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && method != null
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && mCurMethod.asBinder() == method.asBinder()) {
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1322c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
13239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCurClient.curSession = new SessionState(mCurClient,
1324c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                            method, session, channel);
13257663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    InputBindResult res = attachNewInputLocked(true);
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (res.method != null) {
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                MSG_BIND_METHOD, mCurClient.client, res));
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1330c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return;
13319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1334c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1335c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        // Session abandoned.  Close its associated input channel.
1336c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        channel.dispose();
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1338ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13392ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn    void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
13402c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mVisibleBound) {
13412c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
13422c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
13432c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
13442c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1345b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mHaveConnection) {
1346b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mContext.unbindService(this);
1347b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mHaveConnection = false;
1348b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1349ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1350b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mCurToken != null) {
1351b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            try {
13528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
13532ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
1354e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    // The current IME is shown. Hence an IME switch (transition) is happening.
1355e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    mWindowManagerService.saveLastInputMethodWindowForTransition();
1356e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                }
1357b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mIWindowManager.removeWindowToken(mCurToken);
1358b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            } catch (RemoteException e) {
1359b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
1360b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mCurToken = null;
1361b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1362ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1363105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mCurId = null;
1364b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        clearCurMethodLocked();
1365ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1366b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (reportToClient && mCurClient != null) {
1367b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1368b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
1369b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1370b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    }
1371c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1372c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void requestClientSessionLocked(ClientState cs) {
1373c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (!cs.sessionRequested) {
1374c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
1375c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
1376c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            cs.sessionRequested = true;
1377c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
1378c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    MSG_CREATE_SESSION, mCurMethod, channels[1],
1379c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    new MethodCallback(this, mCurMethod, channels[0])));
1380c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
1381c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1382c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1383c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void clearClientSessionLocked(ClientState cs) {
1384c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        finishSessionLocked(cs.curSession);
1385c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.curSession = null;
1386c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.sessionRequested = false;
1387c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1388c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1389c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private void finishSessionLocked(SessionState sessionState) {
1390c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (sessionState != null) {
1391c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.session != null) {
1392c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                try {
1393c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    sessionState.session.finishSession();
1394c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } catch (RemoteException e) {
1395c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    Slog.w(TAG, "Session failed to close due to remote exception", e);
1396c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    setImeWindowVisibilityStatusHiddenLocked();
1397c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
1398c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.session = null;
1399c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
1400c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.channel != null) {
1401c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel.dispose();
1402c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel = null;
14030c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            }
14040c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor        }
14050c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor    }
1406ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1407b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void clearCurMethodLocked() {
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState cs : mClients.values()) {
1410c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14120c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor
1413c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            finishSessionLocked(mEnabledSession);
14140c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            mEnabledSession = null;
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurMethod = null;
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1417661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        if (mStatusBar != null) {
1418661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn            mStatusBar.setIconVisibility("ime", false);
1419661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        }
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1421ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1422e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceDisconnected(ComponentName name) {
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14258a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mCurIntent=" + mCurIntent);
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && mCurIntent != null
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && name.equals(mCurIntent.getComponent())) {
1429b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                clearCurMethodLocked();
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We consider this to be a new bind attempt, since the system
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // should now try to restart the service for us.
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastBindTime = SystemClock.uptimeMillis();
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mShowRequested = mInputShown;
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputShown = false;
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1443f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
1448a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                if (!calledWithValidToken(token)) {
1449a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    final int uid = Binder.getCallingUid();
1450a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    Slog.e(TAG, "Ignoring updateStatusIcon due to an invalid token. uid:" + uid
1451a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                            + " token:" + token);
1452a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    return;
1453a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                }
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (iconId == 0) {
14558a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
1456661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1457661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", false);
1458661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (packageName != null) {
14608a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
14616179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    CharSequence contentDescription = null;
14626179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    try {
14634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        // Use PackageManager to load label
14644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        final PackageManager packageManager = mContext.getPackageManager();
14656179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        contentDescription = packageManager.getApplicationLabel(
14664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mIPackageManager.getApplicationInfo(packageName, 0,
14674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                        mSettings.getCurrentUserId()));
14684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    } catch (RemoteException e) {
14696179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        /* ignore */
14706179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    }
1471661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1472661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIcon("ime", packageName, iconId, 0,
1473661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                contentDescription  != null
1474661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                        ? contentDescription.toString() : null);
1475661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", true);
1476661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14847cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean needsToShowImeSwitchOngoingNotification() {
14857cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        if (!mShowOngoingImeSwitcherForPhones) return false;
1486807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk        if (mSwitchingDialog != null) return false;
14872c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        if (isScreenLocked()) return false;
14887cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        synchronized (mMethodMap) {
14897cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
14907cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            final int N = imis.size();
1491b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N > 2) return true;
1492b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N < 1) return false;
1493b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int nonAuxCount = 0;
1494b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int auxCount = 0;
1495b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype nonAuxSubtype = null;
1496b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype auxSubtype = null;
14977cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            for(int i = 0; i < N; ++i) {
14987cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final InputMethodInfo imi = imis.get(i);
14998e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final List<InputMethodSubtype> subtypes =
15008e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
15017cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final int subtypeCount = subtypes.size();
15027cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                if (subtypeCount == 0) {
1503b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    ++nonAuxCount;
15047cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
15057cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    for (int j = 0; j < subtypeCount; ++j) {
1506b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        final InputMethodSubtype subtype = subtypes.get(j);
1507b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        if (!subtype.isAuxiliary()) {
1508b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++nonAuxCount;
1509b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            nonAuxSubtype = subtype;
1510b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        } else {
1511b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++auxCount;
1512b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            auxSubtype = subtype;
15137cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        }
15147cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
15157cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
15167cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            }
1517b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (nonAuxCount > 1 || auxCount > 1) {
1518b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1519b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            } else if (nonAuxCount == 1 && auxCount == 1) {
1520b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                if (nonAuxSubtype != null && auxSubtype != null
15219747f8977c55013e656a1e666a1647bb331954cesatok                        && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
15229747f8977c55013e656a1e666a1647bb331954cesatok                                || auxSubtype.overridesImplicitlyEnabledSubtype()
15239747f8977c55013e656a1e666a1647bb331954cesatok                                || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
1524b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
1525b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    return false;
1526b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                }
1527b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1528b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            }
1529b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            return false;
15307cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        }
15317cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    }
15327cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
1533e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean isKeyguardLocked() {
1534e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
1535e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    }
1536e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
15374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Caution! This method is called in this class. Handle multi-user carefully
1538dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("deprecation")
1539f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
1540857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
15414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final long ident = Binder.clearCallingIdentity();
154206487a58be22b100daf3f950b9a1d25c3ea42aa2satok        try {
154322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
154422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
154522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring setImeWindowStatus due to an invalid token. uid:" + uid
154622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + " token:" + token);
154706487a58be22b100daf3f950b9a1d25c3ea42aa2satok                return;
154806487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
154906487a58be22b100daf3f950b9a1d25c3ea42aa2satok            synchronized (mMethodMap) {
1550e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                // apply policy for binder calls
1551e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
1552e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    vis = 0;
1553e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                }
1554857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mImeWindowVis = vis;
1555857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mBackDisposition = backDisposition;
1556217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                final boolean iconVisibility = ((vis & (InputMethodService.IME_ACTIVE)) != 0)
1557217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                        && (mWindowManagerService.isHardKeyboardAvailable()
1558217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                                || (vis & (InputMethodService.IME_VISIBLE)) != 0);
1559b605fecd9e4282823af754b3968b21205d64554aJason Monk                final boolean needsToShowImeSwitcher = iconVisibility
1560b605fecd9e4282823af754b3968b21205d64554aJason Monk                        && needsToShowImeSwitchOngoingNotification();
1561b605fecd9e4282823af754b3968b21205d64554aJason Monk                if (mStatusBar != null) {
1562b605fecd9e4282823af754b3968b21205d64554aJason Monk                    mStatusBar.setImeWindowStatus(token, vis, backDisposition,
1563b605fecd9e4282823af754b3968b21205d64554aJason Monk                            needsToShowImeSwitcher);
1564b605fecd9e4282823af754b3968b21205d64554aJason Monk                }
15655bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
1566b605fecd9e4282823af754b3968b21205d64554aJason Monk                if (imi != null && needsToShowImeSwitcher) {
15674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // Used to load label
15687cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    final CharSequence title = mRes.getText(
15697cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                            com.android.internal.R.string.select_input_method);
1570b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                    final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
1571b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            mContext, imi, mCurrentSubtype);
15725bc8e732bd831a308a5bc1720b0e4c9300d32f67satok
15737cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    mImeSwitcherNotification.setLatestEventInfo(
15745bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                            mContext, title, summary, mImeSwitchPendingIntent);
1575e463c745ef6901121837e88ca8597d062843b9ddJason Monk                    if ((mNotificationManager != null)
1576e463c745ef6901121837e88ca8597d062843b9ddJason Monk                            && !mWindowManagerService.hasNavigationBar()) {
1577135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1578b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            Slog.d(TAG, "--- show notification: label =  " + summary);
1579135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1580135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.notifyAsUser(null,
1581661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                com.android.internal.R.string.select_input_method,
1582135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                mImeSwitcherNotification, UserHandle.ALL);
1583661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mNotificationShown = true;
1584661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
15857cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
1586661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mNotificationShown && mNotificationManager != null) {
1587135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1588135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                            Slog.d(TAG, "--- hide notification");
1589135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1590135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.cancelAsUser(null,
1591135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                com.android.internal.R.string.select_input_method, UserHandle.ALL);
15927cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        mNotificationShown = false;
15937cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
15947cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
159506487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
159606487a58be22b100daf3f950b9a1d25c3ea42aa2satok        } finally {
159706487a58be22b100daf3f950b9a1d25c3ea42aa2satok            Binder.restoreCallingIdentity(ident);
159806487a58be22b100daf3f950b9a1d25c3ea42aa2satok        }
159906487a58be22b100daf3f950b9a1d25c3ea42aa2satok    }
160006487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1601e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1602f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
16034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
16044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
16054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1606f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1607f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
1608f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            for (int i = 0; i < spans.length; ++i) {
1609f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                SuggestionSpan ss = spans[i];
161042c5a1666c4e576ccd5974233513100aad2c1534satok                if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
1611f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                    mSecureSuggestionSpans.put(ss, currentImi);
1612f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                }
1613f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1614f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1615f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1616f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1617e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1618f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
16194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
16204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
16214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1622f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1623f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
1624f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            // TODO: Do not send the intent if the process of the targetImi is already dead.
1625f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            if (targetImi != null) {
1626f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final String[] suggestions = span.getSuggestions();
1627f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                if (index < 0 || index >= suggestions.length) return false;
162842c5a1666c4e576ccd5974233513100aad2c1534satok                final String className = span.getNotificationTargetClassName();
1629f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final Intent intent = new Intent();
1630f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // Ensures that only a class in the original IME package will receive the
1631f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // notification.
163242c5a1666c4e576ccd5974233513100aad2c1534satok                intent.setClassName(targetImi.getPackageName(), className);
1633f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
1634f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
1635f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
1636f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
1637f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                final long ident = Binder.clearCallingIdentity();
1638f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                try {
1639f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
1640f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                } finally {
1641f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    Binder.restoreCallingIdentity(ident);
1642f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                }
1643f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                return true;
1644f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1645f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1646f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        return false;
1647f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1648f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1649fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn    void updateFromSettingsLocked(boolean enabledMayChange) {
1650fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        if (enabledMayChange) {
1651fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
1652fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            for (int i=0; i<enabled.size(); i++) {
1653fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // We allow the user to select "disabled until used" apps, so if they
1654fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // are enabling one of those here we now need to make it enabled.
1655fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                InputMethodInfo imm = enabled.get(i);
1656fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                try {
1657fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
1658fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
1659fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            mSettings.getCurrentUserId());
16607987a3172b0502ea70a26d80e7cd16ca7e460035Satoshi Kataoka                    if (ai != null && ai.enabledSetting
1661fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
1662ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        if (DEBUG) {
1663ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            Slog.d(TAG, "Update state(" + imm.getId()
1664ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                                    + "): DISABLED_UNTIL_USED -> DEFAULT");
1665ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        }
1666fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
1667fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
16683fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(),
16693fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                mContext.getBasePackageName());
1670fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    }
1671fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                } catch (RemoteException e) {
1672fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
1673fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            }
1674fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        }
1675b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
1676b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
1677b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
1678b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // enabled.
16794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String id = mSettings.getSelectedInputMethod();
168003eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        // There is no input method selected, try to choose new applicable input method.
168103eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
16824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            id = mSettings.getSelectedInputMethod();
168303eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        }
168403eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (!TextUtils.isEmpty(id)) {
16859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
16868e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
16879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException e) {
16888a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unknown input method from prefs: " + id, e);
1689105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mCurMethodId = null;
16902ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
16919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1692f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.clear();
1693b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        } else {
1694b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            // There is no longer an input method set, so stop any current one.
1695105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCurMethodId = null;
16962ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn            unbindCurrentMethodLocked(true, false);
16979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16983d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
16993d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
17003d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
17013d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
17023d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
17039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1704ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1705ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /* package */ void setInputMethodLocked(String id, int subtypeId) {
17069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(id);
17079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
1708913a8925c07e854a80bf5df87561f290d3a56d61satok            throw new IllegalArgumentException("Unknown id: " + id);
17099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1710ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1711d81e950265356c81276b73da68a535ffa48d72f0satok        // See if we need to notify a subtype change within the same IME.
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.equals(mCurMethodId)) {
1713d81e950265356c81276b73da68a535ffa48d72f0satok            final int subtypeCount = info.getSubtypeCount();
1714d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeCount <= 0) {
1715d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1716d81e950265356c81276b73da68a535ffa48d72f0satok            }
1717d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype oldSubtype = mCurrentSubtype;
1718d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype newSubtype;
1719d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeId >= 0 && subtypeId < subtypeCount) {
1720d81e950265356c81276b73da68a535ffa48d72f0satok                newSubtype = info.getSubtypeAt(subtypeId);
1721d81e950265356c81276b73da68a535ffa48d72f0satok            } else {
1722d81e950265356c81276b73da68a535ffa48d72f0satok                // If subtype is null, try to find the most applicable one from
1723d81e950265356c81276b73da68a535ffa48d72f0satok                // getCurrentInputMethodSubtype.
17244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                newSubtype = getCurrentInputMethodSubtypeLocked();
1725d81e950265356c81276b73da68a535ffa48d72f0satok            }
1726d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype == null || oldSubtype == null) {
1727d81e950265356c81276b73da68a535ffa48d72f0satok                Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
1728d81e950265356c81276b73da68a535ffa48d72f0satok                        + ", new subtype = " + newSubtype);
1729d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1730d81e950265356c81276b73da68a535ffa48d72f0satok            }
1731d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype != oldSubtype) {
1732d81e950265356c81276b73da68a535ffa48d72f0satok                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
1733d81e950265356c81276b73da68a535ffa48d72f0satok                if (mCurMethod != null) {
1734d81e950265356c81276b73da68a535ffa48d72f0satok                    try {
1735d81e950265356c81276b73da68a535ffa48d72f0satok                        refreshImeWindowVisibilityLocked();
1736d81e950265356c81276b73da68a535ffa48d72f0satok                        mCurMethod.changeInputMethodSubtype(newSubtype);
1737d81e950265356c81276b73da68a535ffa48d72f0satok                    } catch (RemoteException e) {
1738d81e950265356c81276b73da68a535ffa48d72f0satok                        Slog.w(TAG, "Failed to call changeInputMethodSubtype");
1739ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
1740ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                }
1741ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            }
17429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
17439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1744ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1745d81e950265356c81276b73da68a535ffa48d72f0satok        // Changing to a different IME.
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long ident = Binder.clearCallingIdentity();
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1748ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // Set a subtype to this input method.
1749ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // subtypeId the name of a subtype which will be set.
1750723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
1751723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
1752723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // because mCurMethodId is stored as a history in
1753723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // setSelectedInputMethodAndSubtypeLocked().
1754723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mCurMethodId = id;
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ActivityManagerNative.isSystemReady()) {
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
17581c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.putExtra("input_method_id", id);
1760cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani                mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1762b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
17639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1767ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
176842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
17694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean showSoftInput(IInputMethodClient client, int flags,
17704df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
17714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
17724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
17734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1774cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
17819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
17829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
17839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
17849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1785cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
17864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
17889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
17894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
17919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1792ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1793e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
17944df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return showCurrentInputLocked(flags, resultReceiver);
17959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
17979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1800ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = true;
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowForced = true;
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1810ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1811cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        if (!mSystemReady) {
1812cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            return false;
1813cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        }
1814ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res = false;
18169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
1817e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
18184df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
18194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
18204df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    resultReceiver));
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputShown = true;
18222c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            if (mHaveConnection && !mVisibleBound) {
18234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                bindCurrentInputMethodService(
1824f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                        mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
1825f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                                | Context.BIND_TREAT_LIKE_ACTIVITY);
18262c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                mVisibleBound = true;
18272c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            }
18284df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mHaveConnection && SystemClock.uptimeMillis()
183059b424c3b6121c9579fc5efcc785ba084072a5casatok                >= (mLastBindTime+TIME_TO_RECONNECT)) {
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The client has asked to have the input method shown, but
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we have been sitting here too long with a connection to the
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // service and no interface received, so let's disconnect/connect
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to try to prod things along.
1835ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemClock.uptimeMillis()-mLastBindTime,1);
183759b424c3b6121c9579fc5efcc785ba084072a5casatok            Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.unbindService(this);
18394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
18402c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                    | Context.BIND_NOT_VISIBLE);
18414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } else {
18424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
18434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
18444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
18454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1847ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1850ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
185142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
18524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean hideSoftInput(IInputMethodClient client, int flags,
18534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
18544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
18554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
18564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1857cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1868cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
1869cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                                    + uid + ": " + client);
187015452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
18714df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
18729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
187415452a487a4c0274f4217cd060aa54446f30a8f3satok                        setImeWindowVisibilityStatusHiddenLocked();
18754df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
18769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
18779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1878ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18798a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
18804df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return hideCurrentInputLocked(flags, resultReceiver);
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1886ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18874df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
18889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
18899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mShowExplicitlyRequested || mShowForced)) {
1890e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
18914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
18929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
1894e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
18954df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18974df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res;
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputShown && mCurMethod != null) {
18994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
19004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
19014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
19024df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
19034df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = false;
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19052c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mHaveConnection && mVisibleBound) {
19062c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
19072c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
19082c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
19099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputShown = false;
19109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = false;
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowExplicitlyRequested = false;
19129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowForced = false;
19134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1915ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
191642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
19177663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
19187663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            int controlFlags, int softInputMode, int windowFlags,
19197663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            EditorInfo attribute, IInputContext inputContext) {
19208d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        // Needs to check the validity before clearing calling identity
19218d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        final boolean calledFromValidUser = calledFromValidUser();
19228d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
19237663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        InputBindResult res = null;
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
19278a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
19287663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " controlFlags=#" + Integer.toHexString(controlFlags)
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " softInputMode=#" + Integer.toHexString(softInputMode)
19307663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " windowFlags=#" + Integer.toHexString(windowFlags));
1931ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19327663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                ClientState cs = mClients.get(client.asBinder());
19337663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (cs == null) {
19347663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    throw new IllegalArgumentException("unknown client "
19357663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            + client.asBinder());
19367663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
19377663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
19387663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                try {
19397663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
19407663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // Check with the window manager to make sure this client actually
19417663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // has a window with focus.  If not, reject.  This is thread safe
19427663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // because if the focus changes some time before or after, the
19437663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // next client receiving focus that has any interest in input will
19447663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // be calling through here after that change happens.
19457663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        Slog.w(TAG, "Focus gain on non-focused client " + cs.client
19467663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
19477663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return null;
19489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
19497663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                } catch (RemoteException e) {
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1951ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19528d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                if (!calledFromValidUser) {
19538d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "A background user is requesting window. Hiding IME.");
19548d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "If you want to interect with IME, you need "
19558d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                            + "android.permission.INTERACT_ACROSS_USERS_FULL");
19568d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    hideCurrentInputLocked(0, null);
19578d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    return null;
19588d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                }
19598d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
1960b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                if (mCurFocusedWindow == windowToken) {
1961ac92087a9a1c464d4b0a58c82dae01cbaa088e89Dianne Hackborn                    Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
19623573950e0b30178dc963de3fa00aba2ebcfd552dSatoshi Kataoka                            + " attribute=" + attribute + ", token = " + windowToken);
19637663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (attribute != null) {
19647663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return startInputUncheckedLocked(cs, inputContext, attribute,
19657663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                controlFlags);
19667663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    }
19677663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    return null;
1968b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
1969b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mCurFocusedWindow = windowToken;
1970ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19717d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // Should we auto-show the IME even if the caller has not
19727d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // specified what should be done with it?
19737d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // We only do this automatically if the window can resize
19747d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // to accommodate the IME (so what the user sees will give
19757d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // them good context without input information being obscured
19767d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // by the IME) or if running on a large screen where there
19777d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // is more room for the target window + IME.
19787d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                final boolean doAutoShow =
19797d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
19807d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
19817d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        || mRes.getConfiguration().isLayoutSizeAtLeast(
19827d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                Configuration.SCREENLAYOUT_SIZE_LARGE);
19837663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                final boolean isTextEditor =
19847663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0;
19857663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
19867663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // We want to start input before showing the IME, but after closing
19877663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // it.  We want to do this after closing it to help the IME disappear
19887663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // more quickly (not get stuck behind it initializing itself for the
19897663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // new focused input, even if its window wants to hide the IME).
19907663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                boolean didStart = false;
19917d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
19947d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        if (!isTextEditor || !doAutoShow) {
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // There is no focus view, and this window will
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // be behind any soft input window, so hide the
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // soft input window if it is shown.
19998a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
20004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
20027d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        } else if (isTextEditor && doAutoShow && (softInputMode &
20037d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // There is a focus view, and we are navigating forward
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // into the window, so show the input window for the user.
20067663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // We only do this automatically if the window can resize
20077663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // to accommodate the IME (so what the user sees will give
20087d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // them good context without input information being obscured
20097d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // by the IME) or if running on a large screen where there
20107d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // is more room for the target window + IME.
20118a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
20127663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
20137663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
20147663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
20157663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
20167663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
20174df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Do nothing.
20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20268a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
20274df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            hideCurrentInputLocked(0, null);
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
20318a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to hide input");
20324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        hideCurrentInputLocked(0, null);
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20378a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
20387663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
20397663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
20407663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
20417663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
20427663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
20434df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
20478a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to always show input");
20487663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        if (attribute != null) {
20497663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            res = startInputUncheckedLocked(cs, inputContext, attribute,
20507663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                    controlFlags);
20517663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            didStart = true;
20527663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        }
20534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20567663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20577663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (!didStart && attribute != null) {
20587663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    res = startInputUncheckedLocked(cs, inputContext, attribute,
20597663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            controlFlags);
20607663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
20619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
20649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20657663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20667663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return res;
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2068ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
206942c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showInputMethodPickerFromClient(IInputMethodClient client) {
20714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
20759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurClient == null || client == null
20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || mCurClient.client.asBinder() != client.asBinder()) {
207747a44916e2fb33cf4751906386d5f5c903b28d8bsatok                Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
2078cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + ": " + client);
20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2081440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // Always call subtype picker, because subtype picker is a superset of input method
2082440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // picker.
2083ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER);
2084ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2085ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2086ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
208742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethod(IBinder token, String id) {
20894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20922820351489537698ad153c6397edf3270455edc5satok        setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
20932820351489537698ad153c6397edf3270455edc5satok    }
20942820351489537698ad153c6397edf3270455edc5satok
209542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20962820351489537698ad153c6397edf3270455edc5satok    public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
20974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
21002820351489537698ad153c6397edf3270455edc5satok        synchronized (mMethodMap) {
21012820351489537698ad153c6397edf3270455edc5satok            if (subtype != null) {
21024e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, id,
21034e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        InputMethodUtils.getSubtypeIdFromHashCode(mMethodMap.get(id),
21044e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                                subtype.hashCode()));
21052820351489537698ad153c6397edf3270455edc5satok            } else {
21062820351489537698ad153c6397edf3270455edc5satok                setInputMethod(token, id);
21072820351489537698ad153c6397edf3270455edc5satok            }
21082820351489537698ad153c6397edf3270455edc5satok        }
2109ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2110ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
211142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
2112b416a71e56cdd50742eb897366a140775aa4cd61satok    public void showInputMethodAndSubtypeEnablerFromClient(
2113217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            IInputMethodClient client, String inputMethodId) {
21144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
21164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2117b416a71e56cdd50742eb897366a140775aa4cd61satok        synchronized (mMethodMap) {
2118b416a71e56cdd50742eb897366a140775aa4cd61satok            if (mCurClient == null || client == null
2119b416a71e56cdd50742eb897366a140775aa4cd61satok                || mCurClient.client.asBinder() != client.asBinder()) {
2120b416a71e56cdd50742eb897366a140775aa4cd61satok                Slog.w(TAG, "Ignoring showInputMethodAndSubtypeEnablerFromClient of: " + client);
2121b416a71e56cdd50742eb897366a140775aa4cd61satok            }
21227fee71f66afef6421b92fa48e63d4bc73f5d0c27satok            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
21237fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                    MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
2124b416a71e56cdd50742eb897366a140775aa4cd61satok        }
2125b416a71e56cdd50742eb897366a140775aa4cd61satok    }
2126b416a71e56cdd50742eb897366a140775aa4cd61satok
21274fc87d61c29886c848789208c9e32ba9ac4e5dd3satok    @Override
2128735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    public boolean switchToLastInputMethod(IBinder token) {
21294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
21314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2132735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        synchronized (mMethodMap) {
2133c445bcd0bce630948ee029d7c70b28226f0b6c9csatok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
21344fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            final InputMethodInfo lastImi;
2135208d5634047111811de16fb63c43d0bc8b4fe6desatok            if (lastIme != null) {
21364fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = mMethodMap.get(lastIme.first);
21374fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
21384fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = null;
21394fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
21404fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            String targetLastImiId = null;
21414fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            int subtypeId = NOT_A_SUBTYPE_ID;
21424fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (lastIme != null && lastImi != null) {
21434fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
21444fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
21454fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
21464fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        : mCurrentSubtype.hashCode();
21474fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // If the last IME is the same as the current IME and the last subtype is not
21484fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // defined, there is no need to switch to the last IME.
21494fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
21504fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    targetLastImiId = lastIme.first;
21518e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
21524fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
21534fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
21544fc87d61c29886c848789208c9e32ba9ac4e5dd3satok
21558e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            if (TextUtils.isEmpty(targetLastImiId)
21568e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    && !InputMethodUtils.canAddToLastInputMethod(mCurrentSubtype)) {
21574fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // This is a safety net. If the currentSubtype can't be added to the history
21584fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // and the framework couldn't find the last ime, we will make the last ime be
21594fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // the most applicable enabled keyboard subtype of the system imes.
21604fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
21614fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (enabled != null) {
21624fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final int N = enabled.size();
21634fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final String locale = mCurrentSubtype == null
21644fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            ? mRes.getConfiguration().locale.toString()
21654fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            : mCurrentSubtype.getLocale();
21664fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    for (int i = 0; i < N; ++i) {
21674fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        final InputMethodInfo imi = enabled.get(i);
21688e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        if (imi.getSubtypeCount() > 0 && InputMethodUtils.isSystemIme(imi)) {
21694fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            InputMethodSubtype keyboardSubtype =
21708e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                    InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes,
21718e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.getSubtypes(imi),
21728e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, locale, true);
21734fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            if (keyboardSubtype != null) {
21744fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                targetLastImiId = imi.getId();
21758e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
21764fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                        imi, keyboardSubtype.hashCode());
21774fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                if(keyboardSubtype.getLocale().equals(locale)) {
21784fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                    break;
21794fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                }
21804fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            }
21814fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        }
21824fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    }
21834fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
21844fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
2185c445bcd0bce630948ee029d7c70b28226f0b6c9csatok
21864fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (!TextUtils.isEmpty(targetLastImiId)) {
2187c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                if (DEBUG) {
21884fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
21894fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            + ", from: " + mCurMethodId + ", " + subtypeId);
2190735cf38b8c7f8f91ad087511e44fe79018fa61d6satok                }
21914e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
2192c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                return true;
21934fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
21944fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                return false;
2195735cf38b8c7f8f91ad087511e44fe79018fa61d6satok            }
2196735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        }
2197735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    }
2198735cf38b8c7f8f91ad087511e44fe79018fa61d6satok
2199e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2200688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
22014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
22034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2204688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        synchronized (mMethodMap) {
2205a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2206a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2207a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring switchToNextInputMethod due to an invalid token. uid:" + uid
2208a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + " token:" + token);
2209a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2210a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
22115a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
2212688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                    onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
2213688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            if (nextSubtype == null) {
2214688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                return false;
2215688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            }
22164e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
22174e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    nextSubtype.mSubtypeId);
2218688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            return true;
2219688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        }
2220688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    }
2221688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok
2222688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    @Override
22232b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    public boolean shouldOfferSwitchingToNextInputMethod(IBinder token) {
22242b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        if (!calledFromValidUser()) {
22252b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return false;
22262b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
22272b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        synchronized (mMethodMap) {
2228a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2229a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2230a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring shouldOfferSwitchingToNextInputMethod due to an invalid "
2231a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + "token. uid:" + uid + " token:" + token);
2232a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2233a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
22345a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
22352b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                    false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
22362b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            if (nextSubtype == null) {
22372b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                return false;
22382b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            }
22392b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return true;
22402b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
22412b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    }
22422b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka
22432b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    @Override
224468f1b78b7b9139a0e34285ff641a664e664a14b8satok    public InputMethodSubtype getLastInputMethodSubtype() {
22454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
22474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
224868f1b78b7b9139a0e34285ff641a664e664a14b8satok        synchronized (mMethodMap) {
224968f1b78b7b9139a0e34285ff641a664e664a14b8satok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
225068f1b78b7b9139a0e34285ff641a664e664a14b8satok            // TODO: Handle the case of the last IME with no subtypes
225168f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastIme == null || TextUtils.isEmpty(lastIme.first)
225268f1b78b7b9139a0e34285ff641a664e664a14b8satok                    || TextUtils.isEmpty(lastIme.second)) return null;
225368f1b78b7b9139a0e34285ff641a664e664a14b8satok            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
225468f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastImi == null) return null;
225568f1b78b7b9139a0e34285ff641a664e664a14b8satok            try {
225668f1b78b7b9139a0e34285ff641a664e664a14b8satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
22578e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final int lastSubtypeId =
22588e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
22590e7d7d632309409e2bc51d5317cf7a92a7541433satok                if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
22600e7d7d632309409e2bc51d5317cf7a92a7541433satok                    return null;
22610e7d7d632309409e2bc51d5317cf7a92a7541433satok                }
22620e7d7d632309409e2bc51d5317cf7a92a7541433satok                return lastImi.getSubtypeAt(lastSubtypeId);
226368f1b78b7b9139a0e34285ff641a664e664a14b8satok            } catch (NumberFormatException e) {
226468f1b78b7b9139a0e34285ff641a664e664a14b8satok                return null;
226568f1b78b7b9139a0e34285ff641a664e664a14b8satok            }
226668f1b78b7b9139a0e34285ff641a664e664a14b8satok        }
226768f1b78b7b9139a0e34285ff641a664e664a14b8satok    }
226868f1b78b7b9139a0e34285ff641a664e664a14b8satok
2269e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2270ee5e77cafec2eae70890abdcc1646ed39b06edddsatok    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
22714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
22734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
227491e88122cf28a48fd2e2260da7d3d87dd437227asatok        // By this IPC call, only a process which shares the same uid with the IME can add
227591e88122cf28a48fd2e2260da7d3d87dd437227asatok        // additional input method subtypes to the IME.
2276ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
2277e7c6998e0a953ae55487d4fe122739646f9280aasatok        synchronized (mMethodMap) {
227891e88122cf28a48fd2e2260da7d3d87dd437227asatok            final InputMethodInfo imi = mMethodMap.get(imiId);
2279ee5e77cafec2eae70890abdcc1646ed39b06edddsatok            if (imi == null) return;
22804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String[] packageInfos;
22814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            try {
22824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
22834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } catch (RemoteException e) {
22844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.e(TAG, "Failed to get package infos");
22854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
22864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
228791e88122cf28a48fd2e2260da7d3d87dd437227asatok            if (packageInfos != null) {
228891e88122cf28a48fd2e2260da7d3d87dd437227asatok                final int packageNum = packageInfos.length;
228991e88122cf28a48fd2e2260da7d3d87dd437227asatok                for (int i = 0; i < packageNum; ++i) {
229091e88122cf28a48fd2e2260da7d3d87dd437227asatok                    if (packageInfos[i].equals(imi.getPackageName())) {
229191e88122cf28a48fd2e2260da7d3d87dd437227asatok                        mFileManager.addInputMethodSubtypes(imi, subtypes);
2292c593380d1bccbfbd45c404954b2670b65acc287fsatok                        final long ident = Binder.clearCallingIdentity();
2293c593380d1bccbfbd45c404954b2670b65acc287fsatok                        try {
2294f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                            buildInputMethodListLocked(mMethodList, mMethodMap,
2295f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                                    false /* resetDefaultEnabledIme */);
2296c593380d1bccbfbd45c404954b2670b65acc287fsatok                        } finally {
2297c593380d1bccbfbd45c404954b2670b65acc287fsatok                            Binder.restoreCallingIdentity(ident);
2298c593380d1bccbfbd45c404954b2670b65acc287fsatok                        }
2299ee5e77cafec2eae70890abdcc1646ed39b06edddsatok                        return;
230091e88122cf28a48fd2e2260da7d3d87dd437227asatok                    }
230191e88122cf28a48fd2e2260da7d3d87dd437227asatok                }
230291e88122cf28a48fd2e2260da7d3d87dd437227asatok            }
2303e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
2304ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        return;
2305e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
2306e7c6998e0a953ae55487d4fe122739646f9280aasatok
2307658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    @Override
2308658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    public int getInputMethodWindowVisibleHeight() {
2309658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka        return mWindowManagerService.getInputMethodWindowVisibleHeight();
2310658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    }
2311658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka
2312d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    @Override
2313d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    public void notifyTextCommitted() {
2314d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (DEBUG) {
2315d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka            Slog.d(TAG, "Got the notification of commitText");
2316d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
23175a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
23185a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
23195a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            if (imi != null) {
23205a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                mSwitchingController.onCommitTextLocked(imi, mCurrentSubtype);
23215a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
2322d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2323d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    }
2324d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
2325b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    @Override
2326b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    public void setCursorAnchorMonitorMode(IBinder token, int monitorMode) {
2327b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        if (DEBUG) {
2328b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            Slog.d(TAG, "setCursorAnchorMonitorMode: monitorMode=" + monitorMode);
2329b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        }
2330b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        if (!calledFromValidUser()) {
2331b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            return;
2332b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        }
2333b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        synchronized (mMethodMap) {
233422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
233522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
233622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring setCursorAnchorMonitorMode due to an invalid token. uid:"
233722c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
2338b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                return;
2339b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            }
2340b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
2341b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                    MSG_SET_CURSOR_ANCHOR_MONITOR_MODE, monitorMode, mCurClient));
2342b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        }
2343b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    }
2344b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa
23452820351489537698ad153c6397edf3270455edc5satok    private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
23469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
23474e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, id, subtypeId);
23484e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
23494e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    }
23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23514e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
23524e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        if (token == null) {
23534e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            if (mContext.checkCallingOrSelfPermission(
23544e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
23554e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    != PackageManager.PERMISSION_GRANTED) {
23564e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                throw new SecurityException(
23574e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        "Using null token requires permission "
23584e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
23599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23604e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } else if (mCurToken != token) {
23614e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
23624e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    + " token: " + token);
23634e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            return;
23644e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
23654e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa
23664e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        final long ident = Binder.clearCallingIdentity();
23674e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        try {
23684e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodLocked(id, subtypeId);
23694e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } finally {
23704e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Binder.restoreCallingIdentity(ident);
23719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
237442c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideMySoftInput(IBinder token, int flags) {
23764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
238022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
238122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
238222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring hideInputMethod due to an invalid token. uid:"
238322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
23849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
23859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
23879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
23884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                hideCurrentInputLocked(flags, null);
23894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } finally {
23904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                Binder.restoreCallingIdentity(ident);
23914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
23924df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
23934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
2394ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
239542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23964df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void showMySoftInput(IBinder token, int flags) {
23974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
24004df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        synchronized (mMethodMap) {
240122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
240222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
240322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring showMySoftInput due to an invalid token. uid:"
240422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
24054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return;
24064df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
24074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            long ident = Binder.clearCallingIdentity();
24084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            try {
24094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                showCurrentInputLocked(flags, null);
24109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
24119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
24129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
24159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setEnabledSessionInMainThread(SessionState session) {
24179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledSession != session) {
24189d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
24199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24208a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
24219d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false);
24229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
24249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledSession = session;
24269d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
24279d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                try {
24289d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
24299d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true);
24309d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                } catch (RemoteException e) {
24319d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                }
24329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2435ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
243642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
24379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean handleMessage(Message msg) {
2438758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov        SomeArgs args;
24399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (msg.what) {
24409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_IM_PICKER:
24419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showInputMethodMenu();
24429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2443ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2444ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            case MSG_SHOW_IM_SUBTYPE_PICKER:
2445ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                showInputMethodSubtypeMenu();
2446ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                return true;
2447ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
244847a44916e2fb33cf4751906386d5f5c903b28d8bsatok            case MSG_SHOW_IM_SUBTYPE_ENABLER:
2449758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24507fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                showInputMethodAndSubtypeEnabler((String)args.arg1);
2451758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
2452217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                return true;
2453217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2454217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            case MSG_SHOW_IM_CONFIG:
2455217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                showConfigureInputMethods();
245647a44916e2fb33cf4751906386d5f5c903b28d8bsatok                return true;
245747a44916e2fb33cf4751906386d5f5c903b28d8bsatok
24589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2459ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_INPUT:
24619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)msg.obj).unbindInput();
24639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the method dying.
24659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
24669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_BIND_INPUT:
2468758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);
24719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2473758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_SOFT_INPUT:
2476758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2478e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
24796efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + msg.arg1 + ", " + args.arg2 + ")");
2480ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
24819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2483758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_HIDE_SOFT_INPUT:
2486758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2488e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
24896efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + args.arg2 + ")");
2490ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
24919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2493758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_ATTACH_TOKEN:
2496758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2498e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
24999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
25009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2502758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2504c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            case MSG_CREATE_SESSION: {
2505758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25061951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethod method = (IInputMethod)args.arg1;
2507c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel = (InputChannel)args.arg2;
25089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25091951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    method.createSession(channel, (IInputSessionCallback)args.arg3);
25109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2511c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } finally {
25121951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
25131951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
25141951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (channel != null && Binder.isProxy(method)) {
2515c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        channel.dispose();
2516c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    }
25179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2518758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2520c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
25219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2522ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_START_INPUT:
2524758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
25279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
25289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.startInput((IInputContext)args.arg2,
25299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
25309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2532758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_RESTART_INPUT:
2535758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
25389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
25399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.restartInput((IInputContext)args.arg2,
25409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
25419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2543758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2545ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2547ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_METHOD:
25499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1);
25519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the last client dying.
25539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
25549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25551951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            case MSG_BIND_METHOD: {
2556758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25571951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethodClient client = (IInputMethodClient)args.arg1;
25581951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                InputBindResult res = (InputBindResult)args.arg2;
25599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25601951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    client.onBindMethod(res);
25619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25628a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Client died receiving input method " + args.arg2);
25631951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                } finally {
25641951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
25651951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
25661951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (res.channel != null && Binder.isProxy(client)) {
25671951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                        res.channel.dispose();
25681951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    }
25699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2570758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25721951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            }
2573a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            case MSG_SET_ACTIVE:
2574a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                try {
2575a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    ((ClientState)msg.obj).client.setActive(msg.arg1 != 0);
2576a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                } catch (RemoteException e) {
2577a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    Slog.w(TAG, "Got RemoteException sending setActive(false) notification to pid "
2578a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).pid + " uid "
2579a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).uid);
2580a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                }
2581a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                return true;
2582b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            case MSG_SET_CURSOR_ANCHOR_MONITOR_MODE:
2583b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                try {
2584b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                    ((ClientState)msg.obj).client.setCursorAnchorMonitorMode(msg.arg1);
2585b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                } catch (RemoteException e) {
2586b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                    Slog.w(TAG, "Got RemoteException sending setCursorAnchorMonitorMode "
2587b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                            + "notification to pid " + ((ClientState)msg.obj).pid
2588b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                            + " uid " + ((ClientState)msg.obj).uid);
2589b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                }
2590b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                return true;
259101038492ff0317f0d3cff54d8a7ee36bb31ff175satok
259201038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // --------------------------------------------------------------
259301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
259401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                mHardKeyboardListener.handleHardKeyboardStatusChange(
259501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        msg.arg1 == 1, msg.arg2 == 1);
259601038492ff0317f0d3cff54d8a7ee36bb31ff175satok                return true;
25979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
25999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
26009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2601dc9ddaee9a710cf6f5d7f37350650f82e706c706satok    private boolean chooseNewDefaultIMELocked() {
26028e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
26038e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mSettings.getEnabledInputMethodListLocked());
2604dc9ddaee9a710cf6f5d7f37350650f82e706c706satok        if (imi != null) {
260503eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            if (DEBUG) {
260603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                Slog.d(TAG, "New default IME was selected: " + imi.getId());
260703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            }
2608723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            resetSelectedInputMethodAndSubtypeLocked(imi.getId());
26096da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            return true;
26106da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
26116da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
26126da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        return false;
26136da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger    }
26146da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
26159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
2616f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) {
26174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
2618f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
26190766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                    + " \n ------ \n" + InputMethodUtils.getStackTrace());
26204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
26219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        list.clear();
26229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map.clear();
2623ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // Use for queryIntentServicesAsUser
26254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final PackageManager pm = mContext.getPackageManager();
26264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
2627e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani        if (disabledSysImes == null) disabledSysImes = "";
26289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
26309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new Intent(InputMethod.SERVICE_INTERFACE),
2631fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
2632fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                mSettings.getCurrentUserId());
2633ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2634e7c6998e0a953ae55487d4fe122739646f9280aasatok        final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
2635e7c6998e0a953ae55487d4fe122739646f9280aasatok                mFileManager.getAllAdditionalInputMethodSubtypes();
26369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < services.size(); ++i) {
26379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = services.get(i);
26389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ServiceInfo si = ri.serviceInfo;
26399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ComponentName compName = new ComponentName(si.packageName, si.name);
26409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(
26419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    si.permission)) {
26428a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Skipping input method " + compName
26439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": it does not require the permission "
26449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.BIND_INPUT_METHOD);
26459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
26469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26488a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.d(TAG, "Checking " + compName);
26499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2651e7c6998e0a953ae55487d4fe122739646f9280aasatok                InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes);
26529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list.add(p);
2653e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                final String id = p.getId();
2654e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                map.put(id, p);
26559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
2657f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "Found an input method " + p);
26589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2659ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
26618a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
26629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
26638a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
26649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26666da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
2667f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (resetDefaultEnabledIme) {
2668f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            final ArrayList<InputMethodInfo> defaultEnabledIme =
2669f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list);
2670f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            for (int i = 0; i < defaultEnabledIme.size(); ++i) {
2671f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                final InputMethodInfo imi =  defaultEnabledIme.get(i);
2672f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                if (DEBUG) {
2673f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "--- enable ime = " + imi);
2674f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                }
2675f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                setInputMethodEnabledLocked(imi.getId(), true);
2676f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            }
2677f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
2678f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
26794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
26800a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!TextUtils.isEmpty(defaultImiId)) {
26810a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            if (!map.containsKey(defaultImiId)) {
26820a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
26830a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (chooseNewDefaultIMELocked()) {
2684fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(true);
26850a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
26860a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            } else {
26870a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                // Double check that the default IME is certainly enabled.
26880a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                setInputMethodEnabledLocked(defaultImiId, true);
26896da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            }
26906da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
26913d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
26923d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
26933d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
26943d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
2695c834a2590cc7ac478ba2ef5a6d8eb7ce471df132Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
26969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2697ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2699ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2700ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenu() {
2701ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(false);
2702ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2703ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2704ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodSubtypeMenu() {
2705ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(true);
2706ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2707ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2708217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
2709f49688fa17b70313c0734f00df73bc3308a749e9Tadashi G. Takaoka        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
271047a44916e2fb33cf4751906386d5f5c903b28d8bsatok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
271186417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
271286417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
27137fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        if (!TextUtils.isEmpty(inputMethodId)) {
27142548020c364c4119d134c84cc7a00ffca2dcbe7bTadashi G. Takaoka            intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId);
27157fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        }
27163ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
2717217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    }
2718217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2719217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showConfigureInputMethods() {
2720217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
2721217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2722217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
2723217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
27243ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
272547a44916e2fb33cf4751906386d5f5c903b28d8bsatok    }
272647a44916e2fb33cf4751906386d5f5c903b28d8bsatok
27272c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    private boolean isScreenLocked() {
27282c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        return mKeyguardManager != null
27292c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
27302c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    }
2731ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenuInternal(boolean showSubtypes) {
27328a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Show switching menu");
27339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Context context = mContext;
27352c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        final boolean isScreenLocked = isScreenLocked();
2736ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String lastInputMethodId = mSettings.getSelectedInputMethod();
27388e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
27398a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
2740ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27417f35c8cc88bea5230f001dd4356f864845d202e5satok        synchronized (mMethodMap) {
2742bb4aa0683c8a0a1e617c6d5f03eda33f49b89ed9satok            final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
2743d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(
2744d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                            mContext);
27457f35c8cc88bea5230f001dd4356f864845d202e5satok            if (immis == null || immis.size() == 0) {
27467f35c8cc88bea5230f001dd4356f864845d202e5satok                return;
27477f35c8cc88bea5230f001dd4356f864845d202e5satok            }
2748ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
27498cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            hideInputMethodMenuLocked();
27509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2751688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            final List<ImeSubtypeListItem> imList =
27525a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSwitchingController.getSortedInputMethodAndSubtypeListLocked(
2753688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                            showSubtypes, mInputShown, isScreenLocked);
2754913a8925c07e854a80bf5df87561f290d3a56d61satok
2755c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
27564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
2757c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                if (currentSubtype != null) {
2758c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                    final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
27598e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
27608e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            currentImi, currentSubtype.hashCode());
2761c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                }
2762c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            }
2763c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok
2764761eb3762f3602dd1859905ee4ba80f0ef6aec56Ken Wakasa            final int N = imList.size();
2765ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mIms = new InputMethodInfo[N];
2766ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mSubtypeIds = new int[N];
27678cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            int checkedItem = 0;
27688cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            for (int i = 0; i < N; ++i) {
276905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                final ImeSubtypeListItem item = imList.get(i);
277005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mIms[i] = item.mImi;
277105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mSubtypeIds[i] = item.mSubtypeId;
27728cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                if (mIms[i].getId().equals(lastInputMethodId)) {
2773ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    int subtypeId = mSubtypeIds[i];
2774ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    if ((subtypeId == NOT_A_SUBTYPE_ID)
2775ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0)
2776ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (subtypeId == lastInputMethodSubtypeId)) {
2777ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                        checkedItem = i;
2778ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
27798cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                }
27809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
278105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TypedArray a = context.obtainStyledAttributes(null,
27828cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    com.android.internal.R.styleable.DialogPreference,
27838cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    com.android.internal.R.attr.alertDialogStyle, 0);
27848cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            mDialogBuilder = new AlertDialog.Builder(context)
27858cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    .setOnCancelListener(new OnCancelListener() {
278642c5a1666c4e576ccd5974233513100aad2c1534satok                        @Override
27878cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        public void onCancel(DialogInterface dialog) {
27889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            hideInputMethodMenu();
27898cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        }
27908cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    })
27918cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    .setIcon(a.getDrawable(
27928cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                            com.android.internal.R.styleable.DialogPreference_dialogTitle));
27938cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            a.recycle();
279401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final LayoutInflater inflater =
279501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
279601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final View tv = inflater.inflate(
279701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.layout.input_method_switch_dialog_title, null);
279801038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mDialogBuilder.setCustomTitle(tv);
279901038492ff0317f0d3cff54d8a7ee36bb31ff175satok
280001038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // Setup layout for a toggle switch of the hardware keyboard
280101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView = tv;
280201038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView.findViewById(
280301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.id.hard_keyboard_section).setVisibility(
280401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mWindowManagerService.isHardKeyboardAvailable() ?
280501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    View.VISIBLE : View.GONE);
280601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final Switch hardKeySwitch =  ((Switch)mSwitchingDialogTitleView.findViewById(
280701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.id.hard_keyboard_switch));
280801038492ff0317f0d3cff54d8a7ee36bb31ff175satok            hardKeySwitch.setChecked(mWindowManagerService.isHardKeyboardEnabled());
280901038492ff0317f0d3cff54d8a7ee36bb31ff175satok            hardKeySwitch.setOnCheckedChangeListener(
281001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    new OnCheckedChangeListener() {
281101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        @Override
281201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        public void onCheckedChanged(
281301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                CompoundButton buttonView, boolean isChecked) {
281401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mWindowManagerService.setHardKeyboardEnabled(isChecked);
281504dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            // Ensure that the input method dialog is dismissed when changing
281604dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            // the hardware keyboard state.
281704dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            hideInputMethodMenu();
281801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        }
281901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    });
2820d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok
282105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(context,
282205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    com.android.internal.R.layout.simple_list_item_2_single_choice, imList,
282305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    checkedItem);
282405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
282505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mDialogBuilder.setSingleChoiceItems(adapter, checkedItem,
28268cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    new AlertDialog.OnClickListener() {
282742c5a1666c4e576ccd5974233513100aad2c1534satok                        @Override
28288cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        public void onClick(DialogInterface dialog, int which) {
28298cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                            synchronized (mMethodMap) {
2830ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                if (mIms == null || mIms.length <= which
2831ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                        || mSubtypeIds == null || mSubtypeIds.length <= which) {
28328cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                    return;
28338cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                }
28348cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                InputMethodInfo im = mIms[which];
2835ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                int subtypeId = mSubtypeIds[which];
2836d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka                                adapter.mCheckedItem = which;
2837d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka                                adapter.notifyDataSetChanged();
28388cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                hideInputMethodMenu();
28398cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                if (im != null) {
2840ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    if ((subtypeId < 0)
2841586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                                            || (subtypeId >= im.getSubtypeCount())) {
2842ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                        subtypeId = NOT_A_SUBTYPE_ID;
2843ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    }
2844ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    setInputMethodLocked(im.getId(), subtypeId);
28458cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                }
284620cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn                            }
28479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
28488cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    });
28499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2850bc81b692d51a9cd6f9d61584aacd8308ac3366easatok            if (showSubtypes && !isScreenLocked) {
285182beadfa067b1e286fa604f8d7960d769411c954satok                mDialogBuilder.setPositiveButton(
285282beadfa067b1e286fa604f8d7960d769411c954satok                        com.android.internal.R.string.configure_input_methods,
28537f35c8cc88bea5230f001dd4356f864845d202e5satok                        new DialogInterface.OnClickListener() {
285442c5a1666c4e576ccd5974233513100aad2c1534satok                            @Override
28557f35c8cc88bea5230f001dd4356f864845d202e5satok                            public void onClick(DialogInterface dialog, int whichButton) {
2856217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                                showConfigureInputMethods();
28577f35c8cc88bea5230f001dd4356f864845d202e5satok                            }
28587f35c8cc88bea5230f001dd4356f864845d202e5satok                        });
28597f35c8cc88bea5230f001dd4356f864845d202e5satok            }
28609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog = mDialogBuilder.create();
2861e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.setCanceledOnTouchOutside(true);
28629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.getWindow().setType(
28639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
2864c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
2865c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2866e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
2867807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk            updateImeWindowStatusLocked();
28689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.show();
28699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
28709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2871ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
287205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> {
287305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final LayoutInflater mInflater;
287405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final int mTextViewResourceId;
287505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final List<ImeSubtypeListItem> mItemsList;
2876d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka        public int mCheckedItem;
287705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public ImeSubtypeListAdapter(Context context, int textViewResourceId,
287805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                List<ImeSubtypeListItem> itemsList, int checkedItem) {
287905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            super(context, textViewResourceId, itemsList);
288005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mTextViewResourceId = textViewResourceId;
288105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mItemsList = itemsList;
288205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mCheckedItem = checkedItem;
288305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
288405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
288505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
288605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        @Override
288705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public View getView(int position, View convertView, ViewGroup parent) {
288805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final View view = convertView != null ? convertView
288905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    : mInflater.inflate(mTextViewResourceId, null);
289005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (position < 0 || position >= mItemsList.size()) return view;
289105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListItem item = mItemsList.get(position);
289205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence imeName = item.mImeName;
289305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence subtypeName = item.mSubtypeName;
289405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1);
289505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2);
289605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (TextUtils.isEmpty(subtypeName)) {
289705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(imeName);
289805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.GONE);
289905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            } else {
290005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(subtypeName);
290105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setText(imeName);
290205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.VISIBLE);
290305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            }
290405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final RadioButton radioButton =
290505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
290605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            radioButton.setChecked(position == mCheckedItem);
290705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            return view;
290805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
290905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    }
291005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
29119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hideInputMethodMenu() {
2912105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        synchronized (mMethodMap) {
2913105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
2914105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2915105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2916ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2917105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void hideInputMethodMenuLocked() {
29188a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Hide switching menu");
29199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2920105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mSwitchingDialog != null) {
2921105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog.dismiss();
2922105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog = null;
29239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2924ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2925807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk        updateImeWindowStatusLocked();
2926105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mDialogBuilder = null;
2927105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIms = null;
29289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2929ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2931ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
293242c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
29339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setInputMethodEnabled(String id, boolean enabled) {
29344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
29354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
29364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
29374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
29389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
29399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mContext.checkCallingOrSelfPermission(
29409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
29419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    != PackageManager.PERMISSION_GRANTED) {
29429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new SecurityException(
29439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Requires permission "
29449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
29459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
294621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
29479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
29489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
294921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                return setInputMethodEnabledLocked(id, enabled);
295021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } finally {
295121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Binder.restoreCallingIdentity(ident);
295221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
295321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
295421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
29558e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
295621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    boolean setInputMethodEnabledLocked(String id, boolean enabled) {
295721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        // Make sure this is a valid input method.
295821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        InputMethodInfo imm = mMethodMap.get(id);
295921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (imm == null) {
2960d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
296121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
2962ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2963d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
2964d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                .getEnabledInputMethodsAndSubtypeListLocked();
2965ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2966d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        if (enabled) {
2967d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            for (Pair<String, ArrayList<String>> pair: enabledInputMethodsList) {
2968d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                if (pair.first.equals(id)) {
2969d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // We are enabling this input method, but it is already enabled.
2970d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // Nothing to do. The previous state was enabled.
2971d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    return true;
29729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
297321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
2974d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            mSettings.appendAndPutEnabledInputMethodLocked(id, false);
2975d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            // Previous state was disabled.
2976d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return false;
2977d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        } else {
2978d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            StringBuilder builder = new StringBuilder();
2979d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
2980d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    builder, enabledInputMethodsList, id)) {
2981d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Disabled input method is currently selected, switch to another one.
29824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selId = mSettings.getSelectedInputMethod();
298303eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
298403eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
298503eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    resetSelectedInputMethodAndSubtypeLocked("");
2986d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                }
2987d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Previous state was enabled.
2988d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                return true;
2989d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            } else {
2990d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // We are disabling the input method but it is already disabled.
2991d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Nothing to do.  The previous state was disabled.
29929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
29939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
29949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
29964df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
2997723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
2998723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            boolean setSubtypeOnly) {
2999723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Update the history of InputMethod and Subtype
30008e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
3001723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
3002723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Set Subtype here
3003723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi == null || subtypeId < 0) {
3004723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
30050ba75bb22c2992f649ee5f7605a2b45442ad4862Tadashi G. Takaoka            mCurrentSubtype = null;
3006723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        } else {
3007586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa            if (subtypeId < imi.getSubtypeCount()) {
3008586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                InputMethodSubtype subtype = imi.getSubtypeAt(subtypeId);
3009586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mSettings.putSelectedSubtype(subtype.hashCode());
3010586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mCurrentSubtype = subtype;
3011723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            } else {
3012723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
3013d81e950265356c81276b73da68a535ffa48d72f0satok                // If the subtype is not specified, choose the most applicable one
30144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
3015723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3016723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3017723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
30184c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Workaround.
30194c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // ASEC is not ready in the IMMS constructor. Accordingly, forward-locked
30204c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMEs are not recognized and considered uninstalled.
30214c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Actually, we can't move everything after SystemReady because
30224c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMMS needs to run in the encryption lock screen. So, we just skip changing
30234c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the default IME here and try cheking the default IME again in systemReady().
30244c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: Do nothing before system ready and implement a separated logic for
30254c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the encryption lock screen.
30264c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: ASEC should be ready before IMMS is instantiated.
30274c0e7152e74d091eb78af8baacd38287ba95a1a1satok        if (mSystemReady && !setSubtypeOnly) {
3028723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // Set InputMethod here
3029723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
30301ab852fbcfe155c9d4373b7130f8515591669634satok        }
3031ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3032ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3033723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
3034723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        InputMethodInfo imi = mMethodMap.get(newDefaultIme);
3035723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        int lastSubtypeId = NOT_A_SUBTYPE_ID;
3036723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // newDefaultIme is empty when there is no candidate for the selected IME.
3037723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
3038723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme);
3039723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            if (subtypeHashCode != null) {
3040723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                try {
30418e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
3042723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                            imi, Integer.valueOf(subtypeHashCode));
3043723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                } catch (NumberFormatException e) {
3044723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                    Slog.w(TAG, "HashCode for subtype looks broken: " + subtypeHashCode, e);
3045723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                }
3046723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3047723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3048723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
3049723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    }
3050723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
30514e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // If there are no selected shortcuts, tries finding the most applicable ones.
30524e4569dab5c75804b01a19b2d6e6101b445c1c68satok    private Pair<InputMethodInfo, InputMethodSubtype>
30534e4569dab5c75804b01a19b2d6e6101b445c1c68satok            findLastResortApplicableShortcutInputMethodAndSubtypeLocked(String mode) {
30544e4569dab5c75804b01a19b2d6e6101b445c1c68satok        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
30554e4569dab5c75804b01a19b2d6e6101b445c1c68satok        InputMethodInfo mostApplicableIMI = null;
3056cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        InputMethodSubtype mostApplicableSubtype = null;
30574e4569dab5c75804b01a19b2d6e6101b445c1c68satok        boolean foundInSystemIME = false;
30584e4569dab5c75804b01a19b2d6e6101b445c1c68satok
30594e4569dab5c75804b01a19b2d6e6101b445c1c68satok        // Search applicable subtype for each InputMethodInfo
30604e4569dab5c75804b01a19b2d6e6101b445c1c68satok        for (InputMethodInfo imi: imis) {
30617599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            final String imiId = imi.getId();
30627599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (foundInSystemIME && !imiId.equals(mCurMethodId)) {
30637599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                continue;
30647599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3065cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            InputMethodSubtype subtype = null;
3066df31ae6a3011d47421a6ac10021f9649dc34a156satok            final List<InputMethodSubtype> enabledSubtypes =
30678e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
3068df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 1. Search by the current subtype's locale from enabledSubtypes.
30694e4569dab5c75804b01a19b2d6e6101b445c1c68satok            if (mCurrentSubtype != null) {
30708e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3071df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
30724e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3073df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 2. Search by the system locale from enabledSubtypes.
3074df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
3075cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
30768e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3077df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, null, true);
30787599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3079a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
30808e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    InputMethodUtils.getOverridingImplicitlyEnabledSubtypes(imi, mode);
3081a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> subtypesForSearch =
3082a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                    overridingImplicitlyEnabledSubtypes.isEmpty()
30838e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            ? InputMethodUtils.getSubtypes(imi)
30848e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            : overridingImplicitlyEnabledSubtypes;
30857599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 4. Search by the current subtype's locale from all subtypes.
30867599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (subtype == null && mCurrentSubtype != null) {
30878e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3088a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
30894e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
30907599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 5. Search by the system locale from all subtypes.
30917599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 6. Search the first enabled subtype matched with mode from all subtypes.
3092cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
30938e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3094a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, null, true);
30954e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3096cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype != null) {
30977599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (imiId.equals(mCurMethodId)) {
30984e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    // The current input method is the most applicable IME.
30994e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3100cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
31014e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    break;
31024e4569dab5c75804b01a19b2d6e6101b445c1c68satok                } else if (!foundInSystemIME) {
31037599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    // The system input method is 2nd applicable IME.
31044e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3105cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
31067599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    if ((imi.getServiceInfo().applicationInfo.flags
31077599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
31087599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                        foundInSystemIME = true;
31097599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    }
31104e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
31114e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
31124e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
31134e4569dab5c75804b01a19b2d6e6101b445c1c68satok        if (DEBUG) {
3114cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (mostApplicableIMI != null) {
3115cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                Slog.w(TAG, "Most applicable shortcut input method was:"
3116cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                        + mostApplicableIMI.getId());
3117cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                if (mostApplicableSubtype != null) {
3118cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    Slog.w(TAG, "Most applicable shortcut input method subtype was:"
3119cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + "," + mostApplicableSubtype.getMode() + ","
3120cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + mostApplicableSubtype.getLocale());
3121cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                }
3122cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            }
31234e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
3124cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        if (mostApplicableIMI != null) {
31254e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
3126cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype);
31274e4569dab5c75804b01a19b2d6e6101b445c1c68satok        } else {
31284e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return null;
31294e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
31304e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
31314e4569dab5c75804b01a19b2d6e6101b445c1c68satok
3132ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3133ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return Return the current subtype of this input method.
3134ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
313542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3136ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public InputMethodSubtype getCurrentInputMethodSubtype() {
31374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
31384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
31394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
31404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
31414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        synchronized (mMethodMap) {
31424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return getCurrentInputMethodSubtypeLocked();
31434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
31444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
31454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
31464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
3147fdf419e81d795593e3792c9e78f33ed899ff098esatok        if (mCurMethodId == null) {
3148fdf419e81d795593e3792c9e78f33ed899ff098esatok            return null;
3149fdf419e81d795593e3792c9e78f33ed899ff098esatok        }
31508e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
31514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
31524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (imi == null || imi.getSubtypeCount() == 0) {
31534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
31544e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
31554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!subtypeIsSelected || mCurrentSubtype == null
31568e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
31578e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
31584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (subtypeId == NOT_A_SUBTYPE_ID) {
31594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there are no selected subtypes, the framework will try to find
31604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // the most applicable subtype from explicitly or implicitly enabled
31614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // subtypes.
31624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
31638e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
31644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there is only one explicitly or implicitly enabled subtype,
31654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // just returns it.
31664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
31674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
31684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
31698e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
31704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            mRes, explicitlyOrImplicitlyEnabledSubtypes,
31718e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, null, true);
31724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    if (mCurrentSubtype == null) {
31738e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
31744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
31754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                true);
31764e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    }
31773ef8b29fa03fe3ae1c57fd891a12afa46128fff8satok                }
31784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else {
31798e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mCurrentSubtype = InputMethodUtils.getSubtypes(imi).get(subtypeId);
31808fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok            }
31818fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok        }
31824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        return mCurrentSubtype;
3183ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3184ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3185f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
3186f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            InputMethodSubtype subtype) {
3187f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
3188f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
3189f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        } else {
3190f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3191f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            subtypes.add(subtype);
3192f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
3193f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        }
3194f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    }
3195f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok
31964e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // TODO: We should change the return type from List to List<Parcelable>
3197dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("rawtypes")
3198e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
31994e4569dab5c75804b01a19b2d6e6101b445c1c68satok    public List getShortcutInputMethodsAndSubtypes() {
32004e4569dab5c75804b01a19b2d6e6101b445c1c68satok        synchronized (mMethodMap) {
32013da922367c0dbe67b97fe97fcfca13fd93602f7asatok            ArrayList<Object> ret = new ArrayList<Object>();
3202f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            if (mShortcutInputMethodsAndSubtypes.size() == 0) {
32034e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // If there are no selected shortcut subtypes, the framework will try to find
32044e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // the most applicable subtype from all subtypes whose mode is
32054e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
3206f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                Pair<InputMethodInfo, InputMethodSubtype> info =
3207f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
32088e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_VOICE);
32097599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (info != null) {
32103da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.first);
32113da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.second);
32127599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                }
32133da922367c0dbe67b97fe97fcfca13fd93602f7asatok                return ret;
3214f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            }
3215f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
3216f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                ret.add(imi);
3217f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
3218f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    ret.add(subtype);
32194e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
32204e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3221f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            return ret;
32224e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
32234e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
32244e4569dab5c75804b01a19b2d6e6101b445c1c68satok
322542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3226b66d287e3003a0934d5714fbf15e554b3c814906satok    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
32274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
32284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
32294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
32304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
3231b66d287e3003a0934d5714fbf15e554b3c814906satok        synchronized (mMethodMap) {
3232b66d287e3003a0934d5714fbf15e554b3c814906satok            if (subtype != null && mCurMethodId != null) {
3233b66d287e3003a0934d5714fbf15e554b3c814906satok                InputMethodInfo imi = mMethodMap.get(mCurMethodId);
32348e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                int subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode());
3235b66d287e3003a0934d5714fbf15e554b3c814906satok                if (subtypeId != NOT_A_SUBTYPE_ID) {
3236b66d287e3003a0934d5714fbf15e554b3c814906satok                    setInputMethodLocked(mCurMethodId, subtypeId);
3237b66d287e3003a0934d5714fbf15e554b3c814906satok                    return true;
3238b66d287e3003a0934d5714fbf15e554b3c814906satok                }
3239b66d287e3003a0934d5714fbf15e554b3c814906satok            }
3240b66d287e3003a0934d5714fbf15e554b3c814906satok            return false;
3241b66d287e3003a0934d5714fbf15e554b3c814906satok        }
3242b66d287e3003a0934d5714fbf15e554b3c814906satok    }
3243b66d287e3003a0934d5714fbf15e554b3c814906satok
32445ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    // TODO: Cache the state for each user and reset when the cached user is removed.
3245e7c6998e0a953ae55487d4fe122739646f9280aasatok    private static class InputMethodFileManager {
3246e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String SYSTEM_PATH = "system";
3247e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String INPUT_METHOD_PATH = "inputmethod";
3248e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ADDITIONAL_SUBTYPES_FILE_NAME = "subtypes.xml";
3249e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPES = "subtypes";
3250e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPE = "subtype";
3251e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_IMI = "imi";
3252e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ID = "id";
3253e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_LABEL = "label";
3254e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ICON = "icon";
3255e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
3256e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
3257e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
3258e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
3259e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final AtomicFile mAdditionalInputMethodSubtypeFile;
3260e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final HashMap<String, InputMethodInfo> mMethodMap;
3261e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
3262e7c6998e0a953ae55487d4fe122739646f9280aasatok                new HashMap<String, List<InputMethodSubtype>>();
32635ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
3264e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (methodMap == null) {
3265e7c6998e0a953ae55487d4fe122739646f9280aasatok                throw new NullPointerException("methodMap is null");
3266e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3267e7c6998e0a953ae55487d4fe122739646f9280aasatok            mMethodMap = methodMap;
32685ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka            final File systemDir = userId == UserHandle.USER_OWNER
32695ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
32705ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    : Environment.getUserSystemDirectory(userId);
3271e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
3272e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!inputMethodDir.mkdirs()) {
3273e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
3274e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3275e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
3276e7c6998e0a953ae55487d4fe122739646f9280aasatok            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
3277e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!subtypeFile.exists()) {
3278e7c6998e0a953ae55487d4fe122739646f9280aasatok                // If "subtypes.xml" doesn't exist, create a blank file.
3279e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3280e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, methodMap);
3281e7c6998e0a953ae55487d4fe122739646f9280aasatok            } else {
3282e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                readAdditionalInputMethodSubtypes(
3283e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile);
3284e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3285e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3286e7c6998e0a953ae55487d4fe122739646f9280aasatok
3287e7c6998e0a953ae55487d4fe122739646f9280aasatok        private void deleteAllInputMethodSubtypes(String imiId) {
3288e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3289e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.remove(imiId);
3290e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3291e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3292e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3293e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3294e7c6998e0a953ae55487d4fe122739646f9280aasatok
3295e7c6998e0a953ae55487d4fe122739646f9280aasatok        public void addInputMethodSubtypes(
32964a28bde70e23b2ed151d52690da702da7f23cf5esatok                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
3297e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3298e7c6998e0a953ae55487d4fe122739646f9280aasatok                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3299e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int N = additionalSubtypes.length;
3300e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (int i = 0; i < N; ++i) {
3301e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final InputMethodSubtype subtype = additionalSubtypes[i];
3302ed2b24ecc7842b27178fc584a9e5bd5b1ab07635satok                    if (!subtypes.contains(subtype)) {
3303e7c6998e0a953ae55487d4fe122739646f9280aasatok                        subtypes.add(subtype);
3304e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                    } else {
3305e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        Slog.w(TAG, "Duplicated subtype definition found: "
3306e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                                + subtype.getLocale() + ", " + subtype.getMode());
3307e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3308e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3309e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.put(imi.getId(), subtypes);
3310e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3311e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3312e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3313e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3314e7c6998e0a953ae55487d4fe122739646f9280aasatok
3315e7c6998e0a953ae55487d4fe122739646f9280aasatok        public HashMap<String, List<InputMethodSubtype>> getAllAdditionalInputMethodSubtypes() {
3316e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3317e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                return mAdditionalSubtypesMap;
3318e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3319e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3320e7c6998e0a953ae55487d4fe122739646f9280aasatok
3321e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void writeAdditionalInputMethodSubtypes(
3322e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile,
3323e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, InputMethodInfo> methodMap) {
3324e7c6998e0a953ae55487d4fe122739646f9280aasatok            // Safety net for the case that this function is called before methodMap is set.
3325e7c6998e0a953ae55487d4fe122739646f9280aasatok            final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0;
3326e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileOutputStream fos = null;
3327e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3328e7c6998e0a953ae55487d4fe122739646f9280aasatok                fos = subtypesFile.startWrite();
3329e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlSerializer out = new FastXmlSerializer();
3330e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setOutput(fos, "utf-8");
3331e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startDocument(null, true);
3332e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3333e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startTag(null, NODE_SUBTYPES);
3334e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (String imiId : allSubtypes.keySet()) {
3335e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (isSetMethodMap && !methodMap.containsKey(imiId)) {
3336e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "IME uninstalled or not valid.: " + imiId);
3337e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3338e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3339e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.startTag(null, NODE_IMI);
3340e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.attribute(null, ATTR_ID, imiId);
3341e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final List<InputMethodSubtype> subtypesList = allSubtypes.get(imiId);
3342e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final int N = subtypesList.size();
3343e7c6998e0a953ae55487d4fe122739646f9280aasatok                    for (int i = 0; i < N; ++i) {
3344e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype = subtypesList.get(i);
3345e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.startTag(null, NODE_SUBTYPE);
3346e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
3347e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
3348e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
3349e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_MODE, subtype.getMode());
3350e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
3351e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IS_AUXILIARY,
3352e7c6998e0a953ae55487d4fe122739646f9280aasatok                                String.valueOf(subtype.isAuxiliary() ? 1 : 0));
3353e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.endTag(null, NODE_SUBTYPE);
3354e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3355e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.endTag(null, NODE_IMI);
3356e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3357e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endTag(null, NODE_SUBTYPES);
3358e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endDocument();
3359e7c6998e0a953ae55487d4fe122739646f9280aasatok                subtypesFile.finishWrite(fos);
3360e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3361e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error writing subtypes", e);
3362e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fos != null) {
3363e7c6998e0a953ae55487d4fe122739646f9280aasatok                    subtypesFile.failWrite(fos);
3364e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3365e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3366e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3367e7c6998e0a953ae55487d4fe122739646f9280aasatok
3368e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void readAdditionalInputMethodSubtypes(
3369e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile) {
3370e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (allSubtypes == null || subtypesFile == null) return;
3371e7c6998e0a953ae55487d4fe122739646f9280aasatok            allSubtypes.clear();
3372e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileInputStream fis = null;
3373e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3374e7c6998e0a953ae55487d4fe122739646f9280aasatok                fis = subtypesFile.openRead();
3375e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlPullParser parser = Xml.newPullParser();
3376e7c6998e0a953ae55487d4fe122739646f9280aasatok                parser.setInput(fis, null);
3377e7c6998e0a953ae55487d4fe122739646f9280aasatok                int type = parser.getEventType();
3378e7c6998e0a953ae55487d4fe122739646f9280aasatok                // Skip parsing until START_TAG
3379e7c6998e0a953ae55487d4fe122739646f9280aasatok                while ((type = parser.next()) != XmlPullParser.START_TAG
3380e7c6998e0a953ae55487d4fe122739646f9280aasatok                        && type != XmlPullParser.END_DOCUMENT) {}
3381e7c6998e0a953ae55487d4fe122739646f9280aasatok                String firstNodeName = parser.getName();
3382e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (!NODE_SUBTYPES.equals(firstNodeName)) {
3383e7c6998e0a953ae55487d4fe122739646f9280aasatok                    throw new XmlPullParserException("Xml doesn't start with subtypes");
3384e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3385e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int depth =parser.getDepth();
3386e7c6998e0a953ae55487d4fe122739646f9280aasatok                String currentImiId = null;
3387e7c6998e0a953ae55487d4fe122739646f9280aasatok                ArrayList<InputMethodSubtype> tempSubtypesArray = null;
3388e7c6998e0a953ae55487d4fe122739646f9280aasatok                while (((type = parser.next()) != XmlPullParser.END_TAG
3389e7c6998e0a953ae55487d4fe122739646f9280aasatok                        || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
3390e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (type != XmlPullParser.START_TAG)
3391e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3392e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final String nodeName = parser.getName();
3393e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (NODE_IMI.equals(nodeName)) {
3394e7c6998e0a953ae55487d4fe122739646f9280aasatok                        currentImiId = parser.getAttributeValue(null, ATTR_ID);
3395e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId)) {
3396e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "Invalid imi id found in subtypes.xml");
3397e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3398e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3399e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray = new ArrayList<InputMethodSubtype>();
3400e7c6998e0a953ae55487d4fe122739646f9280aasatok                        allSubtypes.put(currentImiId, tempSubtypesArray);
3401e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } else if (NODE_SUBTYPE.equals(nodeName)) {
3402e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
3403e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "IME uninstalled or not valid.: " + currentImiId);
3404e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3405e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3406e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int icon = Integer.valueOf(
3407e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_ICON));
3408e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int label = Integer.valueOf(
3409e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_LABEL));
3410e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeLocale =
3411e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LOCALE);
3412e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeMode =
3413e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
3414e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeExtraValue =
3415e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
34164a28bde70e23b2ed151d52690da702da7f23cf5esatok                        final boolean isAuxiliary = "1".equals(String.valueOf(
34174a28bde70e23b2ed151d52690da702da7f23cf5esatok                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
3418e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype =
3419e7c6998e0a953ae55487d4fe122739646f9280aasatok                                new InputMethodSubtype(label, icon, imeSubtypeLocale,
3420e7c6998e0a953ae55487d4fe122739646f9280aasatok                                        imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
3421e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray.add(subtype);
3422e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3423e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3424e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (XmlPullParserException e) {
3425e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3426e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3427e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3428e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3429e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3430e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (NumberFormatException e) {
3431e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3432e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3433e7c6998e0a953ae55487d4fe122739646f9280aasatok            } finally {
3434e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fis != null) {
3435e7c6998e0a953ae55487d4fe122739646f9280aasatok                    try {
3436e7c6998e0a953ae55487d4fe122739646f9280aasatok                        fis.close();
3437e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } catch (java.io.IOException e1) {
3438e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "Failed to close.");
3439e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3440e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3441e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3442e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3443e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
3444e7c6998e0a953ae55487d4fe122739646f9280aasatok
34459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
34469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
34479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
34489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3449ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
34509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Permission Denial: can't dump InputMethodManager from from pid="
34519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
34529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
34539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
34549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
34559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
34569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IInputMethod method;
34579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState client;
3458ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
34599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(pw);
3460ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
34619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
34629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("Current Input Method Manager state:");
34639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mMethodList.size();
34649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Input Methods:");
34659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
34669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo info = mMethodList.get(i);
34679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  InputMethod #" + i + ":");
34689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.dump(p, "    ");
34699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
34709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Clients:");
34719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState ci : mClients.values()) {
34729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  Client " + ci + ":");
34739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    client=" + ci.client);
34749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    inputContext=" + ci.inputContext);
34759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    sessionRequested=" + ci.sessionRequested);
34769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    curSession=" + ci.curSession);
34779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3478105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            p.println("  mCurMethodId=" + mCurMethodId);
34799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = mCurClient;
3480b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
3481b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
34829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
34839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mBoundToMethod=" + mBoundToMethod);
34849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurToken=" + mCurToken);
34859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurIntent=" + mCurIntent);
34869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = mCurMethod;
34879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurMethod=" + mCurMethod);
34889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mEnabledSession=" + mEnabledSession);
34899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mShowRequested=" + mShowRequested
34909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
34919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowForced=" + mShowForced
34929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mInputShown=" + mInputShown);
3493d4e6d467cd61d6bec1ae25744a415a96f0a0f760Dianne Hackborn            p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
34949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3495ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3496b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
34979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (client != null) {
34989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
34999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
35009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                client.client.asBinder().dump(fd, args);
35019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
35029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method client dead: " + e);
35039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3504b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3505b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method client.");
35069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3507ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3508b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
35099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (method != null) {
35109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
35119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
35129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                method.asBinder().dump(fd, args);
35139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
35149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method service dead: " + e);
35159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3516b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3517b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method service.");
35189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
35199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
35209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3521