InputMethodManagerService.java revision 6aa037887800e34bd057585106609236c950ca22
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;
43e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawaimport android.app.AppOpsManager;
444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.IUserSwitchObserver;
45f90a33e92a7c8d4040c0e660a62336eb7293d785satokimport android.app.KeyguardManager;
467cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.Notification;
477cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.NotificationManager;
48dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackbornimport android.app.PendingIntent;
495b927c431f54ea47c3333afb7940d79e2e863f1asatokimport android.content.BroadcastReceiver;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface.OnCancelListener;
55d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaokaimport android.content.DialogInterface.OnClickListener;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
57e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.content.IntentFilter;
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ServiceConnection;
596da35a0c1205398b7df4776e359f7794584fb128Brandon Ballingerimport android.content.pm.ApplicationInfo;
604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.content.pm.IPackageManager;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ResolveInfo;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ServiceInfo;
64734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.content.pm.UserInfo;
65e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasaniimport android.content.res.Configuration;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver;
69505e3abb8dd0d8f594280b9510adef74623630d7Alan Viveretteimport android.graphics.drawable.Drawable;
70857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onoratoimport android.inputmethodservice.InputMethodService;
717b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wrightimport android.net.Uri;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
73e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.os.Environment;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IInterface;
774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.IRemoteCallback;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.Process;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
824df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport android.os.ResultReceiver;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.UserHandle;
86734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.os.UserManager;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
89f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.text.style.SuggestionSpan;
9039606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
92f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.util.LruCache;
93ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.util.Pair;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
96e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Slog;
97e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Xml;
98d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaokaimport android.view.ContextThemeWrapper;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
100c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.view.InputChannel;
10105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.LayoutInflater;
10205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.View;
10305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.ViewGroup;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
105ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.EditorInfo;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputBinding;
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethod;
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodInfo;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
110ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.InputMethodSubtype;
111443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawaimport android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
11205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.ArrayAdapter;
11301038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton;
11401038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton.OnCheckedChangeListener;
11505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.RadioButton;
11601038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.Switch;
11705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.TextView;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
119e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.File;
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
121e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileInputStream;
122e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileOutputStream;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
126688bd47fccf1a1373e6287bc49b5b33fad12b7f3satokimport java.util.Collections;
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
1295b927c431f54ea47c3333afb7940d79e2e863f1asatokimport java.util.Locale;
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides a system service that manages input methods.
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InputMethodManagerService extends IInputMethodManager.Stub
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements ServiceConnection, Handler.Callback {
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
1376ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    static final String TAG = "InputMethodManagerService";
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_IM_PICKER = 1;
140ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    static final int MSG_SHOW_IM_SUBTYPE_PICKER = 2;
14147a44916e2fb33cf4751906386d5f5c903b28d8bsatok    static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 3;
142217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    static final int MSG_SHOW_IM_CONFIG = 4;
143ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_INPUT = 1000;
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_INPUT = 1010;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_SOFT_INPUT = 1020;
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_HIDE_SOFT_INPUT = 1030;
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_ATTACH_TOKEN = 1040;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_CREATE_SESSION = 1050;
150ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_START_INPUT = 2000;
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_RESTART_INPUT = 2010;
153ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_METHOD = 3000;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_METHOD = 3010;
156a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn    static final int MSG_SET_ACTIVE = 3020;
1573d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
158ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
15901038492ff0317f0d3cff54d8a7ee36bb31ff175satok    static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
16001038492ff0317f0d3cff54d8a7ee36bb31ff175satok
161bcacc322f83de1fe522081a20e0ac36ec8243763Satoshi Kataoka    static final long TIME_TO_RECONNECT = 3 * 1000;
162ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
163f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20;
164f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1658e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
166b6359414adabab2d64acc8ccc9e3b9c1b800b303satok    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
1678e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
1684e4569dab5c75804b01a19b2d6e6101b445c1c68satok
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Context mContext;
1707d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn    final Resources mRes;
1719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Handler mHandler;
172d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final InputMethodSettings mSettings;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final SettingsObserver mSettingsObserver;
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IWindowManager mIWindowManager;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HandlerCaller mCaller;
176119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final boolean mHasFeature;
1775ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private InputMethodFileManager mFileManager;
17801038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final HardKeyboardListener mHardKeyboardListener;
17901038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final WindowManagerService mWindowManagerService;
180e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa    private final AppOpsManager mAppOpsManager;
181ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1823d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
183ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // All known input methods.  mMethodMap also serves as the global
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // lock for this class.
186d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
187d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
188f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
189f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
190d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    private final InputMethodSubtypeSwitchingController mSwitchingController;
191ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1922c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    // Used to bring IME service up to visible adjustment while it is being shown.
1932c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    final ServiceConnection mVisibleConnection = new ServiceConnection() {
1942c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceConnected(ComponentName name, IBinder service) {
1952c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1962c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1972c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceDisconnected(ComponentName name) {
1982c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1992c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    };
2002c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    boolean mVisibleBound = false;
2012c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
2027cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    // Ongoing notification
203661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private NotificationManager mNotificationManager;
204661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private KeyguardManager mKeyguardManager;
205661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private StatusBarManagerService mStatusBar;
206661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private Notification mImeSwitcherNotification;
207661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private PendingIntent mImeSwitchPendingIntent;
208b858c732f665fe9610f2d913230ae625f44a8caasatok    private boolean mShowOngoingImeSwitcherForPhones;
2097cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean mNotificationShown;
2100a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok    private final boolean mImeSelectedOnBoot;
2117cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
2128c6d477d30e64f3dfae20250b8274ffb37ef7bfaTadashi G. Takaoka    static class SessionState {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ClientState client;
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethod method;
215c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
216c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        IInputMethodSession session;
217c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        InputChannel channel;
218ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "SessionState{uid " + client.uid + " pid " + client.pid
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " method " + Integer.toHexString(
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(method))
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " session " + Integer.toHexString(
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(session))
226c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    + " channel " + channel
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "}";
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState(ClientState _client, IInputMethod _method,
231c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                IInputMethodSession _session, InputChannel _channel) {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = _method;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            session = _session;
235c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            channel = _channel;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
238ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
239c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    static final class ClientState {
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethodClient client;
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputContext inputContext;
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int uid;
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int pid;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final InputBinding binding;
245ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean sessionRequested;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState curSession;
248ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ClientState{" + Integer.toHexString(
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.identityHashCode(this)) + " uid " + uid
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " pid " + pid + "}";
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState(IInputMethodClient _client, IInputContext _inputContext,
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int _uid, int _pid) {
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inputContext = _inputContext;
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uid = _uid;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pid = _pid;
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
265ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, ClientState> mClients
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<IBinder, ClientState>();
268ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
270a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     * Set once the system is ready to run third party code.
271a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     */
272a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    boolean mSystemReady;
273ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
274a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    /**
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Id of the currently selected input method.
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurMethodId;
278ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The current binding sequence number, incremented every time there is
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new bind performed.
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCurSeq;
284ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The client that is currently bound to an input method.
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ClientState mCurClient;
289ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
291b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     * The last window token that gained focus.
292b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     */
293b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    IBinder mCurFocusedWindow;
294ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
295b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    /**
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input context last provided by the current client.
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputContext mCurInputContext;
299ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The attributes last provided by the current client.
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mCurAttribute;
304ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method ID of the input method service that we are currently
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * connected to or in the process of connecting to.
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurId;
310ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
312ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * The current subtype of the current input method.
313ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
314ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private InputMethodSubtype mCurrentSubtype;
315ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3164e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
317f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
318f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes =
319f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
320ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
321e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    // Was the keyguard locked when this client became current?
322e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean mCurClientInKeyguard;
323e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
324ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set to true if our ServiceConnection is currently actively bound to
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a service (whether or not we have gotten its IBinder back yet).
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mHaveConnection;
329ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if the client has asked for the input method to be shown.
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowRequested;
334ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were explicitly told to show the input method.
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowExplicitlyRequested;
339ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were forced to be shown.
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowForced;
344ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we last told the input method to show itself.
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputShown;
349ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The Intent used to connect to the current input method.
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Intent mCurIntent;
354ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The token we have made for the currently active input method, to
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * identify it in the future.
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mCurToken;
360ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If non-null, this is the input method service we are currently connected
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to.
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputMethod mCurMethod;
366ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time that we last initiated a bind to the input method, to determine
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if we should try to disconnect and reconnect to it.
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mLastBindTime;
372ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Have we called mCurMethod.bindInput()?
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mBoundToMethod;
377ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Currently enabled session.  Only touched by service thread, not
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * protected by a lock.
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SessionState mEnabledSession;
383ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * True if the screen is on.  The value is true initially.
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mScreenOn = true;
388ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3893d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    int mCurUserActionNotificationSequenceNumber = 0;
3903d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
391857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
392857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mImeWindowVis;
393857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
39405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog.Builder mDialogBuilder;
39505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog mSwitchingDialog;
39601038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private View mSwitchingDialogTitleView;
39705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private InputMethodInfo[] mIms;
39805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private int[] mSubtypeIds;
3995b927c431f54ea47c3333afb7940d79e2e863f1asatok    private Locale mLastSystemLocale;
4007b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    private boolean mShowImeWithHardKeyboard;
4014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
4024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final IPackageManager mIPackageManager;
403ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SettingsObserver extends ContentObserver {
405fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        String mLastEnabled = "";
406fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SettingsObserver(Handler handler) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(handler);
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver resolver = mContext.getContentResolver();
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resolver.registerContentObserver(Settings.Secure.getUriFor(
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
412ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            resolver.registerContentObserver(Settings.Secure.getUriFor(
413b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok                    Settings.Secure.ENABLED_INPUT_METHODS), false, this);
414b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok            resolver.registerContentObserver(Settings.Secure.getUriFor(
415ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this);
4167b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            resolver.registerContentObserver(Settings.Secure.getUriFor(
4177b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this);
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
419ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4207b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        @Override public void onChange(boolean selfChange, Uri uri) {
4217b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            final Uri showImeUri =
4227b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
4247b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                if (showImeUri.equals(uri)) {
4257b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateKeyboardFromSettingsLocked();
4267b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                } else {
4277b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    boolean enabledChanged = false;
4287b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    String newEnabled = mSettings.getEnabledInputMethodsStr();
4297b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    if (!mLastEnabled.equals(newEnabled)) {
4307b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        mLastEnabled = newEnabled;
4317b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        enabledChanged = true;
4327b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    }
4337b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateInputMethodsFromSettingsLocked(enabledChanged);
434fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
438ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
4404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private void updateActive() {
4414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // Inform the current client of the change in active status
4424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (mCurClient != null && mCurClient.client != null) {
4434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
4444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
4454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
4504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String action = intent.getAction();
4514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (Intent.ACTION_SCREEN_ON.equals(action)) {
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = true;
4533afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                refreshImeWindowVisibilityLocked();
4544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
4579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = false;
45815452a487a4c0274f4217cd060aa54446f30a8f3satok                setImeWindowVisibilityStatusHiddenLocked();
4594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
462105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                hideInputMethodMenu();
4634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // No need to updateActive
464105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                return;
465734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani            } else if (Intent.ACTION_USER_ADDED.equals(action)
466734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                    || Intent.ACTION_USER_REMOVED.equals(action)) {
4672a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                updateCurrentProfileIds();
468734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                return;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4708a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unexpected intent " + intent);
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
474ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
47521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
4764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private boolean isChangingPackagesOfCurrentUser() {
4774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final int userId = getChangingUserId();
4784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final boolean retval = userId == mSettings.getCurrentUserId();
4794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
48081f8b7c66750a0a89c8e6b6037136ca169c96f95satok                if (!retval) {
48181f8b7c66750a0a89c8e6b6037136ca169c96f95satok                    Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
48281f8b7c66750a0a89c8e6b6037136ca169c96f95satok                }
4834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return retval;
4854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
48821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
4894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
4904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return false;
4914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
49221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
4934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
49421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                final int N = mMethodList.size();
49521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curInputMethodId != null) {
49621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    for (int i=0; i<N; i++) {
49721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
49821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (imi.getId().equals(curInputMethodId)) {
49921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            for (String pkg : packages) {
50021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                if (imi.getPackageName().equals(pkg)) {
50121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    if (!doit) {
50221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        return true;
50321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    }
504723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                    resetSelectedInputMethodAndSubtypeLocked("");
50521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    chooseNewDefaultIMELocked();
50621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    return true;
50721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                }
50821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            }
50921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
51021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
51108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                }
51208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu            }
51321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return false;
51421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
515ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
51621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        @Override
51721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
5184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
5194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
5204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
52121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo curIm = null;
5234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int N = mMethodList.size();
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (curInputMethodId != null) {
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<N; i++) {
52721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
528e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imiId = imi.getId();
529e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (imiId.equals(curInputMethodId)) {
53021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            curIm = imi;
53121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
532e7c6998e0a953ae55487d4fe122739646f9280aasatok
53321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        int change = isPackageDisappearing(imi.getPackageName());
534e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (isPackageModified(imi.getPackageName())) {
535e7c6998e0a953ae55487d4fe122739646f9280aasatok                            mFileManager.deleteAllInputMethodSubtypes(imiId);
536e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
53721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (change == PACKAGE_TEMPORARY_CHANGE
53821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                || change == PACKAGE_PERMANENT_CHANGE) {
5398a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Input method uninstalled, disabling: "
54021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    + imi.getComponent());
54121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            setInputMethodEnabledLocked(imi.getId(), false);
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
545ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
546f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(
547f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        mMethodList, mMethodMap, false /* resetDefaultEnabledIme */);
54821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed = false;
550ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
55108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                if (curIm != null) {
55221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    int change = isPackageDisappearing(curIm.getPackageName());
55321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (change == PACKAGE_TEMPORARY_CHANGE
55421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            || change == PACKAGE_PERMANENT_CHANGE) {
55508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        ServiceInfo si = null;
55608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        try {
5574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            si = mIPackageManager.getServiceInfo(
5584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    curIm.getComponent(), 0, mSettings.getCurrentUserId());
5594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        } catch (RemoteException ex) {
56008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
56108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (si == null) {
56208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Uh oh, current input method is no longer around!
56308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Pick another one...
5648a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
56515452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
56621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            if (!chooseNewDefaultIMELocked()) {
56708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                changed = true;
56808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                curIm = null;
5698a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.i(TAG, "Unsetting current input method");
570723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                resetSelectedInputMethodAndSubtypeLocked("");
57108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
57208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
57308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
57421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
575ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
57621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curIm == null) {
57721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // We currently don't have a default input method... is
57821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // one now available?
57921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    changed = chooseNewDefaultIMELocked();
58021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
581ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
58221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (changed) {
583fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(false);
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
588ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
589c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private static final class MethodCallback extends IInputSessionCallback.Stub {
590e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard        private final InputMethodManagerService mParentIMMS;
591c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final IInputMethod mMethod;
592c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final InputChannel mChannel;
593ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
594c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        MethodCallback(InputMethodManagerService imms, IInputMethod method,
595c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel) {
596e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard            mParentIMMS = imms;
597c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mMethod = method;
598c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mChannel = channel;
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
600ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
601e7c6998e0a953ae55487d4fe122739646f9280aasatok        @Override
602c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        public void sessionCreated(IInputMethodSession session) {
6036b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            long ident = Binder.clearCallingIdentity();
6046b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            try {
6056b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                mParentIMMS.onSessionCreated(mMethod, session, mChannel);
6066b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            } finally {
6076b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                Binder.restoreCallingIdentity(ident);
6086b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            }
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
611ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
61201038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private class HardKeyboardListener
61301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            implements WindowManagerService.OnHardKeyboardStatusChangeListener {
61401038492ff0317f0d3cff54d8a7ee36bb31ff175satok        @Override
6157b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        public void onHardKeyboardStatusChange(boolean available) {
6167b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED,
6177b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        available ? 1 : 0));
61801038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
61901038492ff0317f0d3cff54d8a7ee36bb31ff175satok
6207b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        public void handleHardKeyboardStatusChange(boolean available) {
62101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            if (DEBUG) {
6227b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                Slog.w(TAG, "HardKeyboardStatusChanged: available=" + available);
62301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
62401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            synchronized(mMethodMap) {
62501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
62601038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        && mSwitchingDialog.isShowing()) {
62701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mSwitchingDialogTitleView.findViewById(
62801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            com.android.internal.R.id.hard_keyboard_section).setVisibility(
62901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    available ? View.VISIBLE : View.GONE);
63001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
63101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
63201038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
63301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    }
63401038492ff0317f0d3cff54d8a7ee36bb31ff175satok
63501038492ff0317f0d3cff54d8a7ee36bb31ff175satok    public InputMethodManagerService(Context context, WindowManagerService windowManager) {
6364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mIPackageManager = AppGlobals.getPackageManager();
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
6387d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn        mRes = context.getResources();
6399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new Handler(this);
6409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIWindowManager = IWindowManager.Stub.asInterface(
6419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.WINDOW_SERVICE));
642ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
643e7c6998e0a953ae55487d4fe122739646f9280aasatok            @Override
6449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void executeMessage(Message msg) {
6459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleMessage(msg);
6469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
647ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        }, true /*asyncHandler*/);
64801038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mWindowManagerService = windowManager;
649e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
65001038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mHardKeyboardListener = new HardKeyboardListener();
651119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        mHasFeature = context.getPackageManager().hasSystemFeature(
652119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                PackageManager.FEATURE_INPUT_METHODS);
6537cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6547cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification = new Notification();
6557cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
6567cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.when = 0;
6577cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT;
6587cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.tickerText = null;
6597cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.defaults = 0; // please be quiet
6607cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.sound = null;
6617cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.vibrate = null;
662590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
663590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler        // Tag this notification specially so SystemUI knows it's important
664fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
665fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.category = Notification.CATEGORY_SYSTEM;
666590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
6677cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
668683e2383c8549f95e00bade15daed3dbddf13950satok        mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
669b858c732f665fe9610f2d913230ae625f44a8caasatok
670b858c732f665fe9610f2d913230ae625f44a8caasatok        mShowOngoingImeSwitcherForPhones = false;
6717cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final IntentFilter broadcastFilter = new IntentFilter();
6734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
6744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
6754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
676734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
677734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
6784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
679ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
6807cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mNotificationShown = false;
6814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        int userId = 0;
6824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        try {
6834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            ActivityManagerNative.getDefault().registerUserSwitchObserver(
6844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    new IUserSwitchObserver.Stub() {
6854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
6875ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            synchronized(mMethodMap) {
6885ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                                switchUserLocked(newUserId);
6895ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            }
6904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            if (reply != null) {
6914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                try {
6924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    reply.sendResult(null);
6934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                } catch (RemoteException e) {
6944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                }
6954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            }
6964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
6974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
6984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
7004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
7014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    });
7024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
7034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } catch (RemoteException e) {
7044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
7054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
70681f8b7c66750a0a89c8e6b6037136ca169c96f95satok        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
707913a8925c07e854a80bf5df87561f290d3a56d61satok
708d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        // mSettings should be created before buildInputMethodListLocked
709df31ae6a3011d47421a6ac10021f9649dc34a156satok        mSettings = new InputMethodSettings(
7104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
7112a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
7125ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, userId);
7135a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
7145a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
7155a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSettings, context);
7165a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
7170a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
7180a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        // Just checking if defaultImiId is empty or not
7194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
720f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (DEBUG) {
721f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "Initial default ime = " + defaultImiId);
722f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
7230a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
7240a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
7255a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
7265a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            buildInputMethodListLocked(mMethodList, mMethodMap,
7275a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
7285a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
729d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        mSettings.enableAllIMEsIfThereIsNoEnabledIME();
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7310a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!mImeSelectedOnBoot) {
7320a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            Slog.w(TAG, "No IME selected. Choose the most applicable IME.");
7335a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            synchronized (mMethodMap) {
7345a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                resetDefaultImeLocked(context);
7355a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
7365b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7375b927c431f54ea47c3333afb7940d79e2e863f1asatok
7385b927c431f54ea47c3333afb7940d79e2e863f1asatok        mSettingsObserver = new SettingsObserver(mHandler);
7395a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
7405a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            updateFromSettingsLocked(true);
7415a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
7425b927c431f54ea47c3333afb7940d79e2e863f1asatok
7435b927c431f54ea47c3333afb7940d79e2e863f1asatok        // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
7445b927c431f54ea47c3333afb7940d79e2e863f1asatok        // according to the new system locale.
7455b927c431f54ea47c3333afb7940d79e2e863f1asatok        final IntentFilter filter = new IntentFilter();
7465b927c431f54ea47c3333afb7940d79e2e863f1asatok        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
7475b927c431f54ea47c3333afb7940d79e2e863f1asatok        mContext.registerReceiver(
7485b927c431f54ea47c3333afb7940d79e2e863f1asatok                new BroadcastReceiver() {
7495b927c431f54ea47c3333afb7940d79e2e863f1asatok                    @Override
7505b927c431f54ea47c3333afb7940d79e2e863f1asatok                    public void onReceive(Context context, Intent intent) {
7515b927c431f54ea47c3333afb7940d79e2e863f1asatok                        synchronized(mMethodMap) {
752ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            resetStateIfCurrentLocaleChangedLocked();
7539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
7549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7555b927c431f54ea47c3333afb7940d79e2e863f1asatok                }, filter);
7565b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7575b927c431f54ea47c3333afb7940d79e2e863f1asatok
7585b927c431f54ea47c3333afb7940d79e2e863f1asatok    private void resetDefaultImeLocked(Context context) {
7595b927c431f54ea47c3333afb7940d79e2e863f1asatok        // Do not reset the default (current) IME when it is a 3rd-party IME
7608e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        if (mCurMethodId != null
7618e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
7625b927c431f54ea47c3333afb7940d79e2e863f1asatok            return;
7635b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7645b927c431f54ea47c3333afb7940d79e2e863f1asatok
7655b927c431f54ea47c3333afb7940d79e2e863f1asatok        InputMethodInfo defIm = null;
7665b927c431f54ea47c3333afb7940d79e2e863f1asatok        for (InputMethodInfo imi : mMethodList) {
7676aa037887800e34bd057585106609236c950ca22Yohei Yukawa            if (defIm == null && mSystemReady) {
7686aa037887800e34bd057585106609236c950ca22Yohei Yukawa                final Locale systemLocale = context.getResources().getConfiguration().locale;
7696aa037887800e34bd057585106609236c950ca22Yohei Yukawa                if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
7706aa037887800e34bd057585106609236c950ca22Yohei Yukawa                        true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
7716aa037887800e34bd057585106609236c950ca22Yohei Yukawa                        InputMethodUtils.SUBTYPE_MODE_ANY)) {
7725b927c431f54ea47c3333afb7940d79e2e863f1asatok                    defIm = imi;
7735b927c431f54ea47c3333afb7940d79e2e863f1asatok                    Slog.i(TAG, "Selected default: " + imi.getId());
7745b927c431f54ea47c3333afb7940d79e2e863f1asatok                }
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7765b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7775b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm == null && mMethodList.size() > 0) {
7788e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            defIm = InputMethodUtils.getMostApplicableDefaultIME(
7798e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
7805baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            if (defIm != null) {
7815baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim                Slog.i(TAG, "Default found, using " + defIm.getId());
7825baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            } else {
7835baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim                Slog.i(TAG, "No default found");
7845baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            }
7855b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7865b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm != null) {
7875b927c431f54ea47c3333afb7940d79e2e863f1asatok            setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
7885b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7895b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7905b927c431f54ea47c3333afb7940d79e2e863f1asatok
7917f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka    private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
7927f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            final boolean resetDefaultEnabledIme) {
7934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!mSystemReady) {
7944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // not system ready
7954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
7964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
7974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final Locale newLocale = mRes.getConfiguration().locale;
7984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!updateOnlyWhenLocaleChanged
7994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
8004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
8014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                hideCurrentInputLocked(0, null);
8024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurMethodId = null;
8032ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
8044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
8054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
8064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.i(TAG, "Locale has been changed to " + newLocale);
8074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
8087f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            buildInputMethodListLocked(mMethodList, mMethodMap, resetDefaultEnabledIme);
8094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
8104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selectedImiId = mSettings.getSelectedInputMethod();
8114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (TextUtils.isEmpty(selectedImiId)) {
8124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // This is the first time of the user switch and
8134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // set the current ime to the proper one.
8144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    resetDefaultImeLocked(mContext);
8154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
816d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka            } else {
817d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                // If the locale is changed, needs to reset the default ime
818d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                resetDefaultImeLocked(mContext);
8194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
820fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            updateFromSettingsLocked(true);
8214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            mLastSystemLocale = newLocale;
8224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
8234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                try {
8244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    startInputInnerLocked();
8254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } catch (RuntimeException e) {
8264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    Slog.w(TAG, "Unexpected exception", e);
8274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
8284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
8294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
8304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
832ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka    private void resetStateIfCurrentLocaleChangedLocked() {
8337f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */,
8347f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka                true /* resetDefaultImeLocked */);
8354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8375ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private void switchUserLocked(int newUserId) {
8384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mSettings.setCurrentUserId(newUserId);
8392a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
8405ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        // InputMethodFileManager should be reset when the user is changed
8415ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
8427f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
8437c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // For secondary users, the list of enabled IMEs may not have been updated since the
8447c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // callbacks to PackageMonitor are ignored for the secondary user. Here, defaultImiId may
8457c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // not be empty even if the IME has been uninstalled by the primary user.
8467c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // Even in such cases, IMMS works fine because it will find the most applicable
8477c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // IME for that user.
848ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
8497f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        if (DEBUG) {
8507f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId);
8517f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        }
8527f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(false  /* updateOnlyWhenLocaleChanged */,
853ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                initialUserSwitch /* needsToResetDefaultIme */);
854ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        if (initialUserSwitch) {
855ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka            InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(),
856ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
857ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        }
8584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8602a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy    void updateCurrentProfileIds() {
8612a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        List<UserInfo> profiles =
8622a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
8632a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
8642a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        for (int i = 0; i < currentProfileIds.length; i++) {
8652a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy            currentProfileIds[i] = profiles.get(i).id;
866734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        }
8672a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        mSettings.setCurrentProfileIds(currentProfileIds);
868734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani    }
869734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani
8709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
8729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws RemoteException {
8739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.onTransact(code, data, reply, flags);
8759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
8769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The input method manager only throws security exceptions, so let's
8779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // log all others.
8789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!(e instanceof SecurityException)) {
879164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf(TAG, "Input Method Manager Crash", e);
8809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
885a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning(StatusBarManagerService statusBar) {
886a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        synchronized (mMethodMap) {
8874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
8884e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "--- systemReady");
8894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
890a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            if (!mSystemReady) {
891a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn                mSystemReady = true;
8924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mKeyguardManager =
8934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
894661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mNotificationManager = (NotificationManager)
895661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
896661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mStatusBar = statusBar;
897661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                statusBar.setIconVisibility("ime", false);
898661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                updateImeWindowStatusLocked();
899b858c732f665fe9610f2d913230ae625f44a8caasatok                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
900b858c732f665fe9610f2d913230ae625f44a8caasatok                        com.android.internal.R.bool.show_ongoing_ime_switcher);
90101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mShowOngoingImeSwitcherForPhones) {
90201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mWindowManagerService.setOnHardKeyboardStatusChangeListener(
90301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mHardKeyboardListener);
90401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
905f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(mMethodList, mMethodMap,
906f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
9070a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (!mImeSelectedOnBoot) {
9080a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                    Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
909ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    resetStateIfCurrentLocaleChangedLocked();
910ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
911ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mContext.getPackageManager(),
912ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mSettings.getEnabledInputMethodListLocked());
9130a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
9140a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                mLastSystemLocale = mRes.getConfiguration().locale;
915cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                try {
916cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    startInputInnerLocked();
917cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                } catch (RuntimeException e) {
9188a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Unexpected exception", e);
919cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
920a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            }
921a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
923ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
92415452a487a4c0274f4217cd060aa54446f30a8f3satok    private void setImeWindowVisibilityStatusHiddenLocked() {
92515452a487a4c0274f4217cd060aa54446f30a8f3satok        mImeWindowVis = 0;
92615452a487a4c0274f4217cd060aa54446f30a8f3satok        updateImeWindowStatusLocked();
92715452a487a4c0274f4217cd060aa54446f30a8f3satok    }
92815452a487a4c0274f4217cd060aa54446f30a8f3satok
9293afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    private void refreshImeWindowVisibilityLocked() {
9303afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final Configuration conf = mRes.getConfiguration();
9313afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean haveHardKeyboard = conf.keyboard
9323afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                != Configuration.KEYBOARD_NOKEYS;
9333afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean hardKeyShown = haveHardKeyboard
9343afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                && conf.hardKeyboardHidden
9353afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                        != Configuration.HARDKEYBOARDHIDDEN_YES;
936e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
937e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean isScreenLocked = isKeyguardLocked();
938e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean inputActive = !isScreenLocked && (mInputShown || hardKeyShown);
93936439b43121751ae94e703da52b2763aa17d0720John Spurlock        // We assume the softkeyboard is shown when the input is active as long as the
94036439b43121751ae94e703da52b2763aa17d0720John Spurlock        // hard keyboard is not shown.
94136439b43121751ae94e703da52b2763aa17d0720John Spurlock        final boolean inputVisible = inputActive && !hardKeyShown;
94236439b43121751ae94e703da52b2763aa17d0720John Spurlock        mImeWindowVis = (inputActive ? InputMethodService.IME_ACTIVE : 0)
94336439b43121751ae94e703da52b2763aa17d0720John Spurlock                | (inputVisible ? InputMethodService.IME_VISIBLE : 0);
9443afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        updateImeWindowStatusLocked();
9453afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    }
9463afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok
94715452a487a4c0274f4217cd060aa54446f30a8f3satok    private void updateImeWindowStatusLocked() {
948dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok        setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
949661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    }
950661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn
9514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // ---------------------------------------------------------------------------------------
9524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
9534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 1) it comes from the system process
9544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 2) the calling process' user id is identical to the current user id IMMS thinks.
9554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean calledFromValidUser() {
9564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int uid = Binder.getCallingUid();
9574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int userId = UserHandle.getUserId(uid);
9584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
9594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
9604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
9614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + " calling userId = " + userId + ", foreground user id = "
96287c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
96387c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + InputMethodUtils.getApiCallStack());
9644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9652a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
9664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return true;
9674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
968135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka
969135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
970135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // foreground user, not for the user of that process. Accordingly InputMethodManagerService
971135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // must not manage background users' states in any functions.
972135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Note that privacy-sensitive IPCs, such as setInputMethod, are still securely guarded
973135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // by a token.
974135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        if (mContext.checkCallingOrSelfPermission(
975135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
976135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        == PackageManager.PERMISSION_GRANTED) {
977135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            if (DEBUG) {
978135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                Slog.d(TAG, "--- Access granted because the calling process has "
979135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        + "the INTERACT_ACROSS_USERS_FULL permission");
980135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            }
981135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            return true;
982135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        }
9830766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka        Slog.w(TAG, "--- IPC called from background users. Ignore. \n"
9840766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                + InputMethodUtils.getStackTrace());
985135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        return false;
9864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
98822c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
98922c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    /**
99022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * Returns true iff the caller is identified to be the current input method with the token.
99122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @param token The window token given to the input method when it was started.
99222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @return true if and only if non-null valid token is specified.
99322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     */
99422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    private boolean calledWithValidToken(IBinder token) {
99522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        if (token == null || mCurToken != token) {
99622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            return false;
99722c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        }
99822c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        return true;
99922c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    }
100022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
10014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean bindCurrentInputMethodService(
10024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Intent service, ServiceConnection conn, int flags) {
10034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (service == null || conn == null) {
10044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
10054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
10064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
100727b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani        return mContext.bindServiceAsUser(service, conn, flags,
100827b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                new UserHandle(mSettings.getCurrentUserId()));
10094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
10104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
1011e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getInputMethodList() {
10134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
10144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
10164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ArrayList<InputMethodInfo>(mMethodList);
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1022e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getEnabledInputMethodList() {
10244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
10254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
10274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1029d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return mSettings.getEnabledInputMethodListLocked();
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10338e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    /**
1034b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka     * @param imiId if null, returns enabled subtypes for the current imi
10358e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     * @return enabled subtypes of the specified imi
10368e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     */
1037e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1038b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
103916331c8a1d33defccc5cbb18694def79196c921bsatok            boolean allowsImplicitlySelectedSubtypes) {
10404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
10414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
1042b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            return Collections.<InputMethodSubtype>emptyList();
10434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
104467ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        synchronized (mMethodMap) {
1045b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            final InputMethodInfo imi;
1046b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imiId == null && mCurMethodId != null) {
10478e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                imi = mMethodMap.get(mCurMethodId);
1048b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            } else {
1049b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                imi = mMethodMap.get(imiId);
1050b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            }
1051b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imi == null) {
1052b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                return Collections.<InputMethodSubtype>emptyList();
10538e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            }
10548e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            return mSettings.getEnabledInputMethodSubtypeListLocked(
10558e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mContext, imi, allowsImplicitlySelectedSubtypes);
105667ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        }
105767ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok    }
105867ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok
1059e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addClient(IInputMethodClient client,
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IInputContext inputContext, int uid, int pid) {
10624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClients.put(client.asBinder(), new ClientState(client,
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    inputContext, uid, pid));
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1070ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1071e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeClient(IInputMethodClient client) {
10734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1077c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ClientState cs = mClients.remove(client.asBinder());
1078c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (cs != null) {
1079c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
1080c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1083ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void executeOrSendMessage(IInterface target, Message msg) {
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         if (target.asBinder() instanceof Binder) {
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             mCaller.sendMessage(msg);
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         } else {
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             handleMessage(msg);
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             msg.recycle();
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         }
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1092ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1093b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void unbindCurrentClientLocked() {
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != null) {
10958a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client = "
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurClient.client.asBinder());
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBoundToMethod) {
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBoundToMethod = false;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_INPUT, mCurMethod));
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1104a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn
1105a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1106a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    MSG_SET_ACTIVE, 0, mCurClient));
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient.sessionRequested = false;
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient = null;
1111ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1112105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1115ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getImeShowFlags() {
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_FORCED
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    | InputMethod.SHOW_EXPLICIT;
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mShowExplicitlyRequested) {
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_EXPLICIT;
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1126ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getAppShowFlags() {
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_FORCED;
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mShowExplicitlyRequested) {
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_IMPLICIT;
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1136ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11377663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult attachNewInputLocked(boolean initial) {
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBoundToMethod) {
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBoundToMethod = true;
11429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SessionState session = mCurClient.curSession;
11449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initial) {
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_START_INPUT, session, mCurInputContext, mCurAttribute));
11479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_RESTART_INPUT, session, mCurInputContext, mCurAttribute));
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowRequested) {
11528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
11534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            showCurrentInputLocked(getAppShowFlags(), null);
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11551951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown        return new InputBindResult(session.session,
11563d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                (session.channel != null ? session.channel.dup() : null),
11573d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
11589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1159ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBindResult startInputLocked(IInputMethodClient client,
11617663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If no method is currently selected, do nothing.
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethodId == null) {
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNoBinding;
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1166ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState cs = mClients.get(client.asBinder());
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cs == null) {
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("unknown client "
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + client.asBinder());
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1172ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check with the window manager to make sure this client actually
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // has a window with focus.  If not, reject.  This is thread safe
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // because if the focus changes some time before or after, the
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // next client receiving focus that has any interest in input will
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // be calling through here after that change happens.
11808a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Starting input on non-focused client " + cs.client
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1186ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11877663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
11887663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    }
11897663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11907663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult startInputUncheckedLocked(ClientState cs,
11917663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11927663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        // If no method is currently selected, do nothing.
11937663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        if (mCurMethodId == null) {
11947663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            return mNoBinding;
11957663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        }
11967663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != cs) {
1198e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            // Was the keyguard locked when switching over to the new client?
1199e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            mCurClientInKeyguard = isKeyguardLocked();
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the client is changing, we need to switch over to the new
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // one.
1202b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
12038a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "switching to client: client = "
1204e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
12069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the screen is on, inform the new client it is active
12079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mScreenOn) {
1208a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                executeOrSendMessage(cs.client, mCaller.obtainMessageIO(
1209a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, cs));
12109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1212ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Bump up the sequence for this client and attach it.
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurSeq++;
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurSeq <= 0) mCurSeq = 1;
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurClient = cs;
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurInputContext = inputContext;
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurAttribute = attribute;
1219ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check if the input method is changing.
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurId != null && mCurId.equals(mCurMethodId)) {
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cs.curSession != null) {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Fast case: if we are already connected to the input method,
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // then just return it.
12257663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return attachNewInputLocked(
12267663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mHaveConnection) {
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Return to client, and we will get back with it when
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we have had a session made for it.
1232c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(cs);
12333d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    return new InputBindResult(null, null, mCurId, mCurSeq,
12343d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            mCurUserActionNotificationSequenceNumber);
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (SystemClock.uptimeMillis()
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        < (mLastBindTime+TIME_TO_RECONNECT)) {
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // In this case we have connected to the service, but
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // don't yet have its interface.  If it hasn't been too
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // long since we did the connection, we'll return to
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the client and wait to get the service interface so
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we can report back.  If it has been too long, we want
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to fall through so we can try a disconnect/reconnect
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to see if we can get back in touch with the service.
12443d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    return new InputBindResult(null, null, mCurId, mCurSeq,
12453d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            mCurUserActionNotificationSequenceNumber);
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1247ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                    EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
1248ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                            mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1252ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1253a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        return startInputInnerLocked();
1254a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    }
1255ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1256a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    InputBindResult startInputInnerLocked() {
1257a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (mCurMethodId == null) {
1258a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            return mNoBinding;
1259a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1260ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1261a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (!mSystemReady) {
1262a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // If the system is not yet ready, we shouldn't be running third
1263a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // party code.
12643d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            return new InputBindResult(null, null, mCurMethodId, mCurSeq,
12653d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    mCurUserActionNotificationSequenceNumber);
1266a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1267ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(mCurMethodId);
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1272ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12732ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn        unbindCurrentMethodLocked(false, true);
1274ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent.setComponent(info.getComponent());
1277dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1278dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                com.android.internal.R.string.input_method_binding_label);
1279dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1280dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
12814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
1282f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND
1283f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_SHOWING_UI)) {
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastBindTime = SystemClock.uptimeMillis();
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHaveConnection = true;
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurId = info.getId();
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurToken = new Binder();
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
1289ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIWindowManager.addWindowToken(mCurToken,
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12943d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            return new InputBindResult(null, null, mCurId, mCurSeq,
12953d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    mCurUserActionNotificationSequenceNumber);
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIntent = null;
12988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Failure connecting to input method service: "
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurIntent);
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1303ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1304e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBindResult startInput(IInputMethodClient client,
13067663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
13074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
13084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
13094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final long ident = Binder.clearCallingIdentity();
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
13137663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return startInputLocked(client, inputContext, attribute, controlFlags);
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1319ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1320e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishInput(IInputMethodClient client) {
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1323ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1324e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceConnected(ComponentName name, IBinder service) {
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCurMethod = IInputMethod.Stub.asInterface(service);
1329cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                if (mCurToken == null) {
13308a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Service connected without a token!");
13312ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                    unbindCurrentMethodLocked(false, false);
1332cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    return;
1333cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1334e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
1335cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
1336cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1338c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
1339c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(mCurClient);
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
13449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1345c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void onSessionCreated(IInputMethod method, IInputMethodSession session,
1346c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel channel) {
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
13489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && method != null
13499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && mCurMethod.asBinder() == method.asBinder()) {
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1351c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
13529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCurClient.curSession = new SessionState(mCurClient,
1353c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                            method, session, channel);
13547663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    InputBindResult res = attachNewInputLocked(true);
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (res.method != null) {
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                MSG_BIND_METHOD, mCurClient.client, res));
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1359c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return;
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1363c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1364c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        // Session abandoned.  Close its associated input channel.
1365c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        channel.dispose();
13669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1367ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13682ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn    void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
13692c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mVisibleBound) {
13702c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
13712c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
13722c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
13732c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1374b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mHaveConnection) {
1375b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mContext.unbindService(this);
1376b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mHaveConnection = false;
1377b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1378ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1379b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mCurToken != null) {
1380b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            try {
13818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
13822ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
1383e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    // The current IME is shown. Hence an IME switch (transition) is happening.
1384e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    mWindowManagerService.saveLastInputMethodWindowForTransition();
1385e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                }
1386b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mIWindowManager.removeWindowToken(mCurToken);
1387b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            } catch (RemoteException e) {
1388b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
1389b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mCurToken = null;
1390b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1391ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1392105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mCurId = null;
1393b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        clearCurMethodLocked();
1394ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1395b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (reportToClient && mCurClient != null) {
1396b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1397b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
1398b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1399b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    }
1400c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1401c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void requestClientSessionLocked(ClientState cs) {
1402c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (!cs.sessionRequested) {
1403c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
1404c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
1405c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            cs.sessionRequested = true;
1406c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
1407c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    MSG_CREATE_SESSION, mCurMethod, channels[1],
1408c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    new MethodCallback(this, mCurMethod, channels[0])));
1409c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
1410c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1411c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1412c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void clearClientSessionLocked(ClientState cs) {
1413c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        finishSessionLocked(cs.curSession);
1414c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.curSession = null;
1415c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.sessionRequested = false;
1416c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1417c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1418c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private void finishSessionLocked(SessionState sessionState) {
1419c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (sessionState != null) {
1420c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.session != null) {
1421c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                try {
1422c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    sessionState.session.finishSession();
1423c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } catch (RemoteException e) {
1424c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    Slog.w(TAG, "Session failed to close due to remote exception", e);
1425c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    setImeWindowVisibilityStatusHiddenLocked();
1426c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
1427c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.session = null;
1428c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
1429c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.channel != null) {
1430c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel.dispose();
1431c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel = null;
14320c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            }
14330c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor        }
14340c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor    }
1435ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1436b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void clearCurMethodLocked() {
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
14389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState cs : mClients.values()) {
1439c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14410c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor
1442c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            finishSessionLocked(mEnabledSession);
14430c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            mEnabledSession = null;
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurMethod = null;
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1446661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        if (mStatusBar != null) {
1447661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn            mStatusBar.setIconVisibility("ime", false);
1448661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        }
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1450ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1451e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceDisconnected(ComponentName name) {
14539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14548a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mCurIntent=" + mCurIntent);
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && mCurIntent != null
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && name.equals(mCurIntent.getComponent())) {
1458b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                clearCurMethodLocked();
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We consider this to be a new bind attempt, since the system
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // should now try to restart the service for us.
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastBindTime = SystemClock.uptimeMillis();
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mShowRequested = mInputShown;
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputShown = false;
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1472f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
1477a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                if (!calledWithValidToken(token)) {
1478a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    final int uid = Binder.getCallingUid();
1479a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    Slog.e(TAG, "Ignoring updateStatusIcon due to an invalid token. uid:" + uid
1480a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                            + " token:" + token);
1481a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    return;
1482a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                }
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (iconId == 0) {
14848a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
1485661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1486661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", false);
1487661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (packageName != null) {
14898a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
14906179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    CharSequence contentDescription = null;
14916179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    try {
14924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        // Use PackageManager to load label
14934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        final PackageManager packageManager = mContext.getPackageManager();
14946179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        contentDescription = packageManager.getApplicationLabel(
14954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mIPackageManager.getApplicationInfo(packageName, 0,
14964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                        mSettings.getCurrentUserId()));
14974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    } catch (RemoteException e) {
14986179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        /* ignore */
14996179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    }
1500661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1501661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIcon("ime", packageName, iconId, 0,
1502661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                contentDescription  != null
1503661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                        ? contentDescription.toString() : null);
1504661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", true);
1505661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
15099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
15137cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean needsToShowImeSwitchOngoingNotification() {
15147cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        if (!mShowOngoingImeSwitcherForPhones) return false;
1515807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk        if (mSwitchingDialog != null) return false;
15162c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        if (isScreenLocked()) return false;
15177cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        synchronized (mMethodMap) {
15187cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
15197cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            final int N = imis.size();
1520b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N > 2) return true;
1521b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N < 1) return false;
1522b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int nonAuxCount = 0;
1523b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int auxCount = 0;
1524b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype nonAuxSubtype = null;
1525b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype auxSubtype = null;
15267cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            for(int i = 0; i < N; ++i) {
15277cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final InputMethodInfo imi = imis.get(i);
15288e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final List<InputMethodSubtype> subtypes =
15298e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
15307cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final int subtypeCount = subtypes.size();
15317cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                if (subtypeCount == 0) {
1532b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    ++nonAuxCount;
15337cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
15347cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    for (int j = 0; j < subtypeCount; ++j) {
1535b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        final InputMethodSubtype subtype = subtypes.get(j);
1536b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        if (!subtype.isAuxiliary()) {
1537b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++nonAuxCount;
1538b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            nonAuxSubtype = subtype;
1539b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        } else {
1540b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++auxCount;
1541b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            auxSubtype = subtype;
15427cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        }
15437cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
15447cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
15457cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            }
1546b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (nonAuxCount > 1 || auxCount > 1) {
1547b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1548b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            } else if (nonAuxCount == 1 && auxCount == 1) {
1549b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                if (nonAuxSubtype != null && auxSubtype != null
15509747f8977c55013e656a1e666a1647bb331954cesatok                        && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
15519747f8977c55013e656a1e666a1647bb331954cesatok                                || auxSubtype.overridesImplicitlyEnabledSubtype()
15529747f8977c55013e656a1e666a1647bb331954cesatok                                || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
1553b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
1554b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    return false;
1555b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                }
1556b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1557b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            }
1558b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            return false;
15597cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        }
15607cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    }
15617cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
1562e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean isKeyguardLocked() {
1563e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
1564e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    }
1565e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
15664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Caution! This method is called in this class. Handle multi-user carefully
1567dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("deprecation")
1568f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
1569857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
15704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final long ident = Binder.clearCallingIdentity();
157106487a58be22b100daf3f950b9a1d25c3ea42aa2satok        try {
157222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
157322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
157422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring setImeWindowStatus due to an invalid token. uid:" + uid
157522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + " token:" + token);
157606487a58be22b100daf3f950b9a1d25c3ea42aa2satok                return;
157706487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
157806487a58be22b100daf3f950b9a1d25c3ea42aa2satok            synchronized (mMethodMap) {
1579e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                // apply policy for binder calls
1580e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
1581e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    vis = 0;
1582e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                }
1583857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mImeWindowVis = vis;
1584857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mBackDisposition = backDisposition;
1585217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                final boolean iconVisibility = ((vis & (InputMethodService.IME_ACTIVE)) != 0)
1586217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                        && (mWindowManagerService.isHardKeyboardAvailable()
1587217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                                || (vis & (InputMethodService.IME_VISIBLE)) != 0);
1588b605fecd9e4282823af754b3968b21205d64554aJason Monk                final boolean needsToShowImeSwitcher = iconVisibility
1589b605fecd9e4282823af754b3968b21205d64554aJason Monk                        && needsToShowImeSwitchOngoingNotification();
1590b605fecd9e4282823af754b3968b21205d64554aJason Monk                if (mStatusBar != null) {
1591b605fecd9e4282823af754b3968b21205d64554aJason Monk                    mStatusBar.setImeWindowStatus(token, vis, backDisposition,
1592b605fecd9e4282823af754b3968b21205d64554aJason Monk                            needsToShowImeSwitcher);
1593b605fecd9e4282823af754b3968b21205d64554aJason Monk                }
15945bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
1595b605fecd9e4282823af754b3968b21205d64554aJason Monk                if (imi != null && needsToShowImeSwitcher) {
15964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // Used to load label
15977cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    final CharSequence title = mRes.getText(
15987cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                            com.android.internal.R.string.select_input_method);
1599b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                    final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
1600b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            mContext, imi, mCurrentSubtype);
16015bc8e732bd831a308a5bc1720b0e4c9300d32f67satok
1602255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                    mImeSwitcherNotification.color = mContext.getResources().getColor(
1603255dd04271088590fedc46c8e22b2fd4ab142d39Selim Cinek                            com.android.internal.R.color.system_notification_accent_color);
16047cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    mImeSwitcherNotification.setLatestEventInfo(
16055bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                            mContext, title, summary, mImeSwitchPendingIntent);
1606e463c745ef6901121837e88ca8597d062843b9ddJason Monk                    if ((mNotificationManager != null)
1607e463c745ef6901121837e88ca8597d062843b9ddJason Monk                            && !mWindowManagerService.hasNavigationBar()) {
1608135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1609b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            Slog.d(TAG, "--- show notification: label =  " + summary);
1610135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1611135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.notifyAsUser(null,
1612661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                com.android.internal.R.string.select_input_method,
1613135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                mImeSwitcherNotification, UserHandle.ALL);
1614661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mNotificationShown = true;
1615661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
16167cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
1617661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mNotificationShown && mNotificationManager != null) {
1618135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1619135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                            Slog.d(TAG, "--- hide notification");
1620135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1621135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.cancelAsUser(null,
1622135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                com.android.internal.R.string.select_input_method, UserHandle.ALL);
16237cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        mNotificationShown = false;
16247cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
16257cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
162606487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
162706487a58be22b100daf3f950b9a1d25c3ea42aa2satok        } finally {
162806487a58be22b100daf3f950b9a1d25c3ea42aa2satok            Binder.restoreCallingIdentity(ident);
162906487a58be22b100daf3f950b9a1d25c3ea42aa2satok        }
163006487a58be22b100daf3f950b9a1d25c3ea42aa2satok    }
163106487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1632e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1633f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
16344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
16354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
16364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1637f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1638f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
1639f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            for (int i = 0; i < spans.length; ++i) {
1640f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                SuggestionSpan ss = spans[i];
164142c5a1666c4e576ccd5974233513100aad2c1534satok                if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
1642f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                    mSecureSuggestionSpans.put(ss, currentImi);
1643f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                }
1644f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1645f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1646f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1647f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1648e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1649f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
16504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
16514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
16524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1653f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1654f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
1655f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            // TODO: Do not send the intent if the process of the targetImi is already dead.
1656f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            if (targetImi != null) {
1657f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final String[] suggestions = span.getSuggestions();
1658f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                if (index < 0 || index >= suggestions.length) return false;
165942c5a1666c4e576ccd5974233513100aad2c1534satok                final String className = span.getNotificationTargetClassName();
1660f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final Intent intent = new Intent();
1661f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // Ensures that only a class in the original IME package will receive the
1662f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // notification.
166342c5a1666c4e576ccd5974233513100aad2c1534satok                intent.setClassName(targetImi.getPackageName(), className);
1664f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
1665f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
1666f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
1667f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
1668f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                final long ident = Binder.clearCallingIdentity();
1669f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                try {
1670f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
1671f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                } finally {
1672f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    Binder.restoreCallingIdentity(ident);
1673f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                }
1674f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                return true;
1675f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1676f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1677f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        return false;
1678f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1679f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1680fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn    void updateFromSettingsLocked(boolean enabledMayChange) {
16817b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        updateInputMethodsFromSettingsLocked(enabledMayChange);
16827b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        updateKeyboardFromSettingsLocked();
16837b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    }
16847b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
16857b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
1686fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        if (enabledMayChange) {
1687fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
1688fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            for (int i=0; i<enabled.size(); i++) {
1689fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // We allow the user to select "disabled until used" apps, so if they
1690fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // are enabling one of those here we now need to make it enabled.
1691fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                InputMethodInfo imm = enabled.get(i);
1692fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                try {
1693fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
1694fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
1695fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            mSettings.getCurrentUserId());
16967987a3172b0502ea70a26d80e7cd16ca7e460035Satoshi Kataoka                    if (ai != null && ai.enabledSetting
1697fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
1698ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        if (DEBUG) {
1699ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            Slog.d(TAG, "Update state(" + imm.getId()
1700ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                                    + "): DISABLED_UNTIL_USED -> DEFAULT");
1701ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        }
1702fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
1703fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
17043fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(),
17053fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                mContext.getBasePackageName());
1706fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    }
1707fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                } catch (RemoteException e) {
1708fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
1709fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            }
1710fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        }
1711b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
1712b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
1713b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
1714b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // enabled.
17154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String id = mSettings.getSelectedInputMethod();
171603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        // There is no input method selected, try to choose new applicable input method.
171703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
17184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            id = mSettings.getSelectedInputMethod();
171903eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        }
172003eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (!TextUtils.isEmpty(id)) {
17219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
17228e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
17239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException e) {
17248a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unknown input method from prefs: " + id, e);
1725105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mCurMethodId = null;
17262ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1728f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.clear();
1729b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        } else {
1730b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            // There is no longer an input method set, so stop any current one.
1731105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCurMethodId = null;
17322ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn            unbindCurrentMethodLocked(true, false);
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17343d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
17353d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
17363d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
17373d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
17383d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
17397b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
17407b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    }
17417b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
17427b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    public void updateKeyboardFromSettingsLocked() {
17437b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled();
17447b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        if (mSwitchingDialog != null
17457b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                && mSwitchingDialogTitleView != null
17467b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                && mSwitchingDialog.isShowing()) {
17477b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById(
17487b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    com.android.internal.R.id.hard_keyboard_switch);
17497b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
17507b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        }
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1752ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1753ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /* package */ void setInputMethodLocked(String id, int subtypeId) {
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(id);
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
1756913a8925c07e854a80bf5df87561f290d3a56d61satok            throw new IllegalArgumentException("Unknown id: " + id);
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1758ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1759e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        if (mCurClient != null && mCurAttribute != null) {
1760e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa            final int uid = mCurClient.uid;
1761e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa            final String packageName = mCurAttribute.packageName;
1762e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa            if (SystemConfig.getInstance().getFixedImeApps().contains(packageName)) {
1763e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa                if (InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, uid, packageName)) {
1764e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa                    return;
1765e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa                }
1766e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa                // TODO: Do we need to lock the input method when the application reported an
1767e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa                // incorrect package name?
1768e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa                Slog.e(TAG, "Ignoring FixedImeApps due to the validation failure. uid=" + uid
1769e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa                        + " package=" + packageName);
1770e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa            }
1771e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        }
1772e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa
1773d81e950265356c81276b73da68a535ffa48d72f0satok        // See if we need to notify a subtype change within the same IME.
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.equals(mCurMethodId)) {
1775d81e950265356c81276b73da68a535ffa48d72f0satok            final int subtypeCount = info.getSubtypeCount();
1776d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeCount <= 0) {
1777d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1778d81e950265356c81276b73da68a535ffa48d72f0satok            }
1779d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype oldSubtype = mCurrentSubtype;
1780d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype newSubtype;
1781d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeId >= 0 && subtypeId < subtypeCount) {
1782d81e950265356c81276b73da68a535ffa48d72f0satok                newSubtype = info.getSubtypeAt(subtypeId);
1783d81e950265356c81276b73da68a535ffa48d72f0satok            } else {
1784d81e950265356c81276b73da68a535ffa48d72f0satok                // If subtype is null, try to find the most applicable one from
1785d81e950265356c81276b73da68a535ffa48d72f0satok                // getCurrentInputMethodSubtype.
17864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                newSubtype = getCurrentInputMethodSubtypeLocked();
1787d81e950265356c81276b73da68a535ffa48d72f0satok            }
1788d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype == null || oldSubtype == null) {
1789d81e950265356c81276b73da68a535ffa48d72f0satok                Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
1790d81e950265356c81276b73da68a535ffa48d72f0satok                        + ", new subtype = " + newSubtype);
1791d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1792d81e950265356c81276b73da68a535ffa48d72f0satok            }
1793d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype != oldSubtype) {
1794d81e950265356c81276b73da68a535ffa48d72f0satok                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
1795d81e950265356c81276b73da68a535ffa48d72f0satok                if (mCurMethod != null) {
1796d81e950265356c81276b73da68a535ffa48d72f0satok                    try {
1797d81e950265356c81276b73da68a535ffa48d72f0satok                        refreshImeWindowVisibilityLocked();
1798d81e950265356c81276b73da68a535ffa48d72f0satok                        mCurMethod.changeInputMethodSubtype(newSubtype);
1799d81e950265356c81276b73da68a535ffa48d72f0satok                    } catch (RemoteException e) {
1800d81e950265356c81276b73da68a535ffa48d72f0satok                        Slog.w(TAG, "Failed to call changeInputMethodSubtype");
1801ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
1802ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                }
1803ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            }
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1806ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1807d81e950265356c81276b73da68a535ffa48d72f0satok        // Changing to a different IME.
18089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long ident = Binder.clearCallingIdentity();
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1810ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // Set a subtype to this input method.
1811ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // subtypeId the name of a subtype which will be set.
1812723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
1813723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
1814723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // because mCurMethodId is stored as a history in
1815723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // setSelectedInputMethodAndSubtypeLocked().
1816723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mCurMethodId = id;
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ActivityManagerNative.isSystemReady()) {
18199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
18201c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
18219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.putExtra("input_method_id", id);
1822cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani                mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
18239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1824b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
18259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
18269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1829ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
183042c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
18314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean showSoftInput(IInputMethodClient client, int flags,
18324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
18334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
18344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
18354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1836cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
18409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1847cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
18484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
18499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
18514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1854ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1855e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
18564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return showCurrentInputLocked(flags, resultReceiver);
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1862ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18634df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = true;
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
18669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
18709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowForced = true;
18719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1872ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1873cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        if (!mSystemReady) {
1874cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            return false;
1875cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        }
1876ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18774df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res = false;
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
1879e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
18804df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
18814df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
18824df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    resultReceiver));
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputShown = true;
18842c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            if (mHaveConnection && !mVisibleBound) {
18854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                bindCurrentInputMethodService(
1886f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                        mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
1887f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                                | Context.BIND_TREAT_LIKE_ACTIVITY);
18882c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                mVisibleBound = true;
18892c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            }
18904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
18919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mHaveConnection && SystemClock.uptimeMillis()
189259b424c3b6121c9579fc5efcc785ba084072a5casatok                >= (mLastBindTime+TIME_TO_RECONNECT)) {
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The client has asked to have the input method shown, but
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we have been sitting here too long with a connection to the
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // service and no interface received, so let's disconnect/connect
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to try to prod things along.
1897ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemClock.uptimeMillis()-mLastBindTime,1);
189959b424c3b6121c9579fc5efcc785ba084072a5casatok            Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.unbindService(this);
19014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
19022c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                    | Context.BIND_NOT_VISIBLE);
19034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } else {
19044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
19054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
19064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
19074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1909ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
19119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1912ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
191342c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
19144df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean hideSoftInput(IInputMethodClient client, int flags,
19154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
19164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
19174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
19184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1919cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
19229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
19239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
19249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
19259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
19269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
19279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
19289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
19299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1930cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
1931cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                                    + uid + ": " + client);
193215452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
19334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
19349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
193615452a487a4c0274f4217cd060aa54446f30a8f3satok                        setImeWindowVisibilityStatusHiddenLocked();
19374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
19399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1940ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19418a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
19424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return hideCurrentInputLocked(flags, resultReceiver);
19439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
19449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
19459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
19469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1948ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
19509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
19519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mShowExplicitlyRequested || mShowForced)) {
1952e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
19534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
19549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
1956e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
19574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
19589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res;
19609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputShown && mCurMethod != null) {
19614df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
19624df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
19634df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
19644df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
19654df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = false;
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19672c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mHaveConnection && mVisibleBound) {
19682c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
19692c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
19702c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
19719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputShown = false;
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = false;
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowExplicitlyRequested = false;
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowForced = false;
19754df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1977ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
197842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
19797663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
19807663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            int controlFlags, int softInputMode, int windowFlags,
19817663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            EditorInfo attribute, IInputContext inputContext) {
19828d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        // Needs to check the validity before clearing calling identity
19838d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        final boolean calledFromValidUser = calledFromValidUser();
19848d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
19857663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        InputBindResult res = null;
19869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
19898a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
19907663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " controlFlags=#" + Integer.toHexString(controlFlags)
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " softInputMode=#" + Integer.toHexString(softInputMode)
19927663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " windowFlags=#" + Integer.toHexString(windowFlags));
1993ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19947663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                ClientState cs = mClients.get(client.asBinder());
19957663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (cs == null) {
19967663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    throw new IllegalArgumentException("unknown client "
19977663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            + client.asBinder());
19987663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
19997663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20007663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                try {
20017663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
20027663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // Check with the window manager to make sure this client actually
20037663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // has a window with focus.  If not, reject.  This is thread safe
20047663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // because if the focus changes some time before or after, the
20057663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // next client receiving focus that has any interest in input will
20067663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // be calling through here after that change happens.
20077663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        Slog.w(TAG, "Focus gain on non-focused client " + cs.client
20087663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
20097663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return null;
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
20117663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                } catch (RemoteException e) {
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2013ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20148d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                if (!calledFromValidUser) {
20158d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "A background user is requesting window. Hiding IME.");
20168d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "If you want to interect with IME, you need "
20178d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                            + "android.permission.INTERACT_ACROSS_USERS_FULL");
20188d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    hideCurrentInputLocked(0, null);
20198d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    return null;
20208d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                }
20218d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
2022b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                if (mCurFocusedWindow == windowToken) {
2023ac92087a9a1c464d4b0a58c82dae01cbaa088e89Dianne Hackborn                    Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
20243573950e0b30178dc963de3fa00aba2ebcfd552dSatoshi Kataoka                            + " attribute=" + attribute + ", token = " + windowToken);
20257663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (attribute != null) {
20267663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return startInputUncheckedLocked(cs, inputContext, attribute,
20277663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                controlFlags);
20287663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    }
20297663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    return null;
2030b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
2031b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mCurFocusedWindow = windowToken;
2032ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20337d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // Should we auto-show the IME even if the caller has not
20347d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // specified what should be done with it?
20357d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // We only do this automatically if the window can resize
20367d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // to accommodate the IME (so what the user sees will give
20377d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // them good context without input information being obscured
20387d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // by the IME) or if running on a large screen where there
20397d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // is more room for the target window + IME.
20407d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                final boolean doAutoShow =
20417d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
20427d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
20437d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        || mRes.getConfiguration().isLayoutSizeAtLeast(
20447d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                Configuration.SCREENLAYOUT_SIZE_LARGE);
20457663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                final boolean isTextEditor =
20467663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0;
20477663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20487663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // We want to start input before showing the IME, but after closing
20497663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // it.  We want to do this after closing it to help the IME disappear
20507663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // more quickly (not get stuck behind it initializing itself for the
20517663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // new focused input, even if its window wants to hide the IME).
20527663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                boolean didStart = false;
20537d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
20559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
20567d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        if (!isTextEditor || !doAutoShow) {
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // There is no focus view, and this window will
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // be behind any soft input window, so hide the
20609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // soft input window if it is shown.
20618a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
20624df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
20639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
20647d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        } else if (isTextEditor && doAutoShow && (softInputMode &
20657d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // There is a focus view, and we are navigating forward
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // into the window, so show the input window for the user.
20687663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // We only do this automatically if the window can resize
20697663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // to accommodate the IME (so what the user sees will give
20707d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // them good context without input information being obscured
20717d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // by the IME) or if running on a large screen where there
20727d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // is more room for the target window + IME.
20738a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
20747663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
20757663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
20767663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
20777663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
20787663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
20794df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Do nothing.
20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
20879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20888a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
20894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            hideCurrentInputLocked(0, null);
20909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
20938a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to hide input");
20944df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        hideCurrentInputLocked(0, null);
20959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
20979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20998a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
21007663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
21017663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
21027663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
21037663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
21047663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
21054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
21089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
21098a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to always show input");
21107663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        if (attribute != null) {
21117663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            res = startInputUncheckedLocked(cs, inputContext, attribute,
21127663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                    controlFlags);
21137663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            didStart = true;
21147663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        }
21154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
21169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
21179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
21187663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
21197663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (!didStart && attribute != null) {
21207663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    res = startInputUncheckedLocked(cs, inputContext, attribute,
21217663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            controlFlags);
21227663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
21239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
21269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21277663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
21287663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return res;
21299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2130ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
213142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
21329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showInputMethodPickerFromClient(IInputMethodClient client) {
21334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
21354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
21369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurClient == null || client == null
21389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || mCurClient.client.asBinder() != client.asBinder()) {
213947a44916e2fb33cf4751906386d5f5c903b28d8bsatok                Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
2140cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + ": " + client);
21419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2143440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // Always call subtype picker, because subtype picker is a superset of input method
2144440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // picker.
2145ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER);
2146ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2147ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2148ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
214942c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
21509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethod(IBinder token, String id) {
21514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
21534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
21542820351489537698ad153c6397edf3270455edc5satok        setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
21552820351489537698ad153c6397edf3270455edc5satok    }
21562820351489537698ad153c6397edf3270455edc5satok
215742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
21582820351489537698ad153c6397edf3270455edc5satok    public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
21594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
21614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
21622820351489537698ad153c6397edf3270455edc5satok        synchronized (mMethodMap) {
21632820351489537698ad153c6397edf3270455edc5satok            if (subtype != null) {
21644e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, id,
21654e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        InputMethodUtils.getSubtypeIdFromHashCode(mMethodMap.get(id),
21664e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                                subtype.hashCode()));
21672820351489537698ad153c6397edf3270455edc5satok            } else {
21682820351489537698ad153c6397edf3270455edc5satok                setInputMethod(token, id);
21692820351489537698ad153c6397edf3270455edc5satok            }
21702820351489537698ad153c6397edf3270455edc5satok        }
2171ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2172ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
217342c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
2174b416a71e56cdd50742eb897366a140775aa4cd61satok    public void showInputMethodAndSubtypeEnablerFromClient(
2175217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            IInputMethodClient client, String inputMethodId) {
21764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
21784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2179b416a71e56cdd50742eb897366a140775aa4cd61satok        synchronized (mMethodMap) {
2180b416a71e56cdd50742eb897366a140775aa4cd61satok            if (mCurClient == null || client == null
2181b416a71e56cdd50742eb897366a140775aa4cd61satok                || mCurClient.client.asBinder() != client.asBinder()) {
2182b416a71e56cdd50742eb897366a140775aa4cd61satok                Slog.w(TAG, "Ignoring showInputMethodAndSubtypeEnablerFromClient of: " + client);
2183b416a71e56cdd50742eb897366a140775aa4cd61satok            }
21847fee71f66afef6421b92fa48e63d4bc73f5d0c27satok            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
21857fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                    MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
2186b416a71e56cdd50742eb897366a140775aa4cd61satok        }
2187b416a71e56cdd50742eb897366a140775aa4cd61satok    }
2188b416a71e56cdd50742eb897366a140775aa4cd61satok
21894fc87d61c29886c848789208c9e32ba9ac4e5dd3satok    @Override
2190735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    public boolean switchToLastInputMethod(IBinder token) {
21914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
21934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2194735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        synchronized (mMethodMap) {
2195c445bcd0bce630948ee029d7c70b28226f0b6c9csatok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
21964fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            final InputMethodInfo lastImi;
2197208d5634047111811de16fb63c43d0bc8b4fe6desatok            if (lastIme != null) {
21984fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = mMethodMap.get(lastIme.first);
21994fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
22004fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = null;
22014fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
22024fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            String targetLastImiId = null;
22034fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            int subtypeId = NOT_A_SUBTYPE_ID;
22044fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (lastIme != null && lastImi != null) {
22054fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
22064fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
22074fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
22084fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        : mCurrentSubtype.hashCode();
22094fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // If the last IME is the same as the current IME and the last subtype is not
22104fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // defined, there is no need to switch to the last IME.
22114fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
22124fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    targetLastImiId = lastIme.first;
22138e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
22144fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
22154fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
22164fc87d61c29886c848789208c9e32ba9ac4e5dd3satok
22178e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            if (TextUtils.isEmpty(targetLastImiId)
22188e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    && !InputMethodUtils.canAddToLastInputMethod(mCurrentSubtype)) {
22194fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // This is a safety net. If the currentSubtype can't be added to the history
22204fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // and the framework couldn't find the last ime, we will make the last ime be
22214fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // the most applicable enabled keyboard subtype of the system imes.
22224fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
22234fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (enabled != null) {
22244fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final int N = enabled.size();
22254fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final String locale = mCurrentSubtype == null
22264fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            ? mRes.getConfiguration().locale.toString()
22274fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            : mCurrentSubtype.getLocale();
22284fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    for (int i = 0; i < N; ++i) {
22294fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        final InputMethodInfo imi = enabled.get(i);
22308e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        if (imi.getSubtypeCount() > 0 && InputMethodUtils.isSystemIme(imi)) {
22314fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            InputMethodSubtype keyboardSubtype =
22328e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                    InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes,
22338e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.getSubtypes(imi),
22348e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, locale, true);
22354fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            if (keyboardSubtype != null) {
22364fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                targetLastImiId = imi.getId();
22378e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
22384fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                        imi, keyboardSubtype.hashCode());
22394fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                if(keyboardSubtype.getLocale().equals(locale)) {
22404fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                    break;
22414fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                }
22424fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            }
22434fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        }
22444fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    }
22454fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
22464fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
2247c445bcd0bce630948ee029d7c70b28226f0b6c9csatok
22484fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (!TextUtils.isEmpty(targetLastImiId)) {
2249c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                if (DEBUG) {
22504fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
22514fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            + ", from: " + mCurMethodId + ", " + subtypeId);
2252735cf38b8c7f8f91ad087511e44fe79018fa61d6satok                }
22534e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
2254c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                return true;
22554fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
22564fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                return false;
2257735cf38b8c7f8f91ad087511e44fe79018fa61d6satok            }
2258735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        }
2259735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    }
2260735cf38b8c7f8f91ad087511e44fe79018fa61d6satok
2261e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2262688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
22634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
22654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2266688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        synchronized (mMethodMap) {
2267a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2268a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2269a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring switchToNextInputMethod due to an invalid token. uid:" + uid
2270a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + " token:" + token);
2271a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2272a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
22735a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
2274688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                    onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
2275688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            if (nextSubtype == null) {
2276688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                return false;
2277688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            }
22784e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
22794e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    nextSubtype.mSubtypeId);
2280688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            return true;
2281688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        }
2282688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    }
2283688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok
2284688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    @Override
22852b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    public boolean shouldOfferSwitchingToNextInputMethod(IBinder token) {
22862b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        if (!calledFromValidUser()) {
22872b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return false;
22882b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
22892b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        synchronized (mMethodMap) {
2290a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2291a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2292a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring shouldOfferSwitchingToNextInputMethod due to an invalid "
2293a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + "token. uid:" + uid + " token:" + token);
2294a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2295a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
22965a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
22972b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                    false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
22982b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            if (nextSubtype == null) {
22992b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                return false;
23002b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            }
23012b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return true;
23022b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
23032b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    }
23042b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka
23052b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    @Override
230668f1b78b7b9139a0e34285ff641a664e664a14b8satok    public InputMethodSubtype getLastInputMethodSubtype() {
23074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
23094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
231068f1b78b7b9139a0e34285ff641a664e664a14b8satok        synchronized (mMethodMap) {
231168f1b78b7b9139a0e34285ff641a664e664a14b8satok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
231268f1b78b7b9139a0e34285ff641a664e664a14b8satok            // TODO: Handle the case of the last IME with no subtypes
231368f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastIme == null || TextUtils.isEmpty(lastIme.first)
231468f1b78b7b9139a0e34285ff641a664e664a14b8satok                    || TextUtils.isEmpty(lastIme.second)) return null;
231568f1b78b7b9139a0e34285ff641a664e664a14b8satok            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
231668f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastImi == null) return null;
231768f1b78b7b9139a0e34285ff641a664e664a14b8satok            try {
231868f1b78b7b9139a0e34285ff641a664e664a14b8satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
23198e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final int lastSubtypeId =
23208e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
23210e7d7d632309409e2bc51d5317cf7a92a7541433satok                if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
23220e7d7d632309409e2bc51d5317cf7a92a7541433satok                    return null;
23230e7d7d632309409e2bc51d5317cf7a92a7541433satok                }
23240e7d7d632309409e2bc51d5317cf7a92a7541433satok                return lastImi.getSubtypeAt(lastSubtypeId);
232568f1b78b7b9139a0e34285ff641a664e664a14b8satok            } catch (NumberFormatException e) {
232668f1b78b7b9139a0e34285ff641a664e664a14b8satok                return null;
232768f1b78b7b9139a0e34285ff641a664e664a14b8satok            }
232868f1b78b7b9139a0e34285ff641a664e664a14b8satok        }
232968f1b78b7b9139a0e34285ff641a664e664a14b8satok    }
233068f1b78b7b9139a0e34285ff641a664e664a14b8satok
2331e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2332ee5e77cafec2eae70890abdcc1646ed39b06edddsatok    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
23334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
233691e88122cf28a48fd2e2260da7d3d87dd437227asatok        // By this IPC call, only a process which shares the same uid with the IME can add
233791e88122cf28a48fd2e2260da7d3d87dd437227asatok        // additional input method subtypes to the IME.
2338ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
2339e7c6998e0a953ae55487d4fe122739646f9280aasatok        synchronized (mMethodMap) {
234091e88122cf28a48fd2e2260da7d3d87dd437227asatok            final InputMethodInfo imi = mMethodMap.get(imiId);
2341ee5e77cafec2eae70890abdcc1646ed39b06edddsatok            if (imi == null) return;
23424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String[] packageInfos;
23434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            try {
23444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
23454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } catch (RemoteException e) {
23464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.e(TAG, "Failed to get package infos");
23474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
23484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
234991e88122cf28a48fd2e2260da7d3d87dd437227asatok            if (packageInfos != null) {
235091e88122cf28a48fd2e2260da7d3d87dd437227asatok                final int packageNum = packageInfos.length;
235191e88122cf28a48fd2e2260da7d3d87dd437227asatok                for (int i = 0; i < packageNum; ++i) {
235291e88122cf28a48fd2e2260da7d3d87dd437227asatok                    if (packageInfos[i].equals(imi.getPackageName())) {
235391e88122cf28a48fd2e2260da7d3d87dd437227asatok                        mFileManager.addInputMethodSubtypes(imi, subtypes);
2354c593380d1bccbfbd45c404954b2670b65acc287fsatok                        final long ident = Binder.clearCallingIdentity();
2355c593380d1bccbfbd45c404954b2670b65acc287fsatok                        try {
2356f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                            buildInputMethodListLocked(mMethodList, mMethodMap,
2357f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                                    false /* resetDefaultEnabledIme */);
2358c593380d1bccbfbd45c404954b2670b65acc287fsatok                        } finally {
2359c593380d1bccbfbd45c404954b2670b65acc287fsatok                            Binder.restoreCallingIdentity(ident);
2360c593380d1bccbfbd45c404954b2670b65acc287fsatok                        }
2361ee5e77cafec2eae70890abdcc1646ed39b06edddsatok                        return;
236291e88122cf28a48fd2e2260da7d3d87dd437227asatok                    }
236391e88122cf28a48fd2e2260da7d3d87dd437227asatok                }
236491e88122cf28a48fd2e2260da7d3d87dd437227asatok            }
2365e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
2366ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        return;
2367e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
2368e7c6998e0a953ae55487d4fe122739646f9280aasatok
2369658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    @Override
2370658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    public int getInputMethodWindowVisibleHeight() {
2371658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka        return mWindowManagerService.getInputMethodWindowVisibleHeight();
2372658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    }
2373658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka
2374d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    @Override
23753d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    public void notifyUserAction(int sequenceNumber) {
2376d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (DEBUG) {
23773d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            Slog.d(TAG, "Got the notification of a user action. sequenceNumber:" + sequenceNumber);
2378d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
23795a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
23803d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            if (mCurUserActionNotificationSequenceNumber != sequenceNumber) {
23813d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                if (DEBUG) {
23823d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    Slog.d(TAG, "Ignoring the user action notification due to the sequence number "
23833d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + "mismatch. expected:" + mCurUserActionNotificationSequenceNumber
23843d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + " actual: " + sequenceNumber);
23853d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                }
23863d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                return;
23873d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            }
23885a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
23895a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            if (imi != null) {
23900297051162193ef2b7d906409868e404f77e4c31Yohei Yukawa                mSwitchingController.onUserActionLocked(imi, mCurrentSubtype);
23915a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
2392d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2393d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    }
2394d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
23952820351489537698ad153c6397edf3270455edc5satok    private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
23969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
23974e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, id, subtypeId);
23984e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
23994e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    }
24009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24014e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
24024e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        if (token == null) {
24034e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            if (mContext.checkCallingOrSelfPermission(
24044e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
24054e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    != PackageManager.PERMISSION_GRANTED) {
24064e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                throw new SecurityException(
24074e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        "Using null token requires permission "
24084e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
24099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24104e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } else if (mCurToken != token) {
24114e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
24124e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    + " token: " + token);
24134e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            return;
24144e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
24154e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa
24164e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        final long ident = Binder.clearCallingIdentity();
24174e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        try {
24184e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodLocked(id, subtypeId);
24194e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } finally {
24204e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Binder.restoreCallingIdentity(ident);
24219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
24239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
242442c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
24259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideMySoftInput(IBinder token, int flags) {
24264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
24274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
24284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
24299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
243022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
243122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
243222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring hideInputMethod due to an invalid token. uid:"
243322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
24349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
24359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
24379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
24384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                hideCurrentInputLocked(flags, null);
24394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } finally {
24404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                Binder.restoreCallingIdentity(ident);
24414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
24424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
24434df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
2444ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
244542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
24464df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void showMySoftInput(IBinder token, int flags) {
24474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
24484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
24494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
24504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        synchronized (mMethodMap) {
245122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
245222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
245322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring showMySoftInput due to an invalid token. uid:"
245422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
24554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return;
24564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
24574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            long ident = Binder.clearCallingIdentity();
24584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            try {
24594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                showCurrentInputLocked(flags, null);
24609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
24619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
24629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
24659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
24669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setEnabledSessionInMainThread(SessionState session) {
24679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledSession != session) {
24689d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
24699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24708a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
24719d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false);
24729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
24749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledSession = session;
24769d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
24779d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                try {
24789d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
24799d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true);
24809d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                } catch (RemoteException e) {
24819d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                }
24829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
24839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
24849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2485ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
248642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
24879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean handleMessage(Message msg) {
2488758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov        SomeArgs args;
24899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (msg.what) {
24909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_IM_PICKER:
24919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showInputMethodMenu();
24929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2493ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2494ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            case MSG_SHOW_IM_SUBTYPE_PICKER:
2495ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                showInputMethodSubtypeMenu();
2496ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                return true;
2497ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
249847a44916e2fb33cf4751906386d5f5c903b28d8bsatok            case MSG_SHOW_IM_SUBTYPE_ENABLER:
2499758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25007fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                showInputMethodAndSubtypeEnabler((String)args.arg1);
2501758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
2502217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                return true;
2503217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2504217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            case MSG_SHOW_IM_CONFIG:
2505217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                showConfigureInputMethods();
250647a44916e2fb33cf4751906386d5f5c903b28d8bsatok                return true;
250747a44916e2fb33cf4751906386d5f5c903b28d8bsatok
25089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2509ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_INPUT:
25119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)msg.obj).unbindInput();
25139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the method dying.
25159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
25169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_BIND_INPUT:
2518758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);
25219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2523758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_SOFT_INPUT:
2526758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2528e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
25296efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + msg.arg1 + ", " + args.arg2 + ")");
2530ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
25319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2533758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_HIDE_SOFT_INPUT:
2536758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2538e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
25396efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + args.arg2 + ")");
2540ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
25419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2543758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_ATTACH_TOKEN:
2546758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2548e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
25499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
25509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2552758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2554c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            case MSG_CREATE_SESSION: {
2555758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25561951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethod method = (IInputMethod)args.arg1;
2557c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel = (InputChannel)args.arg2;
25589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25591951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    method.createSession(channel, (IInputSessionCallback)args.arg3);
25609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2561c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } finally {
25621951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
25631951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
25641951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (channel != null && Binder.isProxy(method)) {
2565c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        channel.dispose();
2566c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    }
25679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2568758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2570c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
25719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2572ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_START_INPUT:
2574758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
25779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
25789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.startInput((IInputContext)args.arg2,
25799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2582758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_RESTART_INPUT:
2585758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
25889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
25899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.restartInput((IInputContext)args.arg2,
25909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
25919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2593758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2595ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2597ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_METHOD:
25999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1);
26019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
26029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the last client dying.
26039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
26049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
26051951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            case MSG_BIND_METHOD: {
2606758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
26071951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethodClient client = (IInputMethodClient)args.arg1;
26081951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                InputBindResult res = (InputBindResult)args.arg2;
26099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26101951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    client.onBindMethod(res);
26119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
26128a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Client died receiving input method " + args.arg2);
26131951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                } finally {
26141951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
26151951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
26161951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (res.channel != null && Binder.isProxy(client)) {
26171951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                        res.channel.dispose();
26181951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    }
26199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2620758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
26219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
26221951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            }
2623a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            case MSG_SET_ACTIVE:
2624a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                try {
2625a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    ((ClientState)msg.obj).client.setActive(msg.arg1 != 0);
2626a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                } catch (RemoteException e) {
2627a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    Slog.w(TAG, "Got RemoteException sending setActive(false) notification to pid "
2628a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).pid + " uid "
2629a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).uid);
2630a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                }
2631a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                return true;
26323d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
26333d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                final int sequenceNumber = msg.arg1;
2634080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                final ClientState clientState = (ClientState)msg.obj;
26353d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                try {
2636080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                    clientState.client.setUserActionNotificationSequenceNumber(sequenceNumber);
26373d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                } catch (RemoteException e) {
26383d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    Slog.w(TAG, "Got RemoteException sending "
26393d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + "setUserActionNotificationSequenceNumber("
26403d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + sequenceNumber + ") notification to pid "
2641080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                            + clientState.pid + " uid "
2642080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                            + clientState.uid);
26433d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                }
26443d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                return true;
26453d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            }
264601038492ff0317f0d3cff54d8a7ee36bb31ff175satok
264701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // --------------------------------------------------------------
264801038492ff0317f0d3cff54d8a7ee36bb31ff175satok            case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
26497b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1);
265001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                return true;
26519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
26539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
26549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2655dc9ddaee9a710cf6f5d7f37350650f82e706c706satok    private boolean chooseNewDefaultIMELocked() {
26568e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
26578e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mSettings.getEnabledInputMethodListLocked());
2658dc9ddaee9a710cf6f5d7f37350650f82e706c706satok        if (imi != null) {
265903eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            if (DEBUG) {
266003eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                Slog.d(TAG, "New default IME was selected: " + imi.getId());
266103eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            }
2662723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            resetSelectedInputMethodAndSubtypeLocked(imi.getId());
26636da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            return true;
26646da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
26656da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
26666da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        return false;
26676da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger    }
26686da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
26699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
2670f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) {
26714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
2672f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
26730766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                    + " \n ------ \n" + InputMethodUtils.getStackTrace());
26744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
26759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        list.clear();
26769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map.clear();
2677ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // Use for queryIntentServicesAsUser
26794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final PackageManager pm = mContext.getPackageManager();
26804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
2681e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani        if (disabledSysImes == null) disabledSysImes = "";
26829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
26849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new Intent(InputMethod.SERVICE_INTERFACE),
2685fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
2686fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                mSettings.getCurrentUserId());
2687ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2688e7c6998e0a953ae55487d4fe122739646f9280aasatok        final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
2689e7c6998e0a953ae55487d4fe122739646f9280aasatok                mFileManager.getAllAdditionalInputMethodSubtypes();
26909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < services.size(); ++i) {
26919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = services.get(i);
26929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ServiceInfo si = ri.serviceInfo;
26939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ComponentName compName = new ComponentName(si.packageName, si.name);
26949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(
26959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    si.permission)) {
26968a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Skipping input method " + compName
26979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": it does not require the permission "
26989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.BIND_INPUT_METHOD);
26999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
27009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
27019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27028a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.d(TAG, "Checking " + compName);
27039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2705e7c6998e0a953ae55487d4fe122739646f9280aasatok                InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes);
27069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list.add(p);
2707e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                final String id = p.getId();
2708e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                map.put(id, p);
27099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
2711f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "Found an input method " + p);
27129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2713ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
27158a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
27169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
27178a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
27189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
27199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
27206da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
2721f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (resetDefaultEnabledIme) {
2722f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            final ArrayList<InputMethodInfo> defaultEnabledIme =
2723f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list);
2724f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            for (int i = 0; i < defaultEnabledIme.size(); ++i) {
2725f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                final InputMethodInfo imi =  defaultEnabledIme.get(i);
2726f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                if (DEBUG) {
2727f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "--- enable ime = " + imi);
2728f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                }
2729f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                setInputMethodEnabledLocked(imi.getId(), true);
2730f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            }
2731f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
2732f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
27334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
27340a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!TextUtils.isEmpty(defaultImiId)) {
27350a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            if (!map.containsKey(defaultImiId)) {
27360a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
27370a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (chooseNewDefaultIMELocked()) {
27387b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateInputMethodsFromSettingsLocked(true);
27390a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
27400a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            } else {
27410a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                // Double check that the default IME is certainly enabled.
27420a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                setInputMethodEnabledLocked(defaultImiId, true);
27436da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            }
27446da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
27453d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
27463d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
27473d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
27483d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
2749c834a2590cc7ac478ba2ef5a6d8eb7ce471df132Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
27509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2751ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2753ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2754ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenu() {
2755ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(false);
2756ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2757ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2758ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodSubtypeMenu() {
2759ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(true);
2760ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2761ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2762217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
2763f49688fa17b70313c0734f00df73bc3308a749e9Tadashi G. Takaoka        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
276447a44916e2fb33cf4751906386d5f5c903b28d8bsatok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
276586417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
276686417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
27677fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        if (!TextUtils.isEmpty(inputMethodId)) {
27682548020c364c4119d134c84cc7a00ffca2dcbe7bTadashi G. Takaoka            intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId);
27697fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        }
27703ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
2771217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    }
2772217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2773217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showConfigureInputMethods() {
2774217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
2775217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2776217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
2777217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
27783ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
277947a44916e2fb33cf4751906386d5f5c903b28d8bsatok    }
278047a44916e2fb33cf4751906386d5f5c903b28d8bsatok
27812c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    private boolean isScreenLocked() {
27822c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        return mKeyguardManager != null
27832c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
27842c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    }
2785d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka
2786ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenuInternal(boolean showSubtypes) {
27878a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Show switching menu");
27889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
27899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Context context = mContext;
27902c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        final boolean isScreenLocked = isScreenLocked();
2791ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String lastInputMethodId = mSettings.getSelectedInputMethod();
27938e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
27948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
2795ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27967f35c8cc88bea5230f001dd4356f864845d202e5satok        synchronized (mMethodMap) {
2797bb4aa0683c8a0a1e617c6d5f03eda33f49b89ed9satok            final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
2798d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(
2799d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                            mContext);
28007f35c8cc88bea5230f001dd4356f864845d202e5satok            if (immis == null || immis.size() == 0) {
28017f35c8cc88bea5230f001dd4356f864845d202e5satok                return;
28027f35c8cc88bea5230f001dd4356f864845d202e5satok            }
2803ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
28048cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            hideInputMethodMenuLocked();
28059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2806688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            final List<ImeSubtypeListItem> imList =
28075a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSwitchingController.getSortedInputMethodAndSubtypeListLocked(
2808688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                            showSubtypes, mInputShown, isScreenLocked);
2809913a8925c07e854a80bf5df87561f290d3a56d61satok
2810c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
28114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
2812c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                if (currentSubtype != null) {
2813c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                    final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
28148e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
28158e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            currentImi, currentSubtype.hashCode());
2816c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                }
2817c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            }
2818c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok
2819761eb3762f3602dd1859905ee4ba80f0ef6aec56Ken Wakasa            final int N = imList.size();
2820ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mIms = new InputMethodInfo[N];
2821ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mSubtypeIds = new int[N];
28228cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            int checkedItem = 0;
28238cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            for (int i = 0; i < N; ++i) {
282405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                final ImeSubtypeListItem item = imList.get(i);
282505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mIms[i] = item.mImi;
282605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mSubtypeIds[i] = item.mSubtypeId;
28278cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                if (mIms[i].getId().equals(lastInputMethodId)) {
2828ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    int subtypeId = mSubtypeIds[i];
2829ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    if ((subtypeId == NOT_A_SUBTYPE_ID)
2830ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0)
2831ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (subtypeId == lastInputMethodSubtypeId)) {
2832ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                        checkedItem = i;
2833ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
28348cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                }
28359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2836505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
2837505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Context settingsContext = new ContextThemeWrapper(context,
2838505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.style.Theme_DeviceDefault_Settings);
2839505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
2840505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mDialogBuilder = new AlertDialog.Builder(settingsContext);
2841d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mDialogBuilder.setOnCancelListener(new OnCancelListener() {
2842d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
2843d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onCancel(DialogInterface dialog) {
2844d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    hideInputMethodMenu();
2845d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
2846d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            });
2847505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
2848505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Context dialogContext = mDialogBuilder.getContext();
2849505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final TypedArray a = dialogContext.obtainStyledAttributes(null,
2850505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.styleable.DialogPreference,
2851505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.attr.alertDialogStyle, 0);
2852505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Drawable dialogIcon = a.getDrawable(
2853505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.styleable.DialogPreference_dialogIcon);
2854505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            a.recycle();
2855505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
2856505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mDialogBuilder.setIcon(dialogIcon);
2857505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
2858505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final LayoutInflater inflater = (LayoutInflater) dialogContext.getSystemService(
2859505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    Context.LAYOUT_INFLATER_SERVICE);
286001038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final View tv = inflater.inflate(
286101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.layout.input_method_switch_dialog_title, null);
286201038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mDialogBuilder.setCustomTitle(tv);
286301038492ff0317f0d3cff54d8a7ee36bb31ff175satok
286401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // Setup layout for a toggle switch of the hardware keyboard
286501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView = tv;
2866d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mSwitchingDialogTitleView
2867d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    .findViewById(com.android.internal.R.id.hard_keyboard_section)
2868d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    .setVisibility(mWindowManagerService.isHardKeyboardAvailable()
2869d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            ? View.VISIBLE : View.GONE);
2870505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Switch hardKeySwitch = (Switch) mSwitchingDialogTitleView.findViewById(
2871d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    com.android.internal.R.id.hard_keyboard_switch);
28727b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
2873d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
2874d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
2875d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
28767b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    mSettings.setShowImeWithHardKeyboard(isChecked);
2877d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    // Ensure that the input method dialog is dismissed when changing
2878d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    // the hardware keyboard state.
2879d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    hideInputMethodMenu();
2880d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
2881d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            });
2882d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka
2883505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(dialogContext,
2884d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    com.android.internal.R.layout.input_method_switch_item, imList, checkedItem);
2885d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            final OnClickListener choiceListener = new OnClickListener() {
2886d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
2887d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onClick(final DialogInterface dialog, final int which) {
2888d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    synchronized (mMethodMap) {
2889d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        if (mIms == null || mIms.length <= which || mSubtypeIds == null
2890d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                                || mSubtypeIds.length <= which) {
2891d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            return;
289201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        }
2893d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        final InputMethodInfo im = mIms[which];
2894d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        int subtypeId = mSubtypeIds[which];
2895d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        adapter.mCheckedItem = which;
2896d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        adapter.notifyDataSetChanged();
2897d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        hideInputMethodMenu();
2898d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        if (im != null) {
2899d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) {
2900d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                                subtypeId = NOT_A_SUBTYPE_ID;
290120cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn                            }
2902d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            setInputMethodLocked(im.getId(), subtypeId);
29039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
2904d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    }
2905d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
2906d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            };
2907d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener);
29089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2909bc81b692d51a9cd6f9d61584aacd8308ac3366easatok            if (showSubtypes && !isScreenLocked) {
2910d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                final OnClickListener positiveListener = new OnClickListener() {
2911d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    @Override
2912d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    public void onClick(DialogInterface dialog, int whichButton) {
2913d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        showConfigureInputMethods();
2914d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    }
2915d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                };
291682beadfa067b1e286fa604f8d7960d769411c954satok                mDialogBuilder.setPositiveButton(
2917d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        com.android.internal.R.string.configure_input_methods, positiveListener);
29187f35c8cc88bea5230f001dd4356f864845d202e5satok            }
29199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog = mDialogBuilder.create();
2920e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.setCanceledOnTouchOutside(true);
29219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.getWindow().setType(
29229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
2923c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
2924c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2925e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
2926807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk            updateImeWindowStatusLocked();
29279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.show();
29289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2930ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
293105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> {
293205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final LayoutInflater mInflater;
293305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final int mTextViewResourceId;
293405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final List<ImeSubtypeListItem> mItemsList;
2935d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka        public int mCheckedItem;
293605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public ImeSubtypeListAdapter(Context context, int textViewResourceId,
293705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                List<ImeSubtypeListItem> itemsList, int checkedItem) {
293805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            super(context, textViewResourceId, itemsList);
2939505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
294005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mTextViewResourceId = textViewResourceId;
294105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mItemsList = itemsList;
294205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mCheckedItem = checkedItem;
2943505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
294405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
294505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
294605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        @Override
294705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public View getView(int position, View convertView, ViewGroup parent) {
294805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final View view = convertView != null ? convertView
294905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    : mInflater.inflate(mTextViewResourceId, null);
295005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (position < 0 || position >= mItemsList.size()) return view;
295105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListItem item = mItemsList.get(position);
295205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence imeName = item.mImeName;
295305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence subtypeName = item.mSubtypeName;
295405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1);
295505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2);
295605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (TextUtils.isEmpty(subtypeName)) {
295705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(imeName);
295805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.GONE);
295905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            } else {
296005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(subtypeName);
296105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setText(imeName);
296205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.VISIBLE);
296305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            }
296405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final RadioButton radioButton =
296505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
296605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            radioButton.setChecked(position == mCheckedItem);
296705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            return view;
296805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
296905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    }
297005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
29719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hideInputMethodMenu() {
2972105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        synchronized (mMethodMap) {
2973105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
2974105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2975105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2976ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2977105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void hideInputMethodMenuLocked() {
29788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Hide switching menu");
29799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2980105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mSwitchingDialog != null) {
2981105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog.dismiss();
2982105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog = null;
29839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2984ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2985807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk        updateImeWindowStatusLocked();
2986105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mDialogBuilder = null;
2987105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIms = null;
29889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2989ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2991ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
299242c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
29939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setInputMethodEnabled(String id, boolean enabled) {
29944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
29954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
29964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
29974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
29989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
29999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mContext.checkCallingOrSelfPermission(
30009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
30019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    != PackageManager.PERMISSION_GRANTED) {
30029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new SecurityException(
30039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Requires permission "
30049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
30059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
300621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
30079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
30089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
300921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                return setInputMethodEnabledLocked(id, enabled);
301021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } finally {
301121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Binder.restoreCallingIdentity(ident);
301221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
301321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
301421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
30158e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
301621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    boolean setInputMethodEnabledLocked(String id, boolean enabled) {
301721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        // Make sure this is a valid input method.
301821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        InputMethodInfo imm = mMethodMap.get(id);
301921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (imm == null) {
3020d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
302121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
3022ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3023d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
3024d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                .getEnabledInputMethodsAndSubtypeListLocked();
3025ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3026d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        if (enabled) {
3027d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            for (Pair<String, ArrayList<String>> pair: enabledInputMethodsList) {
3028d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                if (pair.first.equals(id)) {
3029d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // We are enabling this input method, but it is already enabled.
3030d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // Nothing to do. The previous state was enabled.
3031d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    return true;
30329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
303321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
3034d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            mSettings.appendAndPutEnabledInputMethodLocked(id, false);
3035d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            // Previous state was disabled.
3036d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return false;
3037d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        } else {
3038d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            StringBuilder builder = new StringBuilder();
3039d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
3040d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    builder, enabledInputMethodsList, id)) {
3041d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Disabled input method is currently selected, switch to another one.
30424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selId = mSettings.getSelectedInputMethod();
304303eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
304403eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
304503eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    resetSelectedInputMethodAndSubtypeLocked("");
3046d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                }
3047d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Previous state was enabled.
3048d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                return true;
3049d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            } else {
3050d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // We are disabling the input method but it is already disabled.
3051d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Nothing to do.  The previous state was disabled.
30529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
30539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
30549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
30559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
30564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
3057723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
3058723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            boolean setSubtypeOnly) {
3059723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Update the history of InputMethod and Subtype
30608e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
3061723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
30623d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        mCurUserActionNotificationSequenceNumber =
30633d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                Math.max(mCurUserActionNotificationSequenceNumber + 1, 1);
30643d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        if (DEBUG) {
30653d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            Slog.d(TAG, "Bump mCurUserActionNotificationSequenceNumber:"
30663d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    + mCurUserActionNotificationSequenceNumber);
30673d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        }
30683d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
30693d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        if (mCurClient != null && mCurClient.client != null) {
30703d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
30713d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
3072080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                    mCurUserActionNotificationSequenceNumber, mCurClient));
30733d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        }
30743d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
3075723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Set Subtype here
3076723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi == null || subtypeId < 0) {
3077723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
30780ba75bb22c2992f649ee5f7605a2b45442ad4862Tadashi G. Takaoka            mCurrentSubtype = null;
3079723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        } else {
3080586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa            if (subtypeId < imi.getSubtypeCount()) {
3081586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                InputMethodSubtype subtype = imi.getSubtypeAt(subtypeId);
3082586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mSettings.putSelectedSubtype(subtype.hashCode());
3083586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mCurrentSubtype = subtype;
3084723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            } else {
3085723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
3086d81e950265356c81276b73da68a535ffa48d72f0satok                // If the subtype is not specified, choose the most applicable one
30874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
3088723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3089723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3090723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
30914c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Workaround.
30924c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // ASEC is not ready in the IMMS constructor. Accordingly, forward-locked
30934c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMEs are not recognized and considered uninstalled.
30944c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Actually, we can't move everything after SystemReady because
30954c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMMS needs to run in the encryption lock screen. So, we just skip changing
30964c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the default IME here and try cheking the default IME again in systemReady().
30974c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: Do nothing before system ready and implement a separated logic for
30984c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the encryption lock screen.
30994c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: ASEC should be ready before IMMS is instantiated.
31004c0e7152e74d091eb78af8baacd38287ba95a1a1satok        if (mSystemReady && !setSubtypeOnly) {
3101723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // Set InputMethod here
3102723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
31031ab852fbcfe155c9d4373b7130f8515591669634satok        }
3104ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3105ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3106723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
3107723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        InputMethodInfo imi = mMethodMap.get(newDefaultIme);
3108723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        int lastSubtypeId = NOT_A_SUBTYPE_ID;
3109723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // newDefaultIme is empty when there is no candidate for the selected IME.
3110723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
3111723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme);
3112723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            if (subtypeHashCode != null) {
3113723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                try {
31148e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
3115723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                            imi, Integer.valueOf(subtypeHashCode));
3116723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                } catch (NumberFormatException e) {
3117723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                    Slog.w(TAG, "HashCode for subtype looks broken: " + subtypeHashCode, e);
3118723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                }
3119723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3120723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3121723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
3122723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    }
3123723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
31244e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // If there are no selected shortcuts, tries finding the most applicable ones.
31254e4569dab5c75804b01a19b2d6e6101b445c1c68satok    private Pair<InputMethodInfo, InputMethodSubtype>
31264e4569dab5c75804b01a19b2d6e6101b445c1c68satok            findLastResortApplicableShortcutInputMethodAndSubtypeLocked(String mode) {
31274e4569dab5c75804b01a19b2d6e6101b445c1c68satok        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
31284e4569dab5c75804b01a19b2d6e6101b445c1c68satok        InputMethodInfo mostApplicableIMI = null;
3129cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        InputMethodSubtype mostApplicableSubtype = null;
31304e4569dab5c75804b01a19b2d6e6101b445c1c68satok        boolean foundInSystemIME = false;
31314e4569dab5c75804b01a19b2d6e6101b445c1c68satok
31324e4569dab5c75804b01a19b2d6e6101b445c1c68satok        // Search applicable subtype for each InputMethodInfo
31334e4569dab5c75804b01a19b2d6e6101b445c1c68satok        for (InputMethodInfo imi: imis) {
31347599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            final String imiId = imi.getId();
31357599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (foundInSystemIME && !imiId.equals(mCurMethodId)) {
31367599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                continue;
31377599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3138cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            InputMethodSubtype subtype = null;
3139df31ae6a3011d47421a6ac10021f9649dc34a156satok            final List<InputMethodSubtype> enabledSubtypes =
31408e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
3141df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 1. Search by the current subtype's locale from enabledSubtypes.
31424e4569dab5c75804b01a19b2d6e6101b445c1c68satok            if (mCurrentSubtype != null) {
31438e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3144df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
31454e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3146df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 2. Search by the system locale from enabledSubtypes.
3147df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
3148cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
31498e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3150df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, null, true);
31517599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3152a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
31538e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    InputMethodUtils.getOverridingImplicitlyEnabledSubtypes(imi, mode);
3154a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> subtypesForSearch =
3155a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                    overridingImplicitlyEnabledSubtypes.isEmpty()
31568e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            ? InputMethodUtils.getSubtypes(imi)
31578e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            : overridingImplicitlyEnabledSubtypes;
31587599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 4. Search by the current subtype's locale from all subtypes.
31597599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (subtype == null && mCurrentSubtype != null) {
31608e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3161a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
31624e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
31637599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 5. Search by the system locale from all subtypes.
31647599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 6. Search the first enabled subtype matched with mode from all subtypes.
3165cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
31668e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3167a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, null, true);
31684e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3169cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype != null) {
31707599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (imiId.equals(mCurMethodId)) {
31714e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    // The current input method is the most applicable IME.
31724e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3173cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
31744e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    break;
31754e4569dab5c75804b01a19b2d6e6101b445c1c68satok                } else if (!foundInSystemIME) {
31767599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    // The system input method is 2nd applicable IME.
31774e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3178cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
31797599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    if ((imi.getServiceInfo().applicationInfo.flags
31807599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
31817599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                        foundInSystemIME = true;
31827599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    }
31834e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
31844e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
31854e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
31864e4569dab5c75804b01a19b2d6e6101b445c1c68satok        if (DEBUG) {
3187cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (mostApplicableIMI != null) {
3188cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                Slog.w(TAG, "Most applicable shortcut input method was:"
3189cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                        + mostApplicableIMI.getId());
3190cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                if (mostApplicableSubtype != null) {
3191cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    Slog.w(TAG, "Most applicable shortcut input method subtype was:"
3192cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + "," + mostApplicableSubtype.getMode() + ","
3193cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + mostApplicableSubtype.getLocale());
3194cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                }
3195cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            }
31964e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
3197cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        if (mostApplicableIMI != null) {
31984e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
3199cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype);
32004e4569dab5c75804b01a19b2d6e6101b445c1c68satok        } else {
32014e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return null;
32024e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
32034e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
32044e4569dab5c75804b01a19b2d6e6101b445c1c68satok
3205ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3206ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return Return the current subtype of this input method.
3207ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
320842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3209ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public InputMethodSubtype getCurrentInputMethodSubtype() {
32104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
32114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
32124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
32134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
32144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        synchronized (mMethodMap) {
32154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return getCurrentInputMethodSubtypeLocked();
32164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
32174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
32184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
32194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
3220fdf419e81d795593e3792c9e78f33ed899ff098esatok        if (mCurMethodId == null) {
3221fdf419e81d795593e3792c9e78f33ed899ff098esatok            return null;
3222fdf419e81d795593e3792c9e78f33ed899ff098esatok        }
32238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
32244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
32254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (imi == null || imi.getSubtypeCount() == 0) {
32264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
32274e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
32284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!subtypeIsSelected || mCurrentSubtype == null
32298e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
32308e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
32314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (subtypeId == NOT_A_SUBTYPE_ID) {
32324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there are no selected subtypes, the framework will try to find
32334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // the most applicable subtype from explicitly or implicitly enabled
32344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // subtypes.
32354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
32368e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
32374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there is only one explicitly or implicitly enabled subtype,
32384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // just returns it.
32394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
32404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
32414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
32428e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
32434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            mRes, explicitlyOrImplicitlyEnabledSubtypes,
32448e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, null, true);
32454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    if (mCurrentSubtype == null) {
32468e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
32474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
32484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                true);
32494e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    }
32503ef8b29fa03fe3ae1c57fd891a12afa46128fff8satok                }
32514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else {
32528e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mCurrentSubtype = InputMethodUtils.getSubtypes(imi).get(subtypeId);
32538fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok            }
32548fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok        }
32554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        return mCurrentSubtype;
3256ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3257ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3258f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
3259f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            InputMethodSubtype subtype) {
3260f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
3261f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
3262f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        } else {
3263f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3264f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            subtypes.add(subtype);
3265f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
3266f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        }
3267f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    }
3268f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok
32694e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // TODO: We should change the return type from List to List<Parcelable>
3270dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("rawtypes")
3271e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
32724e4569dab5c75804b01a19b2d6e6101b445c1c68satok    public List getShortcutInputMethodsAndSubtypes() {
32734e4569dab5c75804b01a19b2d6e6101b445c1c68satok        synchronized (mMethodMap) {
32743da922367c0dbe67b97fe97fcfca13fd93602f7asatok            ArrayList<Object> ret = new ArrayList<Object>();
3275f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            if (mShortcutInputMethodsAndSubtypes.size() == 0) {
32764e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // If there are no selected shortcut subtypes, the framework will try to find
32774e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // the most applicable subtype from all subtypes whose mode is
32784e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
3279f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                Pair<InputMethodInfo, InputMethodSubtype> info =
3280f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
32818e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_VOICE);
32827599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (info != null) {
32833da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.first);
32843da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.second);
32857599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                }
32863da922367c0dbe67b97fe97fcfca13fd93602f7asatok                return ret;
3287f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            }
3288f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
3289f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                ret.add(imi);
3290f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
3291f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    ret.add(subtype);
32924e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
32934e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3294f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            return ret;
32954e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
32964e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
32974e4569dab5c75804b01a19b2d6e6101b445c1c68satok
329842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3299b66d287e3003a0934d5714fbf15e554b3c814906satok    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
33004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
33014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
33024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
33034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
3304b66d287e3003a0934d5714fbf15e554b3c814906satok        synchronized (mMethodMap) {
3305b66d287e3003a0934d5714fbf15e554b3c814906satok            if (subtype != null && mCurMethodId != null) {
3306b66d287e3003a0934d5714fbf15e554b3c814906satok                InputMethodInfo imi = mMethodMap.get(mCurMethodId);
33078e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                int subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode());
3308b66d287e3003a0934d5714fbf15e554b3c814906satok                if (subtypeId != NOT_A_SUBTYPE_ID) {
3309b66d287e3003a0934d5714fbf15e554b3c814906satok                    setInputMethodLocked(mCurMethodId, subtypeId);
3310b66d287e3003a0934d5714fbf15e554b3c814906satok                    return true;
3311b66d287e3003a0934d5714fbf15e554b3c814906satok                }
3312b66d287e3003a0934d5714fbf15e554b3c814906satok            }
3313b66d287e3003a0934d5714fbf15e554b3c814906satok            return false;
3314b66d287e3003a0934d5714fbf15e554b3c814906satok        }
3315b66d287e3003a0934d5714fbf15e554b3c814906satok    }
3316b66d287e3003a0934d5714fbf15e554b3c814906satok
33175ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    // TODO: Cache the state for each user and reset when the cached user is removed.
3318e7c6998e0a953ae55487d4fe122739646f9280aasatok    private static class InputMethodFileManager {
3319e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String SYSTEM_PATH = "system";
3320e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String INPUT_METHOD_PATH = "inputmethod";
3321e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ADDITIONAL_SUBTYPES_FILE_NAME = "subtypes.xml";
3322e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPES = "subtypes";
3323e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPE = "subtype";
3324e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_IMI = "imi";
3325e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ID = "id";
3326e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_LABEL = "label";
3327e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ICON = "icon";
3328e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
3329e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
3330e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
3331e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
3332e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final AtomicFile mAdditionalInputMethodSubtypeFile;
3333e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final HashMap<String, InputMethodInfo> mMethodMap;
3334e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
3335e7c6998e0a953ae55487d4fe122739646f9280aasatok                new HashMap<String, List<InputMethodSubtype>>();
33365ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
3337e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (methodMap == null) {
3338e7c6998e0a953ae55487d4fe122739646f9280aasatok                throw new NullPointerException("methodMap is null");
3339e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3340e7c6998e0a953ae55487d4fe122739646f9280aasatok            mMethodMap = methodMap;
33415ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka            final File systemDir = userId == UserHandle.USER_OWNER
33425ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
33435ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    : Environment.getUserSystemDirectory(userId);
3344e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
3345e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!inputMethodDir.mkdirs()) {
3346e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
3347e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3348e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
3349e7c6998e0a953ae55487d4fe122739646f9280aasatok            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
3350e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!subtypeFile.exists()) {
3351e7c6998e0a953ae55487d4fe122739646f9280aasatok                // If "subtypes.xml" doesn't exist, create a blank file.
3352e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3353e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, methodMap);
3354e7c6998e0a953ae55487d4fe122739646f9280aasatok            } else {
3355e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                readAdditionalInputMethodSubtypes(
3356e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile);
3357e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3358e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3359e7c6998e0a953ae55487d4fe122739646f9280aasatok
3360e7c6998e0a953ae55487d4fe122739646f9280aasatok        private void deleteAllInputMethodSubtypes(String imiId) {
3361e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3362e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.remove(imiId);
3363e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3364e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3365e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3366e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3367e7c6998e0a953ae55487d4fe122739646f9280aasatok
3368e7c6998e0a953ae55487d4fe122739646f9280aasatok        public void addInputMethodSubtypes(
33694a28bde70e23b2ed151d52690da702da7f23cf5esatok                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
3370e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3371e7c6998e0a953ae55487d4fe122739646f9280aasatok                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3372e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int N = additionalSubtypes.length;
3373e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (int i = 0; i < N; ++i) {
3374e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final InputMethodSubtype subtype = additionalSubtypes[i];
3375ed2b24ecc7842b27178fc584a9e5bd5b1ab07635satok                    if (!subtypes.contains(subtype)) {
3376e7c6998e0a953ae55487d4fe122739646f9280aasatok                        subtypes.add(subtype);
3377e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                    } else {
3378e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        Slog.w(TAG, "Duplicated subtype definition found: "
3379e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                                + subtype.getLocale() + ", " + subtype.getMode());
3380e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3381e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3382e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.put(imi.getId(), subtypes);
3383e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3384e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3385e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3386e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3387e7c6998e0a953ae55487d4fe122739646f9280aasatok
3388e7c6998e0a953ae55487d4fe122739646f9280aasatok        public HashMap<String, List<InputMethodSubtype>> getAllAdditionalInputMethodSubtypes() {
3389e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3390e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                return mAdditionalSubtypesMap;
3391e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3392e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3393e7c6998e0a953ae55487d4fe122739646f9280aasatok
3394e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void writeAdditionalInputMethodSubtypes(
3395e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile,
3396e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, InputMethodInfo> methodMap) {
3397e7c6998e0a953ae55487d4fe122739646f9280aasatok            // Safety net for the case that this function is called before methodMap is set.
3398e7c6998e0a953ae55487d4fe122739646f9280aasatok            final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0;
3399e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileOutputStream fos = null;
3400e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3401e7c6998e0a953ae55487d4fe122739646f9280aasatok                fos = subtypesFile.startWrite();
3402e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlSerializer out = new FastXmlSerializer();
3403e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setOutput(fos, "utf-8");
3404e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startDocument(null, true);
3405e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3406e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startTag(null, NODE_SUBTYPES);
3407e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (String imiId : allSubtypes.keySet()) {
3408e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (isSetMethodMap && !methodMap.containsKey(imiId)) {
3409e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "IME uninstalled or not valid.: " + imiId);
3410e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3411e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3412e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.startTag(null, NODE_IMI);
3413e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.attribute(null, ATTR_ID, imiId);
3414e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final List<InputMethodSubtype> subtypesList = allSubtypes.get(imiId);
3415e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final int N = subtypesList.size();
3416e7c6998e0a953ae55487d4fe122739646f9280aasatok                    for (int i = 0; i < N; ++i) {
3417e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype = subtypesList.get(i);
3418e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.startTag(null, NODE_SUBTYPE);
3419e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
3420e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
3421e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
3422e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_MODE, subtype.getMode());
3423e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
3424e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IS_AUXILIARY,
3425e7c6998e0a953ae55487d4fe122739646f9280aasatok                                String.valueOf(subtype.isAuxiliary() ? 1 : 0));
3426e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.endTag(null, NODE_SUBTYPE);
3427e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3428e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.endTag(null, NODE_IMI);
3429e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3430e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endTag(null, NODE_SUBTYPES);
3431e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endDocument();
3432e7c6998e0a953ae55487d4fe122739646f9280aasatok                subtypesFile.finishWrite(fos);
3433e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3434e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error writing subtypes", e);
3435e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fos != null) {
3436e7c6998e0a953ae55487d4fe122739646f9280aasatok                    subtypesFile.failWrite(fos);
3437e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3438e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3439e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3440e7c6998e0a953ae55487d4fe122739646f9280aasatok
3441e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void readAdditionalInputMethodSubtypes(
3442e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile) {
3443e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (allSubtypes == null || subtypesFile == null) return;
3444e7c6998e0a953ae55487d4fe122739646f9280aasatok            allSubtypes.clear();
3445e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileInputStream fis = null;
3446e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3447e7c6998e0a953ae55487d4fe122739646f9280aasatok                fis = subtypesFile.openRead();
3448e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlPullParser parser = Xml.newPullParser();
3449e7c6998e0a953ae55487d4fe122739646f9280aasatok                parser.setInput(fis, null);
3450e7c6998e0a953ae55487d4fe122739646f9280aasatok                int type = parser.getEventType();
3451e7c6998e0a953ae55487d4fe122739646f9280aasatok                // Skip parsing until START_TAG
3452e7c6998e0a953ae55487d4fe122739646f9280aasatok                while ((type = parser.next()) != XmlPullParser.START_TAG
3453e7c6998e0a953ae55487d4fe122739646f9280aasatok                        && type != XmlPullParser.END_DOCUMENT) {}
3454e7c6998e0a953ae55487d4fe122739646f9280aasatok                String firstNodeName = parser.getName();
3455e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (!NODE_SUBTYPES.equals(firstNodeName)) {
3456e7c6998e0a953ae55487d4fe122739646f9280aasatok                    throw new XmlPullParserException("Xml doesn't start with subtypes");
3457e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3458e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int depth =parser.getDepth();
3459e7c6998e0a953ae55487d4fe122739646f9280aasatok                String currentImiId = null;
3460e7c6998e0a953ae55487d4fe122739646f9280aasatok                ArrayList<InputMethodSubtype> tempSubtypesArray = null;
3461e7c6998e0a953ae55487d4fe122739646f9280aasatok                while (((type = parser.next()) != XmlPullParser.END_TAG
3462e7c6998e0a953ae55487d4fe122739646f9280aasatok                        || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
3463e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (type != XmlPullParser.START_TAG)
3464e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3465e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final String nodeName = parser.getName();
3466e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (NODE_IMI.equals(nodeName)) {
3467e7c6998e0a953ae55487d4fe122739646f9280aasatok                        currentImiId = parser.getAttributeValue(null, ATTR_ID);
3468e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId)) {
3469e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "Invalid imi id found in subtypes.xml");
3470e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3471e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3472e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray = new ArrayList<InputMethodSubtype>();
3473e7c6998e0a953ae55487d4fe122739646f9280aasatok                        allSubtypes.put(currentImiId, tempSubtypesArray);
3474e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } else if (NODE_SUBTYPE.equals(nodeName)) {
3475e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
3476e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "IME uninstalled or not valid.: " + currentImiId);
3477e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3478e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3479e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int icon = Integer.valueOf(
3480e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_ICON));
3481e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int label = Integer.valueOf(
3482e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_LABEL));
3483e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeLocale =
3484e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LOCALE);
3485e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeMode =
3486e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
3487e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeExtraValue =
3488e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
34894a28bde70e23b2ed151d52690da702da7f23cf5esatok                        final boolean isAuxiliary = "1".equals(String.valueOf(
34904a28bde70e23b2ed151d52690da702da7f23cf5esatok                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
3491443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                        final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
3492443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeNameResId(label)
3493443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeIconResId(icon)
3494443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeLocale(imeSubtypeLocale)
3495443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeMode(imeSubtypeMode)
3496443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeExtraValue(imeSubtypeExtraValue)
3497443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setIsAuxiliary(isAuxiliary)
3498443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .build();
3499e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray.add(subtype);
3500e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3501e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3502e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (XmlPullParserException e) {
3503e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3504e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3505e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3506e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3507e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3508e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (NumberFormatException e) {
3509e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3510e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3511e7c6998e0a953ae55487d4fe122739646f9280aasatok            } finally {
3512e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fis != null) {
3513e7c6998e0a953ae55487d4fe122739646f9280aasatok                    try {
3514e7c6998e0a953ae55487d4fe122739646f9280aasatok                        fis.close();
3515e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } catch (java.io.IOException e1) {
3516e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "Failed to close.");
3517e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3518e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3519e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3520e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3521e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
3522e7c6998e0a953ae55487d4fe122739646f9280aasatok
35239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
35249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
35259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
35269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3527ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
35289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Permission Denial: can't dump InputMethodManager from from pid="
35299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
35309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
35319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
35329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
35339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
35349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IInputMethod method;
35359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState client;
3536ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
35379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(pw);
3538ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
35399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
35409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("Current Input Method Manager state:");
35419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mMethodList.size();
35429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Input Methods:");
35439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
35449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo info = mMethodList.get(i);
35459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  InputMethod #" + i + ":");
35469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.dump(p, "    ");
35479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
35489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Clients:");
35499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState ci : mClients.values()) {
35509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  Client " + ci + ":");
35519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    client=" + ci.client);
35529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    inputContext=" + ci.inputContext);
35539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    sessionRequested=" + ci.sessionRequested);
35549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    curSession=" + ci.curSession);
35559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3556105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            p.println("  mCurMethodId=" + mCurMethodId);
35579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = mCurClient;
3558b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
3559b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
35609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
35619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mBoundToMethod=" + mBoundToMethod);
35629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurToken=" + mCurToken);
35639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurIntent=" + mCurIntent);
35649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = mCurMethod;
35659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurMethod=" + mCurMethod);
35669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mEnabledSession=" + mEnabledSession);
35679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mShowRequested=" + mShowRequested
35689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
35699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowForced=" + mShowForced
35709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mInputShown=" + mInputShown);
35713d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            p.println("  mCurUserActionNotificationSequenceNumber="
35723d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    + mCurUserActionNotificationSequenceNumber);
3573d4e6d467cd61d6bec1ae25744a415a96f0a0f760Dianne Hackborn            p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
35749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3575ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3576b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
35779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (client != null) {
35789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
35799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
35809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                client.client.asBinder().dump(fd, args);
35819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
35829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method client dead: " + e);
35839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3584b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3585b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method client.");
35869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3587ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3588b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
35899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (method != null) {
35909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
35919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
35929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                method.asBinder().dump(fd, args);
35939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
35949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method service dead: " + e);
35959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3596b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3597b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method service.");
35989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
35999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
36009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3601