InputMethodManagerService.java revision e463c745ef6901121837e88ca8597d062843b9dd
19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
2ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker *
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License"); you may not
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * use this file except in compliance with the License. You may obtain a copy of
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License at
6ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker *
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0
8ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker *
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * License for the specific language governing permissions and limitations under
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * the License.
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage com.android.server;
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport com.android.internal.content.PackageMonitor;
19d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
20d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
218e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils;
228e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.os.HandlerCaller;
24758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganovimport com.android.internal.os.SomeArgs;
25e7c6998e0a953ae55487d4fe122739646f9280aasatokimport com.android.internal.util.FastXmlSerializer;
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputContext;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethod;
2852a53526265c801b70eaf6dab1acf5c3f628f8a6Michael Wrightimport com.android.internal.view.IInputSessionCallback;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodClient;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodManager;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodSession;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.InputBindResult;
33ef2ea1faf6449f97a2423ecbdecce664c58bcbe1Adam Lesinskiimport com.android.server.statusbar.StatusBarManagerService;
3401038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport com.android.server.wm.WindowManagerService;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
36e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlPullParser;
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
38e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlSerializer;
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative;
414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.AppGlobals;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog;
434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.IUserSwitchObserver;
44f90a33e92a7c8d4040c0e660a62336eb7293d785satokimport android.app.KeyguardManager;
457cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.Notification;
467cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.NotificationManager;
47dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackbornimport android.app.PendingIntent;
485b927c431f54ea47c3333afb7940d79e2e863f1asatokimport android.content.BroadcastReceiver;
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface.OnCancelListener;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
55e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.content.IntentFilter;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ServiceConnection;
576da35a0c1205398b7df4776e359f7794584fb128Brandon Ballingerimport android.content.pm.ApplicationInfo;
584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.content.pm.IPackageManager;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ResolveInfo;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ServiceInfo;
62734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.content.pm.UserInfo;
63e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasaniimport android.content.res.Configuration;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver;
67857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onoratoimport android.inputmethodservice.InputMethodService;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
69e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.os.Environment;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IInterface;
734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.IRemoteCallback;
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.Process;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
784df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport android.os.ResultReceiver;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.UserHandle;
82734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.os.UserManager;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
85f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.text.style.SuggestionSpan;
8639606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
88f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.util.LruCache;
89ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.util.Pair;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
92e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Slog;
93e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Xml;
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
95c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.view.InputChannel;
9605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.LayoutInflater;
9705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.View;
9805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.ViewGroup;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
100ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.EditorInfo;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputBinding;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethod;
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodInfo;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
105ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.InputMethodSubtype;
10605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.ArrayAdapter;
10701038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton;
10801038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton.OnCheckedChangeListener;
10905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.RadioButton;
11001038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.Switch;
11105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.TextView;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
113e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.File;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
115e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileInputStream;
116e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileOutputStream;
1179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
120688bd47fccf1a1373e6287bc49b5b33fad12b7f3satokimport java.util.Collections;
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
1235b927c431f54ea47c3333afb7940d79e2e863f1asatokimport java.util.Locale;
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides a system service that manages input methods.
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InputMethodManagerService extends IInputMethodManager.Stub
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements ServiceConnection, Handler.Callback {
1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
1316ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    static final String TAG = "InputMethodManagerService";
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_IM_PICKER = 1;
134ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    static final int MSG_SHOW_IM_SUBTYPE_PICKER = 2;
13547a44916e2fb33cf4751906386d5f5c903b28d8bsatok    static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 3;
136217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    static final int MSG_SHOW_IM_CONFIG = 4;
137ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_INPUT = 1000;
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_INPUT = 1010;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_SOFT_INPUT = 1020;
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_HIDE_SOFT_INPUT = 1030;
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_ATTACH_TOKEN = 1040;
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_CREATE_SESSION = 1050;
144ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_START_INPUT = 2000;
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_RESTART_INPUT = 2010;
147ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_METHOD = 3000;
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_METHOD = 3010;
150a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn    static final int MSG_SET_ACTIVE = 3020;
151b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    static final int MSG_SET_CURSOR_ANCHOR_MONITOR_MODE = 3030;
152ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
15301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
15401038492ff0317f0d3cff54d8a7ee36bb31ff175satok
155bcacc322f83de1fe522081a20e0ac36ec8243763Satoshi Kataoka    static final long TIME_TO_RECONNECT = 3 * 1000;
156ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
157f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20;
158f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1598e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
160b6359414adabab2d64acc8ccc9e3b9c1b800b303satok    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
1618e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
1624e4569dab5c75804b01a19b2d6e6101b445c1c68satok
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Context mContext;
1647d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn    final Resources mRes;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Handler mHandler;
166d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final InputMethodSettings mSettings;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final SettingsObserver mSettingsObserver;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IWindowManager mIWindowManager;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HandlerCaller mCaller;
170119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final boolean mHasFeature;
1715ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private InputMethodFileManager mFileManager;
17201038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final HardKeyboardListener mHardKeyboardListener;
17301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final WindowManagerService mWindowManagerService;
174ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
175c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1);
176ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // All known input methods.  mMethodMap also serves as the global
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // lock for this class.
179d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
180d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
181f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
182f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
183d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    private final InputMethodSubtypeSwitchingController mSwitchingController;
184ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1852c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    // Used to bring IME service up to visible adjustment while it is being shown.
1862c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    final ServiceConnection mVisibleConnection = new ServiceConnection() {
1872c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceConnected(ComponentName name, IBinder service) {
1882c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1892c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1902c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceDisconnected(ComponentName name) {
1912c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1922c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    };
1932c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    boolean mVisibleBound = false;
1942c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1957cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    // Ongoing notification
196661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private NotificationManager mNotificationManager;
197661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private KeyguardManager mKeyguardManager;
198661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private StatusBarManagerService mStatusBar;
199661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private Notification mImeSwitcherNotification;
200661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private PendingIntent mImeSwitchPendingIntent;
201b858c732f665fe9610f2d913230ae625f44a8caasatok    private boolean mShowOngoingImeSwitcherForPhones;
2027cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean mNotificationShown;
2030a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok    private final boolean mImeSelectedOnBoot;
2047cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SessionState {
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ClientState client;
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethod method;
208c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
209c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        IInputMethodSession session;
210c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        InputChannel channel;
211ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "SessionState{uid " + client.uid + " pid " + client.pid
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " method " + Integer.toHexString(
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(method))
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " session " + Integer.toHexString(
2189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(session))
219c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    + " channel " + channel
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "}";
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState(ClientState _client, IInputMethod _method,
224c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                IInputMethodSession _session, InputChannel _channel) {
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = _method;
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            session = _session;
228c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            channel = _channel;
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
231ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
232c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    static final class ClientState {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethodClient client;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputContext inputContext;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int uid;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int pid;
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final InputBinding binding;
238ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean sessionRequested;
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState curSession;
241ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ClientState{" + Integer.toHexString(
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.identityHashCode(this)) + " uid " + uid
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " pid " + pid + "}";
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState(IInputMethodClient _client, IInputContext _inputContext,
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int _uid, int _pid) {
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inputContext = _inputContext;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uid = _uid;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pid = _pid;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
258ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, ClientState> mClients
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<IBinder, ClientState>();
261ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
263a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     * Set once the system is ready to run third party code.
264a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     */
265a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    boolean mSystemReady;
266ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
267a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    /**
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Id of the currently selected input method.
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurMethodId;
271ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The current binding sequence number, incremented every time there is
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new bind performed.
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCurSeq;
277ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The client that is currently bound to an input method.
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ClientState mCurClient;
282ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
284b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     * The last window token that gained focus.
285b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     */
286b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    IBinder mCurFocusedWindow;
287ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
288b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    /**
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input context last provided by the current client.
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputContext mCurInputContext;
292ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The attributes last provided by the current client.
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mCurAttribute;
297ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method ID of the input method service that we are currently
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * connected to or in the process of connecting to.
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurId;
303ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
305ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * The current subtype of the current input method.
306ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
307ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private InputMethodSubtype mCurrentSubtype;
308ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3094e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
310f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
311f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes =
312f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
313ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
314e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    // Was the keyguard locked when this client became current?
315e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean mCurClientInKeyguard;
316e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
317ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set to true if our ServiceConnection is currently actively bound to
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a service (whether or not we have gotten its IBinder back yet).
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mHaveConnection;
322ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if the client has asked for the input method to be shown.
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowRequested;
327ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were explicitly told to show the input method.
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowExplicitlyRequested;
332ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were forced to be shown.
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowForced;
337ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we last told the input method to show itself.
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputShown;
342ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The Intent used to connect to the current input method.
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Intent mCurIntent;
347ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The token we have made for the currently active input method, to
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * identify it in the future.
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mCurToken;
353ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If non-null, this is the input method service we are currently connected
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to.
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputMethod mCurMethod;
359ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time that we last initiated a bind to the input method, to determine
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if we should try to disconnect and reconnect to it.
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mLastBindTime;
365ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Have we called mCurMethod.bindInput()?
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mBoundToMethod;
370ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Currently enabled session.  Only touched by service thread, not
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * protected by a lock.
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SessionState mEnabledSession;
376ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * True if the screen is on.  The value is true initially.
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mScreenOn = true;
381ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
382857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
383857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mImeWindowVis;
384857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
38505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog.Builder mDialogBuilder;
38605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog mSwitchingDialog;
38701038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private View mSwitchingDialogTitleView;
38805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private InputMethodInfo[] mIms;
38905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private int[] mSubtypeIds;
3905b927c431f54ea47c3333afb7940d79e2e863f1asatok    private Locale mLastSystemLocale;
3914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
3924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final IPackageManager mIPackageManager;
393ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SettingsObserver extends ContentObserver {
395fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        String mLastEnabled = "";
396fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SettingsObserver(Handler handler) {
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(handler);
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver resolver = mContext.getContentResolver();
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resolver.registerContentObserver(Settings.Secure.getUriFor(
4019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
402ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            resolver.registerContentObserver(Settings.Secure.getUriFor(
403b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok                    Settings.Secure.ENABLED_INPUT_METHODS), false, this);
404b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok            resolver.registerContentObserver(Settings.Secure.getUriFor(
405ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this);
4069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
407ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void onChange(boolean selfChange) {
4099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
410fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                boolean enabledChanged = false;
411fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                String newEnabled = mSettings.getEnabledInputMethodsStr();
412fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                if (!mLastEnabled.equals(newEnabled)) {
413fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    mLastEnabled = newEnabled;
414fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    enabledChanged = true;
415fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
416fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                updateFromSettingsLocked(enabledChanged);
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
420ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
4224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private void updateActive() {
4234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // Inform the current client of the change in active status
4244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (mCurClient != null && mCurClient.client != null) {
4254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
4264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
4274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
4324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String action = intent.getAction();
4334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (Intent.ACTION_SCREEN_ON.equals(action)) {
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = true;
4353afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                refreshImeWindowVisibilityLocked();
4364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = false;
44015452a487a4c0274f4217cd060aa54446f30a8f3satok                setImeWindowVisibilityStatusHiddenLocked();
4414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
444105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                hideInputMethodMenu();
4454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // No need to updateActive
446105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                return;
447734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani            } else if (Intent.ACTION_USER_ADDED.equals(action)
448734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                    || Intent.ACTION_USER_REMOVED.equals(action)) {
4492a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                updateCurrentProfileIds();
450734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                return;
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unexpected intent " + intent);
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
456ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
45721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
4584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private boolean isChangingPackagesOfCurrentUser() {
4594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final int userId = getChangingUserId();
4604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final boolean retval = userId == mSettings.getCurrentUserId();
4614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
46281f8b7c66750a0a89c8e6b6037136ca169c96f95satok                if (!retval) {
46381f8b7c66750a0a89c8e6b6037136ca169c96f95satok                    Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
46481f8b7c66750a0a89c8e6b6037136ca169c96f95satok                }
4654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return retval;
4674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
47021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
4714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
4724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return false;
4734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
47421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
4754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
47621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                final int N = mMethodList.size();
47721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curInputMethodId != null) {
47821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    for (int i=0; i<N; i++) {
47921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
48021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (imi.getId().equals(curInputMethodId)) {
48121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            for (String pkg : packages) {
48221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                if (imi.getPackageName().equals(pkg)) {
48321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    if (!doit) {
48421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        return true;
48521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    }
486723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                    resetSelectedInputMethodAndSubtypeLocked("");
48721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    chooseNewDefaultIMELocked();
48821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    return true;
48921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                }
49021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            }
49121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
49221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
49308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                }
49408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu            }
49521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return false;
49621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
497ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
49821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        @Override
49921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
5004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
5014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
5024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
50321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo curIm = null;
5054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int N = mMethodList.size();
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (curInputMethodId != null) {
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<N; i++) {
50921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
510e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imiId = imi.getId();
511e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (imiId.equals(curInputMethodId)) {
51221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            curIm = imi;
51321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
514e7c6998e0a953ae55487d4fe122739646f9280aasatok
51521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        int change = isPackageDisappearing(imi.getPackageName());
516e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (isPackageModified(imi.getPackageName())) {
517e7c6998e0a953ae55487d4fe122739646f9280aasatok                            mFileManager.deleteAllInputMethodSubtypes(imiId);
518e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
51921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (change == PACKAGE_TEMPORARY_CHANGE
52021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                || change == PACKAGE_PERMANENT_CHANGE) {
5218a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Input method uninstalled, disabling: "
52221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    + imi.getComponent());
52321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            setInputMethodEnabledLocked(imi.getId(), false);
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
527ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
528f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(
529f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        mMethodList, mMethodMap, false /* resetDefaultEnabledIme */);
53021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed = false;
532ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
53308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                if (curIm != null) {
53421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    int change = isPackageDisappearing(curIm.getPackageName());
53521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (change == PACKAGE_TEMPORARY_CHANGE
53621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            || change == PACKAGE_PERMANENT_CHANGE) {
53708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        ServiceInfo si = null;
53808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        try {
5394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            si = mIPackageManager.getServiceInfo(
5404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    curIm.getComponent(), 0, mSettings.getCurrentUserId());
5414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        } catch (RemoteException ex) {
54208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
54308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (si == null) {
54408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Uh oh, current input method is no longer around!
54508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Pick another one...
5468a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
54715452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
54821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            if (!chooseNewDefaultIMELocked()) {
54908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                changed = true;
55008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                curIm = null;
5518a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.i(TAG, "Unsetting current input method");
552723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                resetSelectedInputMethodAndSubtypeLocked("");
55308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
55408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
55508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
55621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
557ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
55821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curIm == null) {
55921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // We currently don't have a default input method... is
56021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // one now available?
56121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    changed = chooseNewDefaultIMELocked();
56221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
563ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
56421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (changed) {
565fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(false);
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
570ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
571c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private static final class MethodCallback extends IInputSessionCallback.Stub {
572e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard        private final InputMethodManagerService mParentIMMS;
573c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final IInputMethod mMethod;
574c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final InputChannel mChannel;
575ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
576c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        MethodCallback(InputMethodManagerService imms, IInputMethod method,
577c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel) {
578e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard            mParentIMMS = imms;
579c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mMethod = method;
580c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mChannel = channel;
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
582ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
583e7c6998e0a953ae55487d4fe122739646f9280aasatok        @Override
584c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        public void sessionCreated(IInputMethodSession session) {
5856b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            long ident = Binder.clearCallingIdentity();
5866b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            try {
5876b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                mParentIMMS.onSessionCreated(mMethod, session, mChannel);
5886b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            } finally {
5896b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                Binder.restoreCallingIdentity(ident);
5906b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
593ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
59401038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private class HardKeyboardListener
59501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            implements WindowManagerService.OnHardKeyboardStatusChangeListener {
59601038492ff0317f0d3cff54d8a7ee36bb31ff175satok        @Override
59701038492ff0317f0d3cff54d8a7ee36bb31ff175satok        public void onHardKeyboardStatusChange(boolean available, boolean enabled) {
59801038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mHandler.sendMessage(mHandler.obtainMessage(
59901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0, enabled ? 1 : 0));
60001038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
60101038492ff0317f0d3cff54d8a7ee36bb31ff175satok
60201038492ff0317f0d3cff54d8a7ee36bb31ff175satok        public void handleHardKeyboardStatusChange(boolean available, boolean enabled) {
60301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            if (DEBUG) {
60401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                Slog.w(TAG, "HardKeyboardStatusChanged: available = " + available + ", enabled = "
60501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        + enabled);
60601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
60701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            synchronized(mMethodMap) {
60801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
60901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        && mSwitchingDialog.isShowing()) {
61001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mSwitchingDialogTitleView.findViewById(
61101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            com.android.internal.R.id.hard_keyboard_section).setVisibility(
61201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    available ? View.VISIBLE : View.GONE);
61301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
61401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
61501038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
61601038492ff0317f0d3cff54d8a7ee36bb31ff175satok    }
61701038492ff0317f0d3cff54d8a7ee36bb31ff175satok
61801038492ff0317f0d3cff54d8a7ee36bb31ff175satok    public InputMethodManagerService(Context context, WindowManagerService windowManager) {
6194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mIPackageManager = AppGlobals.getPackageManager();
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
6217d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn        mRes = context.getResources();
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new Handler(this);
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIWindowManager = IWindowManager.Stub.asInterface(
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.WINDOW_SERVICE));
625ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
626e7c6998e0a953ae55487d4fe122739646f9280aasatok            @Override
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void executeMessage(Message msg) {
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleMessage(msg);
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
630ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        }, true /*asyncHandler*/);
63101038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mWindowManagerService = windowManager;
63201038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mHardKeyboardListener = new HardKeyboardListener();
633119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        mHasFeature = context.getPackageManager().hasSystemFeature(
634119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                PackageManager.FEATURE_INPUT_METHODS);
6357cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6367cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification = new Notification();
6377cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
6387cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.when = 0;
6397cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT;
6407cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.tickerText = null;
6417cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.defaults = 0; // please be quiet
6427cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.sound = null;
6437cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.vibrate = null;
644590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
645590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler        // Tag this notification specially so SystemUI knows it's important
646fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
647fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.category = Notification.CATEGORY_SYSTEM;
648590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
6497cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
650683e2383c8549f95e00bade15daed3dbddf13950satok        mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
651b858c732f665fe9610f2d913230ae625f44a8caasatok
652b858c732f665fe9610f2d913230ae625f44a8caasatok        mShowOngoingImeSwitcherForPhones = false;
6537cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final IntentFilter broadcastFilter = new IntentFilter();
6554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
6564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
6574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
658734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
659734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
6604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
661ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
6627cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mNotificationShown = false;
6634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        int userId = 0;
6644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        try {
6654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            ActivityManagerNative.getDefault().registerUserSwitchObserver(
6664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    new IUserSwitchObserver.Stub() {
6674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
6695ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            synchronized(mMethodMap) {
6705ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                                switchUserLocked(newUserId);
6715ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            }
6724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            if (reply != null) {
6734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                try {
6744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    reply.sendResult(null);
6754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                } catch (RemoteException e) {
6764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                }
6774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            }
6784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
6794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
6804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
6824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
6834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    });
6844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
6854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } catch (RemoteException e) {
6864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
6874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
68881f8b7c66750a0a89c8e6b6037136ca169c96f95satok        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
689913a8925c07e854a80bf5df87561f290d3a56d61satok
690d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        // mSettings should be created before buildInputMethodListLocked
691df31ae6a3011d47421a6ac10021f9649dc34a156satok        mSettings = new InputMethodSettings(
6924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
6932a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
6945ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, userId);
695d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mSwitchingController = new InputMethodSubtypeSwitchingController(mSettings);
696d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mSwitchingController.resetCircularListLocked(context);
6970a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
6980a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        // Just checking if defaultImiId is empty or not
6994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
700f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (DEBUG) {
701f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "Initial default ime = " + defaultImiId);
702f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
7030a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
7040a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
705f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        buildInputMethodListLocked(mMethodList, mMethodMap,
706f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
707d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        mSettings.enableAllIMEsIfThereIsNoEnabledIME();
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7090a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!mImeSelectedOnBoot) {
7100a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            Slog.w(TAG, "No IME selected. Choose the most applicable IME.");
7115b927c431f54ea47c3333afb7940d79e2e863f1asatok            resetDefaultImeLocked(context);
7125b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7135b927c431f54ea47c3333afb7940d79e2e863f1asatok
7145b927c431f54ea47c3333afb7940d79e2e863f1asatok        mSettingsObserver = new SettingsObserver(mHandler);
715fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        updateFromSettingsLocked(true);
7165b927c431f54ea47c3333afb7940d79e2e863f1asatok
7175b927c431f54ea47c3333afb7940d79e2e863f1asatok        // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
7185b927c431f54ea47c3333afb7940d79e2e863f1asatok        // according to the new system locale.
7195b927c431f54ea47c3333afb7940d79e2e863f1asatok        final IntentFilter filter = new IntentFilter();
7205b927c431f54ea47c3333afb7940d79e2e863f1asatok        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
7215b927c431f54ea47c3333afb7940d79e2e863f1asatok        mContext.registerReceiver(
7225b927c431f54ea47c3333afb7940d79e2e863f1asatok                new BroadcastReceiver() {
7235b927c431f54ea47c3333afb7940d79e2e863f1asatok                    @Override
7245b927c431f54ea47c3333afb7940d79e2e863f1asatok                    public void onReceive(Context context, Intent intent) {
7255b927c431f54ea47c3333afb7940d79e2e863f1asatok                        synchronized(mMethodMap) {
726ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            resetStateIfCurrentLocaleChangedLocked();
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7295b927c431f54ea47c3333afb7940d79e2e863f1asatok                }, filter);
7305b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7315b927c431f54ea47c3333afb7940d79e2e863f1asatok
7325b927c431f54ea47c3333afb7940d79e2e863f1asatok    private void resetDefaultImeLocked(Context context) {
7335b927c431f54ea47c3333afb7940d79e2e863f1asatok        // Do not reset the default (current) IME when it is a 3rd-party IME
7348e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        if (mCurMethodId != null
7358e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
7365b927c431f54ea47c3333afb7940d79e2e863f1asatok            return;
7375b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7385b927c431f54ea47c3333afb7940d79e2e863f1asatok
7395b927c431f54ea47c3333afb7940d79e2e863f1asatok        InputMethodInfo defIm = null;
7405b927c431f54ea47c3333afb7940d79e2e863f1asatok        for (InputMethodInfo imi : mMethodList) {
7415b927c431f54ea47c3333afb7940d79e2e863f1asatok            if (defIm == null) {
7428e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                if (InputMethodUtils.isValidSystemDefaultIme(
7438e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSystemReady, imi, context)) {
7445b927c431f54ea47c3333afb7940d79e2e863f1asatok                    defIm = imi;
7455b927c431f54ea47c3333afb7940d79e2e863f1asatok                    Slog.i(TAG, "Selected default: " + imi.getId());
7465b927c431f54ea47c3333afb7940d79e2e863f1asatok                }
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7485b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7495b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm == null && mMethodList.size() > 0) {
7508e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            defIm = InputMethodUtils.getMostApplicableDefaultIME(
7518e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
7525b927c431f54ea47c3333afb7940d79e2e863f1asatok            Slog.i(TAG, "No default found, using " + defIm.getId());
7535b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7545b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm != null) {
7555b927c431f54ea47c3333afb7940d79e2e863f1asatok            setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
7565b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7575b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7585b927c431f54ea47c3333afb7940d79e2e863f1asatok
7597f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka    private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
7607f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            final boolean resetDefaultEnabledIme) {
7614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!mSystemReady) {
7624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // not system ready
7634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
7644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
7654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final Locale newLocale = mRes.getConfiguration().locale;
7664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!updateOnlyWhenLocaleChanged
7674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
7684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                hideCurrentInputLocked(0, null);
7704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurMethodId = null;
7712ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
7724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
7734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
7744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.i(TAG, "Locale has been changed to " + newLocale);
7754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
776d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            // CircularList should be reset when the locale is changed.
777d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            mSwitchingController.resetCircularListLocked(mContext);
7787f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            buildInputMethodListLocked(mMethodList, mMethodMap, resetDefaultEnabledIme);
7794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selectedImiId = mSettings.getSelectedInputMethod();
7814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (TextUtils.isEmpty(selectedImiId)) {
7824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // This is the first time of the user switch and
7834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // set the current ime to the proper one.
7844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    resetDefaultImeLocked(mContext);
7854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
786d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka            } else {
787d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                // If the locale is changed, needs to reset the default ime
788d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                resetDefaultImeLocked(mContext);
7894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
790fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            updateFromSettingsLocked(true);
7914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            mLastSystemLocale = newLocale;
7924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                try {
7944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    startInputInnerLocked();
7954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } catch (RuntimeException e) {
7964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    Slog.w(TAG, "Unexpected exception", e);
7974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
7984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
7994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
8004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
802ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka    private void resetStateIfCurrentLocaleChangedLocked() {
8037f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */,
8047f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka                true /* resetDefaultImeLocked */);
8054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8075ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private void switchUserLocked(int newUserId) {
8084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mSettings.setCurrentUserId(newUserId);
8092a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
8105ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        // InputMethodFileManager should be reset when the user is changed
8115ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
8127f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
8137c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // For secondary users, the list of enabled IMEs may not have been updated since the
8147c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // callbacks to PackageMonitor are ignored for the secondary user. Here, defaultImiId may
8157c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // not be empty even if the IME has been uninstalled by the primary user.
8167c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // Even in such cases, IMMS works fine because it will find the most applicable
8177c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // IME for that user.
818ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
8197f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        if (DEBUG) {
8207f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId);
8217f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        }
8227f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(false  /* updateOnlyWhenLocaleChanged */,
823ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                initialUserSwitch /* needsToResetDefaultIme */);
824ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        if (initialUserSwitch) {
825ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka            InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(),
826ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
827ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        }
8284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8302a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy    void updateCurrentProfileIds() {
8312a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        List<UserInfo> profiles =
8322a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
8332a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
8342a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        for (int i = 0; i < currentProfileIds.length; i++) {
8352a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy            currentProfileIds[i] = profiles.get(i).id;
836734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        }
8372a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        mSettings.setCurrentProfileIds(currentProfileIds);
838734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani    }
839734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws RemoteException {
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.onTransact(code, data, reply, flags);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The input method manager only throws security exceptions, so let's
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // log all others.
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!(e instanceof SecurityException)) {
849164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf(TAG, "Input Method Manager Crash", e);
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
855a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning(StatusBarManagerService statusBar) {
856a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        synchronized (mMethodMap) {
8574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
8584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "--- systemReady");
8594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
860a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            if (!mSystemReady) {
861a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn                mSystemReady = true;
8624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mKeyguardManager =
8634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
864661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mNotificationManager = (NotificationManager)
865661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
866661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mStatusBar = statusBar;
867661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                statusBar.setIconVisibility("ime", false);
868661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                updateImeWindowStatusLocked();
869b858c732f665fe9610f2d913230ae625f44a8caasatok                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
870b858c732f665fe9610f2d913230ae625f44a8caasatok                        com.android.internal.R.bool.show_ongoing_ime_switcher);
87101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mShowOngoingImeSwitcherForPhones) {
87201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mWindowManagerService.setOnHardKeyboardStatusChangeListener(
87301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mHardKeyboardListener);
87401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
875f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(mMethodList, mMethodMap,
876f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
8770a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (!mImeSelectedOnBoot) {
8780a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                    Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
879ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    resetStateIfCurrentLocaleChangedLocked();
880ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
881ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mContext.getPackageManager(),
882ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mSettings.getEnabledInputMethodListLocked());
8830a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
8840a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                mLastSystemLocale = mRes.getConfiguration().locale;
885cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                try {
886cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    startInputInnerLocked();
887cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                } catch (RuntimeException e) {
8888a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Unexpected exception", e);
889cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
890a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            }
891a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
893ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
89415452a487a4c0274f4217cd060aa54446f30a8f3satok    private void setImeWindowVisibilityStatusHiddenLocked() {
89515452a487a4c0274f4217cd060aa54446f30a8f3satok        mImeWindowVis = 0;
89615452a487a4c0274f4217cd060aa54446f30a8f3satok        updateImeWindowStatusLocked();
89715452a487a4c0274f4217cd060aa54446f30a8f3satok    }
89815452a487a4c0274f4217cd060aa54446f30a8f3satok
8993afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    private void refreshImeWindowVisibilityLocked() {
9003afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final Configuration conf = mRes.getConfiguration();
9013afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean haveHardKeyboard = conf.keyboard
9023afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                != Configuration.KEYBOARD_NOKEYS;
9033afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean hardKeyShown = haveHardKeyboard
9043afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                && conf.hardKeyboardHidden
9053afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                        != Configuration.HARDKEYBOARDHIDDEN_YES;
906e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
907e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean isScreenLocked = isKeyguardLocked();
908e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean inputActive = !isScreenLocked && (mInputShown || hardKeyShown);
90936439b43121751ae94e703da52b2763aa17d0720John Spurlock        // We assume the softkeyboard is shown when the input is active as long as the
91036439b43121751ae94e703da52b2763aa17d0720John Spurlock        // hard keyboard is not shown.
91136439b43121751ae94e703da52b2763aa17d0720John Spurlock        final boolean inputVisible = inputActive && !hardKeyShown;
91236439b43121751ae94e703da52b2763aa17d0720John Spurlock        mImeWindowVis = (inputActive ? InputMethodService.IME_ACTIVE : 0)
91336439b43121751ae94e703da52b2763aa17d0720John Spurlock                | (inputVisible ? InputMethodService.IME_VISIBLE : 0);
9143afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        updateImeWindowStatusLocked();
9153afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    }
9163afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok
91715452a487a4c0274f4217cd060aa54446f30a8f3satok    private void updateImeWindowStatusLocked() {
918dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok        setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
919661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    }
920661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn
9214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // ---------------------------------------------------------------------------------------
9224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
9234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 1) it comes from the system process
9244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 2) the calling process' user id is identical to the current user id IMMS thinks.
9254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean calledFromValidUser() {
9264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int uid = Binder.getCallingUid();
9274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int userId = UserHandle.getUserId(uid);
9284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
9294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
9304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
9314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + " calling userId = " + userId + ", foreground user id = "
93287c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
93387c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + InputMethodUtils.getApiCallStack());
9344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9352a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
9364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return true;
9374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
938135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka
939135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
940135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // foreground user, not for the user of that process. Accordingly InputMethodManagerService
941135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // must not manage background users' states in any functions.
942135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Note that privacy-sensitive IPCs, such as setInputMethod, are still securely guarded
943135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // by a token.
944135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        if (mContext.checkCallingOrSelfPermission(
945135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
946135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        == PackageManager.PERMISSION_GRANTED) {
947135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            if (DEBUG) {
948135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                Slog.d(TAG, "--- Access granted because the calling process has "
949135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        + "the INTERACT_ACROSS_USERS_FULL permission");
950135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            }
951135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            return true;
952135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        }
9530766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka        Slog.w(TAG, "--- IPC called from background users. Ignore. \n"
9540766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                + InputMethodUtils.getStackTrace());
955135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        return false;
9564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
9584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean bindCurrentInputMethodService(
9594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Intent service, ServiceConnection conn, int flags) {
9604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (service == null || conn == null) {
9614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
9624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
9634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
96427b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani        return mContext.bindServiceAsUser(service, conn, flags,
96527b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                new UserHandle(mSettings.getCurrentUserId()));
9664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
968e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
9699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getInputMethodList() {
9704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
9714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
9724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
9734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ArrayList<InputMethodInfo>(mMethodList);
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getEnabledInputMethodList() {
9814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
9824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
9834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
9844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
986d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return mSettings.getEnabledInputMethodListLocked();
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9908e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    /**
991b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka     * @param imiId if null, returns enabled subtypes for the current imi
9928e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     * @return enabled subtypes of the specified imi
9938e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     */
994e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
995b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
99616331c8a1d33defccc5cbb18694def79196c921bsatok            boolean allowsImplicitlySelectedSubtypes) {
9974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
9984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
999b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            return Collections.<InputMethodSubtype>emptyList();
10004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
100167ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        synchronized (mMethodMap) {
1002b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            final InputMethodInfo imi;
1003b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imiId == null && mCurMethodId != null) {
10048e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                imi = mMethodMap.get(mCurMethodId);
1005b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            } else {
1006b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                imi = mMethodMap.get(imiId);
1007b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            }
1008b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imi == null) {
1009b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                return Collections.<InputMethodSubtype>emptyList();
10108e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            }
10118e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            return mSettings.getEnabledInputMethodSubtypeListLocked(
10128e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mContext, imi, allowsImplicitlySelectedSubtypes);
101367ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        }
101467ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok    }
101567ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok
1016e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addClient(IInputMethodClient client,
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IInputContext inputContext, int uid, int pid) {
10194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClients.put(client.asBinder(), new ClientState(client,
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    inputContext, uid, pid));
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1027ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1028e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeClient(IInputMethodClient client) {
10304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1034c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ClientState cs = mClients.remove(client.asBinder());
1035c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (cs != null) {
1036c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
1037c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1040ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void executeOrSendMessage(IInterface target, Message msg) {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         if (target.asBinder() instanceof Binder) {
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             mCaller.sendMessage(msg);
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         } else {
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             handleMessage(msg);
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             msg.recycle();
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         }
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1049ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1050b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void unbindCurrentClientLocked() {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != null) {
10528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client = "
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurClient.client.asBinder());
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBoundToMethod) {
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBoundToMethod = false;
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_INPUT, mCurMethod));
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1061a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn
1062a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1063a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    MSG_SET_ACTIVE, 0, mCurClient));
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient.sessionRequested = false;
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient = null;
1068ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1069105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1072ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getImeShowFlags() {
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_FORCED
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    | InputMethod.SHOW_EXPLICIT;
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mShowExplicitlyRequested) {
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_EXPLICIT;
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1083ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getAppShowFlags() {
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_FORCED;
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mShowExplicitlyRequested) {
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_IMPLICIT;
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
10929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1093ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10947663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult attachNewInputLocked(boolean initial) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBoundToMethod) {
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBoundToMethod = true;
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SessionState session = mCurClient.curSession;
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initial) {
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_START_INPUT, session, mCurInputContext, mCurAttribute));
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_RESTART_INPUT, session, mCurInputContext, mCurAttribute));
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowRequested) {
11098a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
11104df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            showCurrentInputLocked(getAppShowFlags(), null);
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11121951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown        return new InputBindResult(session.session,
11131951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                session.channel != null ? session.channel.dup() : null, mCurId, mCurSeq);
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1115ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBindResult startInputLocked(IInputMethodClient client,
11177663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If no method is currently selected, do nothing.
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethodId == null) {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNoBinding;
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1122ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState cs = mClients.get(client.asBinder());
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cs == null) {
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("unknown client "
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + client.asBinder());
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1128ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check with the window manager to make sure this client actually
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // has a window with focus.  If not, reject.  This is thread safe
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // because if the focus changes some time before or after, the
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // next client receiving focus that has any interest in input will
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // be calling through here after that change happens.
11368a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Starting input on non-focused client " + cs.client
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
11419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1142ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11437663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
11447663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    }
11457663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11467663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult startInputUncheckedLocked(ClientState cs,
11477663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11487663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        // If no method is currently selected, do nothing.
11497663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        if (mCurMethodId == null) {
11507663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            return mNoBinding;
11517663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        }
11527663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != cs) {
1154e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            // Was the keyguard locked when switching over to the new client?
1155e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            mCurClientInKeyguard = isKeyguardLocked();
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the client is changing, we need to switch over to the new
11579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // one.
1158b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
11598a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "switching to client: client = "
1160e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the screen is on, inform the new client it is active
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mScreenOn) {
1164a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                executeOrSendMessage(cs.client, mCaller.obtainMessageIO(
1165a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, cs));
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1168ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Bump up the sequence for this client and attach it.
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurSeq++;
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurSeq <= 0) mCurSeq = 1;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurClient = cs;
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurInputContext = inputContext;
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurAttribute = attribute;
1175ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check if the input method is changing.
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurId != null && mCurId.equals(mCurMethodId)) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cs.curSession != null) {
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Fast case: if we are already connected to the input method,
11809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // then just return it.
11817663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return attachNewInputLocked(
11827663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mHaveConnection) {
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Return to client, and we will get back with it when
11879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we have had a session made for it.
1188c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(cs);
1189c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return new InputBindResult(null, null, mCurId, mCurSeq);
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (SystemClock.uptimeMillis()
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        < (mLastBindTime+TIME_TO_RECONNECT)) {
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // In this case we have connected to the service, but
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // don't yet have its interface.  If it hasn't been too
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // long since we did the connection, we'll return to
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the client and wait to get the service interface so
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we can report back.  If it has been too long, we want
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to fall through so we can try a disconnect/reconnect
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to see if we can get back in touch with the service.
1199c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return new InputBindResult(null, null, mCurId, mCurSeq);
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1201ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                    EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
1202ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                            mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1206ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1207a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        return startInputInnerLocked();
1208a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    }
1209ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1210a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    InputBindResult startInputInnerLocked() {
1211a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (mCurMethodId == null) {
1212a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            return mNoBinding;
1213a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1214ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1215a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (!mSystemReady) {
1216a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // If the system is not yet ready, we shouldn't be running third
1217a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // party code.
1218c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return new InputBindResult(null, null, mCurMethodId, mCurSeq);
1219a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1220ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(mCurMethodId);
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1225ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12262ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn        unbindCurrentMethodLocked(false, true);
1227ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent.setComponent(info.getComponent());
1230dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1231dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                com.android.internal.R.string.input_method_binding_label);
1232dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1233dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
12344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
1235f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND
1236f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_SHOWING_UI)) {
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastBindTime = SystemClock.uptimeMillis();
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHaveConnection = true;
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurId = info.getId();
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurToken = new Binder();
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
1242ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIWindowManager.addWindowToken(mCurToken,
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1247c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return new InputBindResult(null, null, mCurId, mCurSeq);
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIntent = null;
12508a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Failure connecting to input method service: "
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurIntent);
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1255ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1256e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBindResult startInput(IInputMethodClient client,
12587663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
12594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
12604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
12614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final long ident = Binder.clearCallingIdentity();
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
12657663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return startInputLocked(client, inputContext, attribute, controlFlags);
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1271ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1272e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishInput(IInputMethodClient client) {
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1275ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1276e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceConnected(ComponentName name, IBinder service) {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCurMethod = IInputMethod.Stub.asInterface(service);
1281cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                if (mCurToken == null) {
12828a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Service connected without a token!");
12832ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                    unbindCurrentMethodLocked(false, false);
1284cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    return;
1285cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1286e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
1287cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
1288cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1290c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
1291c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(mCurClient);
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1297c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void onSessionCreated(IInputMethod method, IInputMethodSession session,
1298c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel channel) {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && method != null
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && mCurMethod.asBinder() == method.asBinder()) {
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1303c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCurClient.curSession = new SessionState(mCurClient,
1305c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                            method, session, channel);
13067663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    InputBindResult res = attachNewInputLocked(true);
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (res.method != null) {
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                MSG_BIND_METHOD, mCurClient.client, res));
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1311c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return;
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1315c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1316c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        // Session abandoned.  Close its associated input channel.
1317c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        channel.dispose();
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1319ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13202ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn    void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
13212c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mVisibleBound) {
13222c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
13232c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
13242c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
13252c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1326b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mHaveConnection) {
1327b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mContext.unbindService(this);
1328b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mHaveConnection = false;
1329b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1330ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1331b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mCurToken != null) {
1332b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            try {
13338a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
13342ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
1335e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    // The current IME is shown. Hence an IME switch (transition) is happening.
1336e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    mWindowManagerService.saveLastInputMethodWindowForTransition();
1337e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                }
1338b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mIWindowManager.removeWindowToken(mCurToken);
1339b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            } catch (RemoteException e) {
1340b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
1341b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mCurToken = null;
1342b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1343ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1344105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mCurId = null;
1345b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        clearCurMethodLocked();
1346ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1347b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (reportToClient && mCurClient != null) {
1348b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1349b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
1350b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1351b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    }
1352c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1353c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void requestClientSessionLocked(ClientState cs) {
1354c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (!cs.sessionRequested) {
1355c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
1356c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
1357c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            cs.sessionRequested = true;
1358c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
1359c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    MSG_CREATE_SESSION, mCurMethod, channels[1],
1360c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    new MethodCallback(this, mCurMethod, channels[0])));
1361c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
1362c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1363c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1364c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void clearClientSessionLocked(ClientState cs) {
1365c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        finishSessionLocked(cs.curSession);
1366c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.curSession = null;
1367c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.sessionRequested = false;
1368c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1369c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1370c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private void finishSessionLocked(SessionState sessionState) {
1371c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (sessionState != null) {
1372c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.session != null) {
1373c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                try {
1374c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    sessionState.session.finishSession();
1375c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } catch (RemoteException e) {
1376c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    Slog.w(TAG, "Session failed to close due to remote exception", e);
1377c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    setImeWindowVisibilityStatusHiddenLocked();
1378c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
1379c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.session = null;
1380c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
1381c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.channel != null) {
1382c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel.dispose();
1383c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel = null;
13840c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            }
13850c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor        }
13860c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor    }
1387ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1388b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void clearCurMethodLocked() {
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState cs : mClients.values()) {
1391c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
13929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13930c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor
1394c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            finishSessionLocked(mEnabledSession);
13950c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            mEnabledSession = null;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurMethod = null;
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1398661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        if (mStatusBar != null) {
1399661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn            mStatusBar.setIconVisibility("ime", false);
1400661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        }
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1402ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1403e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceDisconnected(ComponentName name) {
14059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14068a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mCurIntent=" + mCurIntent);
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && mCurIntent != null
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && name.equals(mCurIntent.getComponent())) {
1410b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                clearCurMethodLocked();
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We consider this to be a new bind attempt, since the system
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // should now try to restart the service for us.
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastBindTime = SystemClock.uptimeMillis();
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mShowRequested = mInputShown;
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputShown = false;
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1424f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
1426cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (token == null || mCurToken != token) {
1430cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                Slog.w(TAG, "Ignoring setInputMethod of uid " + uid + " token: " + token);
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1433ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
14359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (iconId == 0) {
14368a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
1437661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1438661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", false);
1439661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (packageName != null) {
14418a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
14426179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    CharSequence contentDescription = null;
14436179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    try {
14444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        // Use PackageManager to load label
14454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        final PackageManager packageManager = mContext.getPackageManager();
14466179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        contentDescription = packageManager.getApplicationLabel(
14474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mIPackageManager.getApplicationInfo(packageName, 0,
14484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                        mSettings.getCurrentUserId()));
14494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    } catch (RemoteException e) {
14506179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        /* ignore */
14516179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    }
1452661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1453661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIcon("ime", packageName, iconId, 0,
1454661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                contentDescription  != null
1455661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                        ? contentDescription.toString() : null);
1456661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", true);
1457661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14657cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean needsToShowImeSwitchOngoingNotification() {
14667cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        if (!mShowOngoingImeSwitcherForPhones) return false;
14672c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        if (isScreenLocked()) return false;
14687cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        synchronized (mMethodMap) {
14697cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
14707cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            final int N = imis.size();
1471b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N > 2) return true;
1472b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N < 1) return false;
1473b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int nonAuxCount = 0;
1474b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int auxCount = 0;
1475b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype nonAuxSubtype = null;
1476b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype auxSubtype = null;
14777cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            for(int i = 0; i < N; ++i) {
14787cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final InputMethodInfo imi = imis.get(i);
14798e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final List<InputMethodSubtype> subtypes =
14808e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
14817cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final int subtypeCount = subtypes.size();
14827cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                if (subtypeCount == 0) {
1483b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    ++nonAuxCount;
14847cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
14857cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    for (int j = 0; j < subtypeCount; ++j) {
1486b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        final InputMethodSubtype subtype = subtypes.get(j);
1487b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        if (!subtype.isAuxiliary()) {
1488b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++nonAuxCount;
1489b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            nonAuxSubtype = subtype;
1490b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        } else {
1491b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++auxCount;
1492b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            auxSubtype = subtype;
14937cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        }
14947cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
14957cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
14967cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            }
1497b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (nonAuxCount > 1 || auxCount > 1) {
1498b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1499b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            } else if (nonAuxCount == 1 && auxCount == 1) {
1500b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                if (nonAuxSubtype != null && auxSubtype != null
15019747f8977c55013e656a1e666a1647bb331954cesatok                        && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
15029747f8977c55013e656a1e666a1647bb331954cesatok                                || auxSubtype.overridesImplicitlyEnabledSubtype()
15039747f8977c55013e656a1e666a1647bb331954cesatok                                || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
1504b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
1505b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    return false;
1506b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                }
1507b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1508b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            }
1509b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            return false;
15107cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        }
15117cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    }
15127cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
1513e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean isKeyguardLocked() {
1514e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
1515e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    }
1516e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
15174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Caution! This method is called in this class. Handle multi-user carefully
1518dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("deprecation")
1519f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
1520857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
15214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final long ident = Binder.clearCallingIdentity();
152206487a58be22b100daf3f950b9a1d25c3ea42aa2satok        try {
152306487a58be22b100daf3f950b9a1d25c3ea42aa2satok            if (token == null || mCurToken != token) {
15244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                int uid = Binder.getCallingUid();
1525857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                Slog.w(TAG, "Ignoring setImeWindowStatus of uid " + uid + " token: " + token);
152606487a58be22b100daf3f950b9a1d25c3ea42aa2satok                return;
152706487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
152806487a58be22b100daf3f950b9a1d25c3ea42aa2satok            synchronized (mMethodMap) {
1529e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                // apply policy for binder calls
1530e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
1531e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    vis = 0;
1532e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                }
1533857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mImeWindowVis = vis;
1534857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mBackDisposition = backDisposition;
1535661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                if (mStatusBar != null) {
1536661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    mStatusBar.setImeWindowStatus(token, vis, backDisposition);
1537661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                }
1538217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                final boolean iconVisibility = ((vis & (InputMethodService.IME_ACTIVE)) != 0)
1539217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                        && (mWindowManagerService.isHardKeyboardAvailable()
1540217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                                || (vis & (InputMethodService.IME_VISIBLE)) != 0);
15415bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
15425bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) {
15434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // Used to load label
15447cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    final CharSequence title = mRes.getText(
15457cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                            com.android.internal.R.string.select_input_method);
1546b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                    final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
1547b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            mContext, imi, mCurrentSubtype);
15485bc8e732bd831a308a5bc1720b0e4c9300d32f67satok
15497cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    mImeSwitcherNotification.setLatestEventInfo(
15505bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                            mContext, title, summary, mImeSwitchPendingIntent);
1551e463c745ef6901121837e88ca8597d062843b9ddJason Monk                    if ((mNotificationManager != null)
1552e463c745ef6901121837e88ca8597d062843b9ddJason Monk                            && !mWindowManagerService.hasNavigationBar()) {
1553135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1554b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            Slog.d(TAG, "--- show notification: label =  " + summary);
1555135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1556135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.notifyAsUser(null,
1557661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                com.android.internal.R.string.select_input_method,
1558135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                mImeSwitcherNotification, UserHandle.ALL);
1559661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mNotificationShown = true;
1560661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
15617cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
1562661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mNotificationShown && mNotificationManager != null) {
1563135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1564135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                            Slog.d(TAG, "--- hide notification");
1565135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1566135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.cancelAsUser(null,
1567135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                com.android.internal.R.string.select_input_method, UserHandle.ALL);
15687cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        mNotificationShown = false;
15697cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
15707cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
157106487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
157206487a58be22b100daf3f950b9a1d25c3ea42aa2satok        } finally {
157306487a58be22b100daf3f950b9a1d25c3ea42aa2satok            Binder.restoreCallingIdentity(ident);
157406487a58be22b100daf3f950b9a1d25c3ea42aa2satok        }
157506487a58be22b100daf3f950b9a1d25c3ea42aa2satok    }
157606487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1577e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1578f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
15794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
15804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
15814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1582f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1583f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
1584f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            for (int i = 0; i < spans.length; ++i) {
1585f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                SuggestionSpan ss = spans[i];
158642c5a1666c4e576ccd5974233513100aad2c1534satok                if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
1587f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                    mSecureSuggestionSpans.put(ss, currentImi);
1588f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                }
1589f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1590f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1591f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1592f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1593e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1594f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
15954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
15964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
15974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1598f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1599f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
1600f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            // TODO: Do not send the intent if the process of the targetImi is already dead.
1601f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            if (targetImi != null) {
1602f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final String[] suggestions = span.getSuggestions();
1603f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                if (index < 0 || index >= suggestions.length) return false;
160442c5a1666c4e576ccd5974233513100aad2c1534satok                final String className = span.getNotificationTargetClassName();
1605f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final Intent intent = new Intent();
1606f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // Ensures that only a class in the original IME package will receive the
1607f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // notification.
160842c5a1666c4e576ccd5974233513100aad2c1534satok                intent.setClassName(targetImi.getPackageName(), className);
1609f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
1610f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
1611f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
1612f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
1613f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                final long ident = Binder.clearCallingIdentity();
1614f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                try {
1615f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
1616f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                } finally {
1617f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    Binder.restoreCallingIdentity(ident);
1618f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                }
1619f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                return true;
1620f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1621f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1622f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        return false;
1623f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1624f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1625fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn    void updateFromSettingsLocked(boolean enabledMayChange) {
1626fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        if (enabledMayChange) {
1627fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
1628fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            for (int i=0; i<enabled.size(); i++) {
1629fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // We allow the user to select "disabled until used" apps, so if they
1630fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // are enabling one of those here we now need to make it enabled.
1631fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                InputMethodInfo imm = enabled.get(i);
1632fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                try {
1633fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
1634fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
1635fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            mSettings.getCurrentUserId());
16367987a3172b0502ea70a26d80e7cd16ca7e460035Satoshi Kataoka                    if (ai != null && ai.enabledSetting
1637fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
1638ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        if (DEBUG) {
1639ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            Slog.d(TAG, "Update state(" + imm.getId()
1640ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                                    + "): DISABLED_UNTIL_USED -> DEFAULT");
1641ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        }
1642fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
1643fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
16443fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(),
16453fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                mContext.getBasePackageName());
1646fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    }
1647fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                } catch (RemoteException e) {
1648fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
1649fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            }
1650fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        }
1651b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
1652b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
1653b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
1654b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // enabled.
16554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String id = mSettings.getSelectedInputMethod();
165603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        // There is no input method selected, try to choose new applicable input method.
165703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
16584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            id = mSettings.getSelectedInputMethod();
165903eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        }
166003eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (!TextUtils.isEmpty(id)) {
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
16628e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
16639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException e) {
16648a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unknown input method from prefs: " + id, e);
1665105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mCurMethodId = null;
16662ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1668f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.clear();
1669b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        } else {
1670b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            // There is no longer an input method set, so stop any current one.
1671105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCurMethodId = null;
16722ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn            unbindCurrentMethodLocked(true, false);
16739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1675ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1676ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /* package */ void setInputMethodLocked(String id, int subtypeId) {
16779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(id);
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
1679913a8925c07e854a80bf5df87561f290d3a56d61satok            throw new IllegalArgumentException("Unknown id: " + id);
16809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1681ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1682d81e950265356c81276b73da68a535ffa48d72f0satok        // See if we need to notify a subtype change within the same IME.
16839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.equals(mCurMethodId)) {
1684d81e950265356c81276b73da68a535ffa48d72f0satok            final int subtypeCount = info.getSubtypeCount();
1685d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeCount <= 0) {
1686d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1687d81e950265356c81276b73da68a535ffa48d72f0satok            }
1688d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype oldSubtype = mCurrentSubtype;
1689d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype newSubtype;
1690d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeId >= 0 && subtypeId < subtypeCount) {
1691d81e950265356c81276b73da68a535ffa48d72f0satok                newSubtype = info.getSubtypeAt(subtypeId);
1692d81e950265356c81276b73da68a535ffa48d72f0satok            } else {
1693d81e950265356c81276b73da68a535ffa48d72f0satok                // If subtype is null, try to find the most applicable one from
1694d81e950265356c81276b73da68a535ffa48d72f0satok                // getCurrentInputMethodSubtype.
16954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                newSubtype = getCurrentInputMethodSubtypeLocked();
1696d81e950265356c81276b73da68a535ffa48d72f0satok            }
1697d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype == null || oldSubtype == null) {
1698d81e950265356c81276b73da68a535ffa48d72f0satok                Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
1699d81e950265356c81276b73da68a535ffa48d72f0satok                        + ", new subtype = " + newSubtype);
1700d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1701d81e950265356c81276b73da68a535ffa48d72f0satok            }
1702d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype != oldSubtype) {
1703d81e950265356c81276b73da68a535ffa48d72f0satok                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
1704d81e950265356c81276b73da68a535ffa48d72f0satok                if (mCurMethod != null) {
1705d81e950265356c81276b73da68a535ffa48d72f0satok                    try {
1706d81e950265356c81276b73da68a535ffa48d72f0satok                        refreshImeWindowVisibilityLocked();
1707d81e950265356c81276b73da68a535ffa48d72f0satok                        mCurMethod.changeInputMethodSubtype(newSubtype);
1708d81e950265356c81276b73da68a535ffa48d72f0satok                    } catch (RemoteException e) {
1709d81e950265356c81276b73da68a535ffa48d72f0satok                        Slog.w(TAG, "Failed to call changeInputMethodSubtype");
1710ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
1711ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                }
1712ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            }
17139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
17149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1715ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1716d81e950265356c81276b73da68a535ffa48d72f0satok        // Changing to a different IME.
17179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long ident = Binder.clearCallingIdentity();
17189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1719ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // Set a subtype to this input method.
1720ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // subtypeId the name of a subtype which will be set.
1721723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
1722723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
1723723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // because mCurMethodId is stored as a history in
1724723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // setSelectedInputMethodAndSubtypeLocked().
1725723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mCurMethodId = id;
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ActivityManagerNative.isSystemReady()) {
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
17291c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.putExtra("input_method_id", id);
1731cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani                mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1733b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
17369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1738ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
173942c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
17404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean showSoftInput(IInputMethodClient client, int flags,
17414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
17424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
17434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
17444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1745cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
17549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
17559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1756cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
17574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
17589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
17604df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
17619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
17629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1763ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1764e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
17654df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return showCurrentInputLocked(flags, resultReceiver);
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
17699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1771ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
17724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = true;
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
17799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowForced = true;
17809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1781ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1782cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        if (!mSystemReady) {
1783cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            return false;
1784cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        }
1785ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
17864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res = false;
17879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
1788e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
17894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
17904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
17914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    resultReceiver));
17929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputShown = true;
17932c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            if (mHaveConnection && !mVisibleBound) {
17944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                bindCurrentInputMethodService(
1795f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                        mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
1796f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                                | Context.BIND_TREAT_LIKE_ACTIVITY);
17972c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                mVisibleBound = true;
17982c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            }
17994df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mHaveConnection && SystemClock.uptimeMillis()
180159b424c3b6121c9579fc5efcc785ba084072a5casatok                >= (mLastBindTime+TIME_TO_RECONNECT)) {
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The client has asked to have the input method shown, but
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we have been sitting here too long with a connection to the
18049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // service and no interface received, so let's disconnect/connect
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to try to prod things along.
1806ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemClock.uptimeMillis()-mLastBindTime,1);
180859b424c3b6121c9579fc5efcc785ba084072a5casatok            Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
18099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.unbindService(this);
18104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
18112c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                    | Context.BIND_NOT_VISIBLE);
18124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } else {
18134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
18144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
18154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
18164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
18179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1818ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
18209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1821ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
182242c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
18234df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean hideSoftInput(IInputMethodClient client, int flags,
18244df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
18254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
18264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
18274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1828cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
18379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
18389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1839cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
1840cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                                    + uid + ": " + client);
184115452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
18424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
18439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
18449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
184515452a487a4c0274f4217cd060aa54446f30a8f3satok                        setImeWindowVisibilityStatusHiddenLocked();
18464df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
18479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
18489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1849ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18508a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
18514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return hideCurrentInputLocked(flags, resultReceiver);
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
18559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1857ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
18599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
18609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mShowExplicitlyRequested || mShowForced)) {
1861e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
18624df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
18639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
1865e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
18664df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res;
18699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputShown && mCurMethod != null) {
18704df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
18714df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
18724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
18734df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
18744df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = false;
18759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18762c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mHaveConnection && mVisibleBound) {
18772c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
18782c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
18792c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputShown = false;
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = false;
18829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowExplicitlyRequested = false;
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowForced = false;
18844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
18859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1886ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
188742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
18887663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
18897663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            int controlFlags, int softInputMode, int windowFlags,
18907663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            EditorInfo attribute, IInputContext inputContext) {
18918d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        // Needs to check the validity before clearing calling identity
18928d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        final boolean calledFromValidUser = calledFromValidUser();
18938d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
18947663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        InputBindResult res = null;
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
18988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
18997663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " controlFlags=#" + Integer.toHexString(controlFlags)
19009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " softInputMode=#" + Integer.toHexString(softInputMode)
19017663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " windowFlags=#" + Integer.toHexString(windowFlags));
1902ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19037663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                ClientState cs = mClients.get(client.asBinder());
19047663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (cs == null) {
19057663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    throw new IllegalArgumentException("unknown client "
19067663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            + client.asBinder());
19077663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
19087663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
19097663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                try {
19107663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
19117663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // Check with the window manager to make sure this client actually
19127663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // has a window with focus.  If not, reject.  This is thread safe
19137663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // because if the focus changes some time before or after, the
19147663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // next client receiving focus that has any interest in input will
19157663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // be calling through here after that change happens.
19167663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        Slog.w(TAG, "Focus gain on non-focused client " + cs.client
19177663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
19187663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return null;
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
19207663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                } catch (RemoteException e) {
19219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1922ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19238d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                if (!calledFromValidUser) {
19248d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "A background user is requesting window. Hiding IME.");
19258d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "If you want to interect with IME, you need "
19268d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                            + "android.permission.INTERACT_ACROSS_USERS_FULL");
19278d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    hideCurrentInputLocked(0, null);
19288d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    return null;
19298d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                }
19308d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
1931b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                if (mCurFocusedWindow == windowToken) {
1932ac92087a9a1c464d4b0a58c82dae01cbaa088e89Dianne Hackborn                    Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
19333573950e0b30178dc963de3fa00aba2ebcfd552dSatoshi Kataoka                            + " attribute=" + attribute + ", token = " + windowToken);
19347663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (attribute != null) {
19357663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return startInputUncheckedLocked(cs, inputContext, attribute,
19367663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                controlFlags);
19377663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    }
19387663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    return null;
1939b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
1940b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mCurFocusedWindow = windowToken;
1941ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19427d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // Should we auto-show the IME even if the caller has not
19437d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // specified what should be done with it?
19447d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // We only do this automatically if the window can resize
19457d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // to accommodate the IME (so what the user sees will give
19467d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // them good context without input information being obscured
19477d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // by the IME) or if running on a large screen where there
19487d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // is more room for the target window + IME.
19497d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                final boolean doAutoShow =
19507d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
19517d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
19527d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        || mRes.getConfiguration().isLayoutSizeAtLeast(
19537d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                Configuration.SCREENLAYOUT_SIZE_LARGE);
19547663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                final boolean isTextEditor =
19557663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0;
19567663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
19577663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // We want to start input before showing the IME, but after closing
19587663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // it.  We want to do this after closing it to help the IME disappear
19597663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // more quickly (not get stuck behind it initializing itself for the
19607663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // new focused input, even if its window wants to hide the IME).
19617663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                boolean didStart = false;
19627d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn
19639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
19657d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        if (!isTextEditor || !doAutoShow) {
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // There is no focus view, and this window will
19689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // be behind any soft input window, so hide the
19699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // soft input window if it is shown.
19708a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
19714df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
19729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
19737d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        } else if (isTextEditor && doAutoShow && (softInputMode &
19747d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // There is a focus view, and we are navigating forward
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // into the window, so show the input window for the user.
19777663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // We only do this automatically if the window can resize
19787663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // to accommodate the IME (so what the user sees will give
19797d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // them good context without input information being obscured
19807d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // by the IME) or if running on a large screen where there
19817d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // is more room for the target window + IME.
19828a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
19837663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
19847663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
19857663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
19867663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
19877663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
19884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Do nothing.
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
19978a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
19984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            hideCurrentInputLocked(0, null);
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
20028a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to hide input");
20034df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        hideCurrentInputLocked(0, null);
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20088a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
20097663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
20107663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
20117663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
20127663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
20137663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
20144df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
20188a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to always show input");
20197663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        if (attribute != null) {
20207663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            res = startInputUncheckedLocked(cs, inputContext, attribute,
20217663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                    controlFlags);
20227663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            didStart = true;
20237663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        }
20244df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20277663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20287663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (!didStart && attribute != null) {
20297663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    res = startInputUncheckedLocked(cs, inputContext, attribute,
20307663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            controlFlags);
20317663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20367663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20377663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return res;
20389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2039ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
204042c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showInputMethodPickerFromClient(IInputMethodClient client) {
20424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurClient == null || client == null
20479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || mCurClient.client.asBinder() != client.asBinder()) {
204847a44916e2fb33cf4751906386d5f5c903b28d8bsatok                Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
2049cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + ": " + client);
20509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2052440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // Always call subtype picker, because subtype picker is a superset of input method
2053440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // picker.
2054ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER);
2055ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2056ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2057ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
205842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethod(IBinder token, String id) {
20604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20632820351489537698ad153c6397edf3270455edc5satok        setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
20642820351489537698ad153c6397edf3270455edc5satok    }
20652820351489537698ad153c6397edf3270455edc5satok
206642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20672820351489537698ad153c6397edf3270455edc5satok    public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
20684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20712820351489537698ad153c6397edf3270455edc5satok        synchronized (mMethodMap) {
20722820351489537698ad153c6397edf3270455edc5satok            if (subtype != null) {
20738e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodWithSubtypeId(token, id, InputMethodUtils.getSubtypeIdFromHashCode(
20742820351489537698ad153c6397edf3270455edc5satok                        mMethodMap.get(id), subtype.hashCode()));
20752820351489537698ad153c6397edf3270455edc5satok            } else {
20762820351489537698ad153c6397edf3270455edc5satok                setInputMethod(token, id);
20772820351489537698ad153c6397edf3270455edc5satok            }
20782820351489537698ad153c6397edf3270455edc5satok        }
2079ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2080ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
208142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
2082b416a71e56cdd50742eb897366a140775aa4cd61satok    public void showInputMethodAndSubtypeEnablerFromClient(
2083217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            IInputMethodClient client, String inputMethodId) {
20844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2087b416a71e56cdd50742eb897366a140775aa4cd61satok        synchronized (mMethodMap) {
2088b416a71e56cdd50742eb897366a140775aa4cd61satok            if (mCurClient == null || client == null
2089b416a71e56cdd50742eb897366a140775aa4cd61satok                || mCurClient.client.asBinder() != client.asBinder()) {
2090b416a71e56cdd50742eb897366a140775aa4cd61satok                Slog.w(TAG, "Ignoring showInputMethodAndSubtypeEnablerFromClient of: " + client);
2091b416a71e56cdd50742eb897366a140775aa4cd61satok            }
20927fee71f66afef6421b92fa48e63d4bc73f5d0c27satok            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
20937fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                    MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
2094b416a71e56cdd50742eb897366a140775aa4cd61satok        }
2095b416a71e56cdd50742eb897366a140775aa4cd61satok    }
2096b416a71e56cdd50742eb897366a140775aa4cd61satok
20974fc87d61c29886c848789208c9e32ba9ac4e5dd3satok    @Override
2098735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    public boolean switchToLastInputMethod(IBinder token) {
20994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
21014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2102735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        synchronized (mMethodMap) {
2103c445bcd0bce630948ee029d7c70b28226f0b6c9csatok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
21044fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            final InputMethodInfo lastImi;
2105208d5634047111811de16fb63c43d0bc8b4fe6desatok            if (lastIme != null) {
21064fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = mMethodMap.get(lastIme.first);
21074fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
21084fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = null;
21094fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
21104fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            String targetLastImiId = null;
21114fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            int subtypeId = NOT_A_SUBTYPE_ID;
21124fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (lastIme != null && lastImi != null) {
21134fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
21144fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
21154fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
21164fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        : mCurrentSubtype.hashCode();
21174fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // If the last IME is the same as the current IME and the last subtype is not
21184fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // defined, there is no need to switch to the last IME.
21194fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
21204fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    targetLastImiId = lastIme.first;
21218e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
21224fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
21234fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
21244fc87d61c29886c848789208c9e32ba9ac4e5dd3satok
21258e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            if (TextUtils.isEmpty(targetLastImiId)
21268e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    && !InputMethodUtils.canAddToLastInputMethod(mCurrentSubtype)) {
21274fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // This is a safety net. If the currentSubtype can't be added to the history
21284fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // and the framework couldn't find the last ime, we will make the last ime be
21294fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // the most applicable enabled keyboard subtype of the system imes.
21304fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
21314fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (enabled != null) {
21324fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final int N = enabled.size();
21334fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final String locale = mCurrentSubtype == null
21344fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            ? mRes.getConfiguration().locale.toString()
21354fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            : mCurrentSubtype.getLocale();
21364fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    for (int i = 0; i < N; ++i) {
21374fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        final InputMethodInfo imi = enabled.get(i);
21388e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        if (imi.getSubtypeCount() > 0 && InputMethodUtils.isSystemIme(imi)) {
21394fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            InputMethodSubtype keyboardSubtype =
21408e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                    InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes,
21418e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.getSubtypes(imi),
21428e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, locale, true);
21434fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            if (keyboardSubtype != null) {
21444fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                targetLastImiId = imi.getId();
21458e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
21464fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                        imi, keyboardSubtype.hashCode());
21474fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                if(keyboardSubtype.getLocale().equals(locale)) {
21484fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                    break;
21494fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                }
21504fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            }
21514fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        }
21524fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    }
21534fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
21544fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
2155c445bcd0bce630948ee029d7c70b28226f0b6c9csatok
21564fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (!TextUtils.isEmpty(targetLastImiId)) {
2157c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                if (DEBUG) {
21584fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
21594fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            + ", from: " + mCurMethodId + ", " + subtypeId);
2160735cf38b8c7f8f91ad087511e44fe79018fa61d6satok                }
21614fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                setInputMethodWithSubtypeId(token, targetLastImiId, subtypeId);
2162c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                return true;
21634fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
21644fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                return false;
2165735cf38b8c7f8f91ad087511e44fe79018fa61d6satok            }
2166735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        }
2167735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    }
2168735cf38b8c7f8f91ad087511e44fe79018fa61d6satok
2169e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2170688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
21714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
21734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2174688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        synchronized (mMethodMap) {
2175d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethod(
2176688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                    onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
2177688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            if (nextSubtype == null) {
2178688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                return false;
2179688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            }
2180688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            setInputMethodWithSubtypeId(token, nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
2181688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            return true;
2182688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        }
2183688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    }
2184688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok
2185688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    @Override
21862b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    public boolean shouldOfferSwitchingToNextInputMethod(IBinder token) {
21872b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        if (!calledFromValidUser()) {
21882b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return false;
21892b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
21902b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        synchronized (mMethodMap) {
2191d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethod(
21922b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                    false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
21932b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            if (nextSubtype == null) {
21942b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                return false;
21952b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            }
21962b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return true;
21972b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
21982b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    }
21992b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka
22002b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    @Override
220168f1b78b7b9139a0e34285ff641a664e664a14b8satok    public InputMethodSubtype getLastInputMethodSubtype() {
22024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
22044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
220568f1b78b7b9139a0e34285ff641a664e664a14b8satok        synchronized (mMethodMap) {
220668f1b78b7b9139a0e34285ff641a664e664a14b8satok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
220768f1b78b7b9139a0e34285ff641a664e664a14b8satok            // TODO: Handle the case of the last IME with no subtypes
220868f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastIme == null || TextUtils.isEmpty(lastIme.first)
220968f1b78b7b9139a0e34285ff641a664e664a14b8satok                    || TextUtils.isEmpty(lastIme.second)) return null;
221068f1b78b7b9139a0e34285ff641a664e664a14b8satok            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
221168f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastImi == null) return null;
221268f1b78b7b9139a0e34285ff641a664e664a14b8satok            try {
221368f1b78b7b9139a0e34285ff641a664e664a14b8satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
22148e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final int lastSubtypeId =
22158e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
22160e7d7d632309409e2bc51d5317cf7a92a7541433satok                if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
22170e7d7d632309409e2bc51d5317cf7a92a7541433satok                    return null;
22180e7d7d632309409e2bc51d5317cf7a92a7541433satok                }
22190e7d7d632309409e2bc51d5317cf7a92a7541433satok                return lastImi.getSubtypeAt(lastSubtypeId);
222068f1b78b7b9139a0e34285ff641a664e664a14b8satok            } catch (NumberFormatException e) {
222168f1b78b7b9139a0e34285ff641a664e664a14b8satok                return null;
222268f1b78b7b9139a0e34285ff641a664e664a14b8satok            }
222368f1b78b7b9139a0e34285ff641a664e664a14b8satok        }
222468f1b78b7b9139a0e34285ff641a664e664a14b8satok    }
222568f1b78b7b9139a0e34285ff641a664e664a14b8satok
2226e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2227ee5e77cafec2eae70890abdcc1646ed39b06edddsatok    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
22284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
22304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
223191e88122cf28a48fd2e2260da7d3d87dd437227asatok        // By this IPC call, only a process which shares the same uid with the IME can add
223291e88122cf28a48fd2e2260da7d3d87dd437227asatok        // additional input method subtypes to the IME.
2233ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
2234e7c6998e0a953ae55487d4fe122739646f9280aasatok        synchronized (mMethodMap) {
223591e88122cf28a48fd2e2260da7d3d87dd437227asatok            final InputMethodInfo imi = mMethodMap.get(imiId);
2236ee5e77cafec2eae70890abdcc1646ed39b06edddsatok            if (imi == null) return;
22374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String[] packageInfos;
22384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            try {
22394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
22404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } catch (RemoteException e) {
22414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.e(TAG, "Failed to get package infos");
22424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
22434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
224491e88122cf28a48fd2e2260da7d3d87dd437227asatok            if (packageInfos != null) {
224591e88122cf28a48fd2e2260da7d3d87dd437227asatok                final int packageNum = packageInfos.length;
224691e88122cf28a48fd2e2260da7d3d87dd437227asatok                for (int i = 0; i < packageNum; ++i) {
224791e88122cf28a48fd2e2260da7d3d87dd437227asatok                    if (packageInfos[i].equals(imi.getPackageName())) {
224891e88122cf28a48fd2e2260da7d3d87dd437227asatok                        mFileManager.addInputMethodSubtypes(imi, subtypes);
2249c593380d1bccbfbd45c404954b2670b65acc287fsatok                        final long ident = Binder.clearCallingIdentity();
2250c593380d1bccbfbd45c404954b2670b65acc287fsatok                        try {
2251f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                            buildInputMethodListLocked(mMethodList, mMethodMap,
2252f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                                    false /* resetDefaultEnabledIme */);
2253c593380d1bccbfbd45c404954b2670b65acc287fsatok                        } finally {
2254c593380d1bccbfbd45c404954b2670b65acc287fsatok                            Binder.restoreCallingIdentity(ident);
2255c593380d1bccbfbd45c404954b2670b65acc287fsatok                        }
2256ee5e77cafec2eae70890abdcc1646ed39b06edddsatok                        return;
225791e88122cf28a48fd2e2260da7d3d87dd437227asatok                    }
225891e88122cf28a48fd2e2260da7d3d87dd437227asatok                }
225991e88122cf28a48fd2e2260da7d3d87dd437227asatok            }
2260e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
2261ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        return;
2262e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
2263e7c6998e0a953ae55487d4fe122739646f9280aasatok
2264658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    @Override
2265658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    public int getInputMethodWindowVisibleHeight() {
2266658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka        return mWindowManagerService.getInputMethodWindowVisibleHeight();
2267658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    }
2268658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka
2269d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    @Override
2270d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    public void notifyTextCommitted() {
2271d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (DEBUG) {
2272d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka            Slog.d(TAG, "Got the notification of commitText");
2273d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2274d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
2275d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (imi != null) {
2276d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka            mSwitchingController.onCommitText(imi, mCurrentSubtype);
2277d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2278d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    }
2279d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
2280b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    @Override
2281b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    public void setCursorAnchorMonitorMode(IBinder token, int monitorMode) {
2282b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        if (DEBUG) {
2283b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            Slog.d(TAG, "setCursorAnchorMonitorMode: monitorMode=" + monitorMode);
2284b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        }
2285b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        if (!calledFromValidUser()) {
2286b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            return;
2287b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        }
2288b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        synchronized (mMethodMap) {
2289b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            if (token == null || mCurToken != token) {
2290b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                if (DEBUG) {
2291b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                    Slog.w(TAG, "Ignoring setCursorAnchorMonitorMode from uid "
2292b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                            + Binder.getCallingUid() + " token: " + token);
2293b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                }
2294b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                return;
2295b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            }
2296b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIO(
2297b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                    MSG_SET_CURSOR_ANCHOR_MONITOR_MODE, monitorMode, mCurClient));
2298b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa        }
2299b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa    }
2300b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa
23012820351489537698ad153c6397edf3270455edc5satok    private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
23029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
23039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (token == null) {
23049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mContext.checkCallingOrSelfPermission(
23059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        android.Manifest.permission.WRITE_SECURE_SETTINGS)
23069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        != PackageManager.PERMISSION_GRANTED) {
23079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new SecurityException(
23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "Using null token requires permission "
23099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + android.Manifest.permission.WRITE_SECURE_SETTINGS);
23109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mCurToken != token) {
2312cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
2313cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + " token: " + token);
23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
23159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2317c593380d1bccbfbd45c404954b2670b65acc287fsatok            final long ident = Binder.clearCallingIdentity();
23189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2319ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                setInputMethodLocked(id, subtypeId);
23209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
23219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
23229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
232642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideMySoftInput(IBinder token, int flags) {
23284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (token == null || mCurToken != token) {
2333cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                if (DEBUG) Slog.w(TAG, "Ignoring hideInputMethod of uid "
2334cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + " token: " + token);
23359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
23369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
23389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
23394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                hideCurrentInputLocked(flags, null);
23404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } finally {
23414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                Binder.restoreCallingIdentity(ident);
23424df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
23434df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
23444df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
2345ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
234642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23474df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void showMySoftInput(IBinder token, int flags) {
23484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        synchronized (mMethodMap) {
23524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (token == null || mCurToken != token) {
2353cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                Slog.w(TAG, "Ignoring showMySoftInput of uid "
2354cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + " token: " + token);
23554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return;
23564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
23574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            long ident = Binder.clearCallingIdentity();
23584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            try {
23594df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                showCurrentInputLocked(flags, null);
23609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
23619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
23629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setEnabledSessionInMainThread(SessionState session) {
23679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledSession != session) {
23689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledSession != null) {
23699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
23708a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
23719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEnabledSession.method.setSessionEnabled(
23729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mEnabledSession.session, false);
23739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
23749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledSession = session;
23779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
23788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
23799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                session.method.setSessionEnabled(
23809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        session.session, true);
23819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
23829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2385ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
238642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean handleMessage(Message msg) {
2388758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov        SomeArgs args;
23899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (msg.what) {
23909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_IM_PICKER:
23919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showInputMethodMenu();
23929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2393ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2394ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            case MSG_SHOW_IM_SUBTYPE_PICKER:
2395ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                showInputMethodSubtypeMenu();
2396ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                return true;
2397ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
239847a44916e2fb33cf4751906386d5f5c903b28d8bsatok            case MSG_SHOW_IM_SUBTYPE_ENABLER:
2399758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24007fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                showInputMethodAndSubtypeEnabler((String)args.arg1);
2401758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
2402217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                return true;
2403217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2404217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            case MSG_SHOW_IM_CONFIG:
2405217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                showConfigureInputMethods();
240647a44916e2fb33cf4751906386d5f5c903b28d8bsatok                return true;
240747a44916e2fb33cf4751906386d5f5c903b28d8bsatok
24089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2409ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_INPUT:
24119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)msg.obj).unbindInput();
24139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the method dying.
24159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
24169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_BIND_INPUT:
2418758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);
24219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2423758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_SOFT_INPUT:
2426758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2428e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
24296efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + msg.arg1 + ", " + args.arg2 + ")");
2430ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
24319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2433758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_HIDE_SOFT_INPUT:
2436758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2438e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
24396efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + args.arg2 + ")");
2440ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
24419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2443758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_ATTACH_TOKEN:
2446758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2448e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
24499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
24509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2452758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2454c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            case MSG_CREATE_SESSION: {
2455758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24561951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethod method = (IInputMethod)args.arg1;
2457c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel = (InputChannel)args.arg2;
24589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24591951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    method.createSession(channel, (IInputSessionCallback)args.arg3);
24609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2461c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } finally {
24621951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
24631951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
24641951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (channel != null && Binder.isProxy(method)) {
2465c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        channel.dispose();
2466c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    }
24679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2468758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2470c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
24719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2472ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_START_INPUT:
2474758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
24779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
24789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.startInput((IInputContext)args.arg2,
24799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
24809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2482758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_RESTART_INPUT:
2485758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
24889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
24899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.restartInput((IInputContext)args.arg2,
24909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
24919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2493758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2495ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2497ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_METHOD:
24999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1);
25019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the last client dying.
25039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
25049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25051951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            case MSG_BIND_METHOD: {
2506758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
25071951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethodClient client = (IInputMethodClient)args.arg1;
25081951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                InputBindResult res = (InputBindResult)args.arg2;
25099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
25101951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    client.onBindMethod(res);
25119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
25128a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Client died receiving input method " + args.arg2);
25131951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                } finally {
25141951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
25151951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
25161951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (res.channel != null && Binder.isProxy(client)) {
25171951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                        res.channel.dispose();
25181951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    }
25199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2520758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
25219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
25221951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            }
2523a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            case MSG_SET_ACTIVE:
2524a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                try {
2525a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    ((ClientState)msg.obj).client.setActive(msg.arg1 != 0);
2526a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                } catch (RemoteException e) {
2527a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    Slog.w(TAG, "Got RemoteException sending setActive(false) notification to pid "
2528a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).pid + " uid "
2529a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).uid);
2530a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                }
2531a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                return true;
2532b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa            case MSG_SET_CURSOR_ANCHOR_MONITOR_MODE:
2533b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                try {
2534b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                    ((ClientState)msg.obj).client.setCursorAnchorMonitorMode(msg.arg1);
2535b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                } catch (RemoteException e) {
2536b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                    Slog.w(TAG, "Got RemoteException sending setCursorAnchorMonitorMode "
2537b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                            + "notification to pid " + ((ClientState)msg.obj).pid
2538b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                            + " uid " + ((ClientState)msg.obj).uid);
2539b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                }
2540b7b7907fb5e4b2252b3c594a6bc4402217fe662aYohei Yukawa                return true;
254101038492ff0317f0d3cff54d8a7ee36bb31ff175satok
254201038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // --------------------------------------------------------------
254301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
254401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                mHardKeyboardListener.handleHardKeyboardStatusChange(
254501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        msg.arg1 == 1, msg.arg2 == 1);
254601038492ff0317f0d3cff54d8a7ee36bb31ff175satok                return true;
25479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
25499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2551dc9ddaee9a710cf6f5d7f37350650f82e706c706satok    private boolean chooseNewDefaultIMELocked() {
25528e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
25538e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mSettings.getEnabledInputMethodListLocked());
2554dc9ddaee9a710cf6f5d7f37350650f82e706c706satok        if (imi != null) {
255503eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            if (DEBUG) {
255603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                Slog.d(TAG, "New default IME was selected: " + imi.getId());
255703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            }
2558723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            resetSelectedInputMethodAndSubtypeLocked(imi.getId());
25596da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            return true;
25606da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
25616da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
25626da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        return false;
25636da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger    }
25646da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
25659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
2566f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) {
25674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
2568f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
25690766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                    + " \n ------ \n" + InputMethodUtils.getStackTrace());
25704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
25719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        list.clear();
25729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map.clear();
2573ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // Use for queryIntentServicesAsUser
25754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final PackageManager pm = mContext.getPackageManager();
25764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
2577e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani        if (disabledSysImes == null) disabledSysImes = "";
25789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new Intent(InputMethod.SERVICE_INTERFACE),
2581fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
2582fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                mSettings.getCurrentUserId());
2583ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2584e7c6998e0a953ae55487d4fe122739646f9280aasatok        final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
2585e7c6998e0a953ae55487d4fe122739646f9280aasatok                mFileManager.getAllAdditionalInputMethodSubtypes();
25869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < services.size(); ++i) {
25879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = services.get(i);
25889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ServiceInfo si = ri.serviceInfo;
25899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ComponentName compName = new ComponentName(si.packageName, si.name);
25909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(
25919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    si.permission)) {
25928a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Skipping input method " + compName
25939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": it does not require the permission "
25949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.BIND_INPUT_METHOD);
25959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
25969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.d(TAG, "Checking " + compName);
25999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2601e7c6998e0a953ae55487d4fe122739646f9280aasatok                InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes);
26029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list.add(p);
2603e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                final String id = p.getId();
2604e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                map.put(id, p);
26059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
2607f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "Found an input method " + p);
26089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2609ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
26118a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
26129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
26138a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
26149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26166da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
2617f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (resetDefaultEnabledIme) {
2618f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            final ArrayList<InputMethodInfo> defaultEnabledIme =
2619f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list);
2620f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            for (int i = 0; i < defaultEnabledIme.size(); ++i) {
2621f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                final InputMethodInfo imi =  defaultEnabledIme.get(i);
2622f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                if (DEBUG) {
2623f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "--- enable ime = " + imi);
2624f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                }
2625f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                setInputMethodEnabledLocked(imi.getId(), true);
2626f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            }
2627f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
2628f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
26294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
26300a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!TextUtils.isEmpty(defaultImiId)) {
26310a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            if (!map.containsKey(defaultImiId)) {
26320a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
26330a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (chooseNewDefaultIMELocked()) {
2634fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(true);
26350a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
26360a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            } else {
26370a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                // Double check that the default IME is certainly enabled.
26380a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                setInputMethodEnabledLocked(defaultImiId, true);
26396da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            }
26406da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
26419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2642ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2644ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2645ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenu() {
2646ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(false);
2647ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2648ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2649ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodSubtypeMenu() {
2650ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(true);
2651ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2652ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2653217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
2654f49688fa17b70313c0734f00df73bc3308a749e9Tadashi G. Takaoka        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
265547a44916e2fb33cf4751906386d5f5c903b28d8bsatok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
265686417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
265786417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
26587fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        if (!TextUtils.isEmpty(inputMethodId)) {
26592548020c364c4119d134c84cc7a00ffca2dcbe7bTadashi G. Takaoka            intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId);
26607fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        }
26613ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
2662217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    }
2663217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2664217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showConfigureInputMethods() {
2665217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
2666217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2667217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
2668217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
26693ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
267047a44916e2fb33cf4751906386d5f5c903b28d8bsatok    }
267147a44916e2fb33cf4751906386d5f5c903b28d8bsatok
26722c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    private boolean isScreenLocked() {
26732c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        return mKeyguardManager != null
26742c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
26752c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    }
2676ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenuInternal(boolean showSubtypes) {
26778a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Show switching menu");
26789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Context context = mContext;
26802c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        final boolean isScreenLocked = isScreenLocked();
2681ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String lastInputMethodId = mSettings.getSelectedInputMethod();
26838e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
26848a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
2685ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26867f35c8cc88bea5230f001dd4356f864845d202e5satok        synchronized (mMethodMap) {
2687bb4aa0683c8a0a1e617c6d5f03eda33f49b89ed9satok            final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
2688d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(
2689d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                            mContext);
26907f35c8cc88bea5230f001dd4356f864845d202e5satok            if (immis == null || immis.size() == 0) {
26917f35c8cc88bea5230f001dd4356f864845d202e5satok                return;
26927f35c8cc88bea5230f001dd4356f864845d202e5satok            }
2693ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
26948cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            hideInputMethodMenuLocked();
26959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2696688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            final List<ImeSubtypeListItem> imList =
2697d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSwitchingController.getSortedInputMethodAndSubtypeList(
2698688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                            showSubtypes, mInputShown, isScreenLocked);
2699913a8925c07e854a80bf5df87561f290d3a56d61satok
2700c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
27014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
2702c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                if (currentSubtype != null) {
2703c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                    final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
27048e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
27058e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            currentImi, currentSubtype.hashCode());
2706c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                }
2707c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            }
2708c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok
2709761eb3762f3602dd1859905ee4ba80f0ef6aec56Ken Wakasa            final int N = imList.size();
2710ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mIms = new InputMethodInfo[N];
2711ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mSubtypeIds = new int[N];
27128cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            int checkedItem = 0;
27138cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            for (int i = 0; i < N; ++i) {
271405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                final ImeSubtypeListItem item = imList.get(i);
271505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mIms[i] = item.mImi;
271605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mSubtypeIds[i] = item.mSubtypeId;
27178cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                if (mIms[i].getId().equals(lastInputMethodId)) {
2718ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    int subtypeId = mSubtypeIds[i];
2719ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    if ((subtypeId == NOT_A_SUBTYPE_ID)
2720ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0)
2721ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (subtypeId == lastInputMethodSubtypeId)) {
2722ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                        checkedItem = i;
2723ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
27248cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                }
27259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
272605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TypedArray a = context.obtainStyledAttributes(null,
27278cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    com.android.internal.R.styleable.DialogPreference,
27288cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    com.android.internal.R.attr.alertDialogStyle, 0);
27298cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            mDialogBuilder = new AlertDialog.Builder(context)
27308cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    .setOnCancelListener(new OnCancelListener() {
273142c5a1666c4e576ccd5974233513100aad2c1534satok                        @Override
27328cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        public void onCancel(DialogInterface dialog) {
27339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            hideInputMethodMenu();
27348cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        }
27358cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    })
27368cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    .setIcon(a.getDrawable(
27378cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                            com.android.internal.R.styleable.DialogPreference_dialogTitle));
27388cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            a.recycle();
273901038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final LayoutInflater inflater =
274001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
274101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final View tv = inflater.inflate(
274201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.layout.input_method_switch_dialog_title, null);
274301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mDialogBuilder.setCustomTitle(tv);
274401038492ff0317f0d3cff54d8a7ee36bb31ff175satok
274501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // Setup layout for a toggle switch of the hardware keyboard
274601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView = tv;
274701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView.findViewById(
274801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.id.hard_keyboard_section).setVisibility(
274901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mWindowManagerService.isHardKeyboardAvailable() ?
275001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    View.VISIBLE : View.GONE);
275101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final Switch hardKeySwitch =  ((Switch)mSwitchingDialogTitleView.findViewById(
275201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.id.hard_keyboard_switch));
275301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            hardKeySwitch.setChecked(mWindowManagerService.isHardKeyboardEnabled());
275401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            hardKeySwitch.setOnCheckedChangeListener(
275501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    new OnCheckedChangeListener() {
275601038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        @Override
275701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        public void onCheckedChanged(
275801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                CompoundButton buttonView, boolean isChecked) {
275901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mWindowManagerService.setHardKeyboardEnabled(isChecked);
276004dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            // Ensure that the input method dialog is dismissed when changing
276104dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            // the hardware keyboard state.
276204dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            hideInputMethodMenu();
276301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        }
276401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    });
2765d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok
276605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(context,
276705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    com.android.internal.R.layout.simple_list_item_2_single_choice, imList,
276805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    checkedItem);
276905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
277005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mDialogBuilder.setSingleChoiceItems(adapter, checkedItem,
27718cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    new AlertDialog.OnClickListener() {
277242c5a1666c4e576ccd5974233513100aad2c1534satok                        @Override
27738cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        public void onClick(DialogInterface dialog, int which) {
27748cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                            synchronized (mMethodMap) {
2775ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                if (mIms == null || mIms.length <= which
2776ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                        || mSubtypeIds == null || mSubtypeIds.length <= which) {
27778cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                    return;
27788cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                }
27798cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                InputMethodInfo im = mIms[which];
2780ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                int subtypeId = mSubtypeIds[which];
2781d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka                                adapter.mCheckedItem = which;
2782d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka                                adapter.notifyDataSetChanged();
27838cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                hideInputMethodMenu();
27848cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                if (im != null) {
2785ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    if ((subtypeId < 0)
2786586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                                            || (subtypeId >= im.getSubtypeCount())) {
2787ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                        subtypeId = NOT_A_SUBTYPE_ID;
2788ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    }
2789ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    setInputMethodLocked(im.getId(), subtypeId);
27908cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                }
279120cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn                            }
27929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
27938cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    });
27949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2795bc81b692d51a9cd6f9d61584aacd8308ac3366easatok            if (showSubtypes && !isScreenLocked) {
279682beadfa067b1e286fa604f8d7960d769411c954satok                mDialogBuilder.setPositiveButton(
279782beadfa067b1e286fa604f8d7960d769411c954satok                        com.android.internal.R.string.configure_input_methods,
27987f35c8cc88bea5230f001dd4356f864845d202e5satok                        new DialogInterface.OnClickListener() {
279942c5a1666c4e576ccd5974233513100aad2c1534satok                            @Override
28007f35c8cc88bea5230f001dd4356f864845d202e5satok                            public void onClick(DialogInterface dialog, int whichButton) {
2801217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                                showConfigureInputMethods();
28027f35c8cc88bea5230f001dd4356f864845d202e5satok                            }
28037f35c8cc88bea5230f001dd4356f864845d202e5satok                        });
28047f35c8cc88bea5230f001dd4356f864845d202e5satok            }
28059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog = mDialogBuilder.create();
2806e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.setCanceledOnTouchOutside(true);
28079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.getWindow().setType(
28089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
2809c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
2810c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2811e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
28129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.show();
28139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
28149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2815ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
281605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> {
281705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final LayoutInflater mInflater;
281805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final int mTextViewResourceId;
281905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final List<ImeSubtypeListItem> mItemsList;
2820d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka        public int mCheckedItem;
282105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public ImeSubtypeListAdapter(Context context, int textViewResourceId,
282205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                List<ImeSubtypeListItem> itemsList, int checkedItem) {
282305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            super(context, textViewResourceId, itemsList);
282405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mTextViewResourceId = textViewResourceId;
282505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mItemsList = itemsList;
282605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mCheckedItem = checkedItem;
282705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
282805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
282905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
283005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        @Override
283105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public View getView(int position, View convertView, ViewGroup parent) {
283205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final View view = convertView != null ? convertView
283305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    : mInflater.inflate(mTextViewResourceId, null);
283405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (position < 0 || position >= mItemsList.size()) return view;
283505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListItem item = mItemsList.get(position);
283605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence imeName = item.mImeName;
283705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence subtypeName = item.mSubtypeName;
283805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1);
283905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2);
284005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (TextUtils.isEmpty(subtypeName)) {
284105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(imeName);
284205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.GONE);
284305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            } else {
284405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(subtypeName);
284505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setText(imeName);
284605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.VISIBLE);
284705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            }
284805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final RadioButton radioButton =
284905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
285005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            radioButton.setChecked(position == mCheckedItem);
285105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            return view;
285205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
285305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    }
285405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
28559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hideInputMethodMenu() {
2856105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        synchronized (mMethodMap) {
2857105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
2858105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2859105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2860ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2861105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void hideInputMethodMenuLocked() {
28628a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Hide switching menu");
28639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2864105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mSwitchingDialog != null) {
2865105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog.dismiss();
2866105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog = null;
28679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2868ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2869105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mDialogBuilder = null;
2870105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIms = null;
28719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2872ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
28739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2874ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
287542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
28769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setInputMethodEnabled(String id, boolean enabled) {
28774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
28784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
28794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
28804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
28819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
28829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mContext.checkCallingOrSelfPermission(
28839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
28849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    != PackageManager.PERMISSION_GRANTED) {
28859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new SecurityException(
28869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Requires permission "
28879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
28889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
288921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
28909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
28919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
289221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                return setInputMethodEnabledLocked(id, enabled);
289321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } finally {
289421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Binder.restoreCallingIdentity(ident);
289521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
289621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
289721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
28988e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
289921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    boolean setInputMethodEnabledLocked(String id, boolean enabled) {
290021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        // Make sure this is a valid input method.
290121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        InputMethodInfo imm = mMethodMap.get(id);
290221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (imm == null) {
2903d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
290421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
2905ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2906d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
2907d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                .getEnabledInputMethodsAndSubtypeListLocked();
2908ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2909d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        if (enabled) {
2910d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            for (Pair<String, ArrayList<String>> pair: enabledInputMethodsList) {
2911d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                if (pair.first.equals(id)) {
2912d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // We are enabling this input method, but it is already enabled.
2913d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // Nothing to do. The previous state was enabled.
2914d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    return true;
29159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
291621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
2917d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            mSettings.appendAndPutEnabledInputMethodLocked(id, false);
2918d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            // Previous state was disabled.
2919d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return false;
2920d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        } else {
2921d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            StringBuilder builder = new StringBuilder();
2922d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
2923d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    builder, enabledInputMethodsList, id)) {
2924d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Disabled input method is currently selected, switch to another one.
29254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selId = mSettings.getSelectedInputMethod();
292603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
292703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
292803eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    resetSelectedInputMethodAndSubtypeLocked("");
2929d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                }
2930d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Previous state was enabled.
2931d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                return true;
2932d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            } else {
2933d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // We are disabling the input method but it is already disabled.
2934d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Nothing to do.  The previous state was disabled.
29359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
29369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
29379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
29394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
2940723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
2941723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            boolean setSubtypeOnly) {
2942723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Update the history of InputMethod and Subtype
29438e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
2944723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
2945723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Set Subtype here
2946723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi == null || subtypeId < 0) {
2947723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
29480ba75bb22c2992f649ee5f7605a2b45442ad4862Tadashi G. Takaoka            mCurrentSubtype = null;
2949723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        } else {
2950586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa            if (subtypeId < imi.getSubtypeCount()) {
2951586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                InputMethodSubtype subtype = imi.getSubtypeAt(subtypeId);
2952586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mSettings.putSelectedSubtype(subtype.hashCode());
2953586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mCurrentSubtype = subtype;
2954723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            } else {
2955723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
2956d81e950265356c81276b73da68a535ffa48d72f0satok                // If the subtype is not specified, choose the most applicable one
29574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
2958723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
2959723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
2960723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
29614c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Workaround.
29624c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // ASEC is not ready in the IMMS constructor. Accordingly, forward-locked
29634c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMEs are not recognized and considered uninstalled.
29644c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Actually, we can't move everything after SystemReady because
29654c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMMS needs to run in the encryption lock screen. So, we just skip changing
29664c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the default IME here and try cheking the default IME again in systemReady().
29674c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: Do nothing before system ready and implement a separated logic for
29684c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the encryption lock screen.
29694c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: ASEC should be ready before IMMS is instantiated.
29704c0e7152e74d091eb78af8baacd38287ba95a1a1satok        if (mSystemReady && !setSubtypeOnly) {
2971723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // Set InputMethod here
2972723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
29731ab852fbcfe155c9d4373b7130f8515591669634satok        }
2974ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2975ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2976723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
2977723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        InputMethodInfo imi = mMethodMap.get(newDefaultIme);
2978723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        int lastSubtypeId = NOT_A_SUBTYPE_ID;
2979723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // newDefaultIme is empty when there is no candidate for the selected IME.
2980723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
2981723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme);
2982723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            if (subtypeHashCode != null) {
2983723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                try {
29848e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
2985723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                            imi, Integer.valueOf(subtypeHashCode));
2986723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                } catch (NumberFormatException e) {
2987723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                    Slog.w(TAG, "HashCode for subtype looks broken: " + subtypeHashCode, e);
2988723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                }
2989723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
2990723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
2991723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
2992723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    }
2993723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
29944e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // If there are no selected shortcuts, tries finding the most applicable ones.
29954e4569dab5c75804b01a19b2d6e6101b445c1c68satok    private Pair<InputMethodInfo, InputMethodSubtype>
29964e4569dab5c75804b01a19b2d6e6101b445c1c68satok            findLastResortApplicableShortcutInputMethodAndSubtypeLocked(String mode) {
29974e4569dab5c75804b01a19b2d6e6101b445c1c68satok        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
29984e4569dab5c75804b01a19b2d6e6101b445c1c68satok        InputMethodInfo mostApplicableIMI = null;
2999cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        InputMethodSubtype mostApplicableSubtype = null;
30004e4569dab5c75804b01a19b2d6e6101b445c1c68satok        boolean foundInSystemIME = false;
30014e4569dab5c75804b01a19b2d6e6101b445c1c68satok
30024e4569dab5c75804b01a19b2d6e6101b445c1c68satok        // Search applicable subtype for each InputMethodInfo
30034e4569dab5c75804b01a19b2d6e6101b445c1c68satok        for (InputMethodInfo imi: imis) {
30047599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            final String imiId = imi.getId();
30057599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (foundInSystemIME && !imiId.equals(mCurMethodId)) {
30067599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                continue;
30077599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3008cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            InputMethodSubtype subtype = null;
3009df31ae6a3011d47421a6ac10021f9649dc34a156satok            final List<InputMethodSubtype> enabledSubtypes =
30108e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
3011df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 1. Search by the current subtype's locale from enabledSubtypes.
30124e4569dab5c75804b01a19b2d6e6101b445c1c68satok            if (mCurrentSubtype != null) {
30138e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3014df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
30154e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3016df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 2. Search by the system locale from enabledSubtypes.
3017df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
3018cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
30198e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3020df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, null, true);
30217599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3022a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
30238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    InputMethodUtils.getOverridingImplicitlyEnabledSubtypes(imi, mode);
3024a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> subtypesForSearch =
3025a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                    overridingImplicitlyEnabledSubtypes.isEmpty()
30268e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            ? InputMethodUtils.getSubtypes(imi)
30278e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            : overridingImplicitlyEnabledSubtypes;
30287599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 4. Search by the current subtype's locale from all subtypes.
30297599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (subtype == null && mCurrentSubtype != null) {
30308e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3031a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
30324e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
30337599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 5. Search by the system locale from all subtypes.
30347599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 6. Search the first enabled subtype matched with mode from all subtypes.
3035cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
30368e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3037a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, null, true);
30384e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3039cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype != null) {
30407599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (imiId.equals(mCurMethodId)) {
30414e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    // The current input method is the most applicable IME.
30424e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3043cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
30444e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    break;
30454e4569dab5c75804b01a19b2d6e6101b445c1c68satok                } else if (!foundInSystemIME) {
30467599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    // The system input method is 2nd applicable IME.
30474e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3048cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
30497599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    if ((imi.getServiceInfo().applicationInfo.flags
30507599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
30517599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                        foundInSystemIME = true;
30527599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    }
30534e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
30544e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
30554e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
30564e4569dab5c75804b01a19b2d6e6101b445c1c68satok        if (DEBUG) {
3057cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (mostApplicableIMI != null) {
3058cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                Slog.w(TAG, "Most applicable shortcut input method was:"
3059cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                        + mostApplicableIMI.getId());
3060cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                if (mostApplicableSubtype != null) {
3061cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    Slog.w(TAG, "Most applicable shortcut input method subtype was:"
3062cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + "," + mostApplicableSubtype.getMode() + ","
3063cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + mostApplicableSubtype.getLocale());
3064cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                }
3065cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            }
30664e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
3067cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        if (mostApplicableIMI != null) {
30684e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
3069cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype);
30704e4569dab5c75804b01a19b2d6e6101b445c1c68satok        } else {
30714e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return null;
30724e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
30734e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
30744e4569dab5c75804b01a19b2d6e6101b445c1c68satok
3075ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3076ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return Return the current subtype of this input method.
3077ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
307842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3079ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public InputMethodSubtype getCurrentInputMethodSubtype() {
30804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
30814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
30824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
30834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
30844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        synchronized (mMethodMap) {
30854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return getCurrentInputMethodSubtypeLocked();
30864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
30874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
30884e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
30894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
3090fdf419e81d795593e3792c9e78f33ed899ff098esatok        if (mCurMethodId == null) {
3091fdf419e81d795593e3792c9e78f33ed899ff098esatok            return null;
3092fdf419e81d795593e3792c9e78f33ed899ff098esatok        }
30938e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
30944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
30954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (imi == null || imi.getSubtypeCount() == 0) {
30964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
30974e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
30984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!subtypeIsSelected || mCurrentSubtype == null
30998e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
31008e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
31014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (subtypeId == NOT_A_SUBTYPE_ID) {
31024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there are no selected subtypes, the framework will try to find
31034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // the most applicable subtype from explicitly or implicitly enabled
31044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // subtypes.
31054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
31068e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
31074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there is only one explicitly or implicitly enabled subtype,
31084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // just returns it.
31094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
31104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
31114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
31128e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
31134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            mRes, explicitlyOrImplicitlyEnabledSubtypes,
31148e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, null, true);
31154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    if (mCurrentSubtype == null) {
31168e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
31174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
31184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                true);
31194e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    }
31203ef8b29fa03fe3ae1c57fd891a12afa46128fff8satok                }
31214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else {
31228e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mCurrentSubtype = InputMethodUtils.getSubtypes(imi).get(subtypeId);
31238fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok            }
31248fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok        }
31254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        return mCurrentSubtype;
3126ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3127ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3128f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
3129f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            InputMethodSubtype subtype) {
3130f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
3131f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
3132f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        } else {
3133f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3134f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            subtypes.add(subtype);
3135f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
3136f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        }
3137f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    }
3138f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok
31394e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // TODO: We should change the return type from List to List<Parcelable>
3140dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("rawtypes")
3141e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
31424e4569dab5c75804b01a19b2d6e6101b445c1c68satok    public List getShortcutInputMethodsAndSubtypes() {
31434e4569dab5c75804b01a19b2d6e6101b445c1c68satok        synchronized (mMethodMap) {
31443da922367c0dbe67b97fe97fcfca13fd93602f7asatok            ArrayList<Object> ret = new ArrayList<Object>();
3145f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            if (mShortcutInputMethodsAndSubtypes.size() == 0) {
31464e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // If there are no selected shortcut subtypes, the framework will try to find
31474e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // the most applicable subtype from all subtypes whose mode is
31484e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
3149f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                Pair<InputMethodInfo, InputMethodSubtype> info =
3150f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
31518e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_VOICE);
31527599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (info != null) {
31533da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.first);
31543da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.second);
31557599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                }
31563da922367c0dbe67b97fe97fcfca13fd93602f7asatok                return ret;
3157f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            }
3158f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
3159f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                ret.add(imi);
3160f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
3161f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    ret.add(subtype);
31624e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
31634e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3164f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            return ret;
31654e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
31664e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
31674e4569dab5c75804b01a19b2d6e6101b445c1c68satok
316842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3169b66d287e3003a0934d5714fbf15e554b3c814906satok    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
31704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
31714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
31724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
31734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
3174b66d287e3003a0934d5714fbf15e554b3c814906satok        synchronized (mMethodMap) {
3175b66d287e3003a0934d5714fbf15e554b3c814906satok            if (subtype != null && mCurMethodId != null) {
3176b66d287e3003a0934d5714fbf15e554b3c814906satok                InputMethodInfo imi = mMethodMap.get(mCurMethodId);
31778e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                int subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode());
3178b66d287e3003a0934d5714fbf15e554b3c814906satok                if (subtypeId != NOT_A_SUBTYPE_ID) {
3179b66d287e3003a0934d5714fbf15e554b3c814906satok                    setInputMethodLocked(mCurMethodId, subtypeId);
3180b66d287e3003a0934d5714fbf15e554b3c814906satok                    return true;
3181b66d287e3003a0934d5714fbf15e554b3c814906satok                }
3182b66d287e3003a0934d5714fbf15e554b3c814906satok            }
3183b66d287e3003a0934d5714fbf15e554b3c814906satok            return false;
3184b66d287e3003a0934d5714fbf15e554b3c814906satok        }
3185b66d287e3003a0934d5714fbf15e554b3c814906satok    }
3186b66d287e3003a0934d5714fbf15e554b3c814906satok
31875ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    // TODO: Cache the state for each user and reset when the cached user is removed.
3188e7c6998e0a953ae55487d4fe122739646f9280aasatok    private static class InputMethodFileManager {
3189e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String SYSTEM_PATH = "system";
3190e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String INPUT_METHOD_PATH = "inputmethod";
3191e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ADDITIONAL_SUBTYPES_FILE_NAME = "subtypes.xml";
3192e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPES = "subtypes";
3193e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPE = "subtype";
3194e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_IMI = "imi";
3195e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ID = "id";
3196e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_LABEL = "label";
3197e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ICON = "icon";
3198e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
3199e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
3200e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
3201e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
3202e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final AtomicFile mAdditionalInputMethodSubtypeFile;
3203e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final HashMap<String, InputMethodInfo> mMethodMap;
3204e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
3205e7c6998e0a953ae55487d4fe122739646f9280aasatok                new HashMap<String, List<InputMethodSubtype>>();
32065ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
3207e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (methodMap == null) {
3208e7c6998e0a953ae55487d4fe122739646f9280aasatok                throw new NullPointerException("methodMap is null");
3209e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3210e7c6998e0a953ae55487d4fe122739646f9280aasatok            mMethodMap = methodMap;
32115ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka            final File systemDir = userId == UserHandle.USER_OWNER
32125ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
32135ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    : Environment.getUserSystemDirectory(userId);
3214e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
3215e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!inputMethodDir.mkdirs()) {
3216e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
3217e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3218e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
3219e7c6998e0a953ae55487d4fe122739646f9280aasatok            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
3220e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!subtypeFile.exists()) {
3221e7c6998e0a953ae55487d4fe122739646f9280aasatok                // If "subtypes.xml" doesn't exist, create a blank file.
3222e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3223e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, methodMap);
3224e7c6998e0a953ae55487d4fe122739646f9280aasatok            } else {
3225e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                readAdditionalInputMethodSubtypes(
3226e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile);
3227e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3228e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3229e7c6998e0a953ae55487d4fe122739646f9280aasatok
3230e7c6998e0a953ae55487d4fe122739646f9280aasatok        private void deleteAllInputMethodSubtypes(String imiId) {
3231e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3232e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.remove(imiId);
3233e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3234e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3235e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3236e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3237e7c6998e0a953ae55487d4fe122739646f9280aasatok
3238e7c6998e0a953ae55487d4fe122739646f9280aasatok        public void addInputMethodSubtypes(
32394a28bde70e23b2ed151d52690da702da7f23cf5esatok                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
3240e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3241e7c6998e0a953ae55487d4fe122739646f9280aasatok                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3242e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int N = additionalSubtypes.length;
3243e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (int i = 0; i < N; ++i) {
3244e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final InputMethodSubtype subtype = additionalSubtypes[i];
3245ed2b24ecc7842b27178fc584a9e5bd5b1ab07635satok                    if (!subtypes.contains(subtype)) {
3246e7c6998e0a953ae55487d4fe122739646f9280aasatok                        subtypes.add(subtype);
3247e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                    } else {
3248e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        Slog.w(TAG, "Duplicated subtype definition found: "
3249e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                                + subtype.getLocale() + ", " + subtype.getMode());
3250e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3251e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3252e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.put(imi.getId(), subtypes);
3253e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3254e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3255e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3256e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3257e7c6998e0a953ae55487d4fe122739646f9280aasatok
3258e7c6998e0a953ae55487d4fe122739646f9280aasatok        public HashMap<String, List<InputMethodSubtype>> getAllAdditionalInputMethodSubtypes() {
3259e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3260e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                return mAdditionalSubtypesMap;
3261e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3262e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3263e7c6998e0a953ae55487d4fe122739646f9280aasatok
3264e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void writeAdditionalInputMethodSubtypes(
3265e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile,
3266e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, InputMethodInfo> methodMap) {
3267e7c6998e0a953ae55487d4fe122739646f9280aasatok            // Safety net for the case that this function is called before methodMap is set.
3268e7c6998e0a953ae55487d4fe122739646f9280aasatok            final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0;
3269e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileOutputStream fos = null;
3270e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3271e7c6998e0a953ae55487d4fe122739646f9280aasatok                fos = subtypesFile.startWrite();
3272e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlSerializer out = new FastXmlSerializer();
3273e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setOutput(fos, "utf-8");
3274e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startDocument(null, true);
3275e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3276e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startTag(null, NODE_SUBTYPES);
3277e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (String imiId : allSubtypes.keySet()) {
3278e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (isSetMethodMap && !methodMap.containsKey(imiId)) {
3279e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "IME uninstalled or not valid.: " + imiId);
3280e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3281e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3282e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.startTag(null, NODE_IMI);
3283e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.attribute(null, ATTR_ID, imiId);
3284e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final List<InputMethodSubtype> subtypesList = allSubtypes.get(imiId);
3285e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final int N = subtypesList.size();
3286e7c6998e0a953ae55487d4fe122739646f9280aasatok                    for (int i = 0; i < N; ++i) {
3287e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype = subtypesList.get(i);
3288e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.startTag(null, NODE_SUBTYPE);
3289e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
3290e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
3291e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
3292e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_MODE, subtype.getMode());
3293e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
3294e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IS_AUXILIARY,
3295e7c6998e0a953ae55487d4fe122739646f9280aasatok                                String.valueOf(subtype.isAuxiliary() ? 1 : 0));
3296e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.endTag(null, NODE_SUBTYPE);
3297e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3298e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.endTag(null, NODE_IMI);
3299e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3300e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endTag(null, NODE_SUBTYPES);
3301e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endDocument();
3302e7c6998e0a953ae55487d4fe122739646f9280aasatok                subtypesFile.finishWrite(fos);
3303e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3304e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error writing subtypes", e);
3305e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fos != null) {
3306e7c6998e0a953ae55487d4fe122739646f9280aasatok                    subtypesFile.failWrite(fos);
3307e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3308e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3309e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3310e7c6998e0a953ae55487d4fe122739646f9280aasatok
3311e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void readAdditionalInputMethodSubtypes(
3312e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile) {
3313e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (allSubtypes == null || subtypesFile == null) return;
3314e7c6998e0a953ae55487d4fe122739646f9280aasatok            allSubtypes.clear();
3315e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileInputStream fis = null;
3316e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3317e7c6998e0a953ae55487d4fe122739646f9280aasatok                fis = subtypesFile.openRead();
3318e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlPullParser parser = Xml.newPullParser();
3319e7c6998e0a953ae55487d4fe122739646f9280aasatok                parser.setInput(fis, null);
3320e7c6998e0a953ae55487d4fe122739646f9280aasatok                int type = parser.getEventType();
3321e7c6998e0a953ae55487d4fe122739646f9280aasatok                // Skip parsing until START_TAG
3322e7c6998e0a953ae55487d4fe122739646f9280aasatok                while ((type = parser.next()) != XmlPullParser.START_TAG
3323e7c6998e0a953ae55487d4fe122739646f9280aasatok                        && type != XmlPullParser.END_DOCUMENT) {}
3324e7c6998e0a953ae55487d4fe122739646f9280aasatok                String firstNodeName = parser.getName();
3325e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (!NODE_SUBTYPES.equals(firstNodeName)) {
3326e7c6998e0a953ae55487d4fe122739646f9280aasatok                    throw new XmlPullParserException("Xml doesn't start with subtypes");
3327e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3328e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int depth =parser.getDepth();
3329e7c6998e0a953ae55487d4fe122739646f9280aasatok                String currentImiId = null;
3330e7c6998e0a953ae55487d4fe122739646f9280aasatok                ArrayList<InputMethodSubtype> tempSubtypesArray = null;
3331e7c6998e0a953ae55487d4fe122739646f9280aasatok                while (((type = parser.next()) != XmlPullParser.END_TAG
3332e7c6998e0a953ae55487d4fe122739646f9280aasatok                        || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
3333e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (type != XmlPullParser.START_TAG)
3334e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3335e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final String nodeName = parser.getName();
3336e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (NODE_IMI.equals(nodeName)) {
3337e7c6998e0a953ae55487d4fe122739646f9280aasatok                        currentImiId = parser.getAttributeValue(null, ATTR_ID);
3338e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId)) {
3339e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "Invalid imi id found in subtypes.xml");
3340e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3341e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3342e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray = new ArrayList<InputMethodSubtype>();
3343e7c6998e0a953ae55487d4fe122739646f9280aasatok                        allSubtypes.put(currentImiId, tempSubtypesArray);
3344e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } else if (NODE_SUBTYPE.equals(nodeName)) {
3345e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
3346e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "IME uninstalled or not valid.: " + currentImiId);
3347e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3348e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3349e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int icon = Integer.valueOf(
3350e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_ICON));
3351e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int label = Integer.valueOf(
3352e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_LABEL));
3353e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeLocale =
3354e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LOCALE);
3355e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeMode =
3356e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
3357e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeExtraValue =
3358e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
33594a28bde70e23b2ed151d52690da702da7f23cf5esatok                        final boolean isAuxiliary = "1".equals(String.valueOf(
33604a28bde70e23b2ed151d52690da702da7f23cf5esatok                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
3361e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype =
3362e7c6998e0a953ae55487d4fe122739646f9280aasatok                                new InputMethodSubtype(label, icon, imeSubtypeLocale,
3363e7c6998e0a953ae55487d4fe122739646f9280aasatok                                        imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
3364e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray.add(subtype);
3365e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3366e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3367e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (XmlPullParserException e) {
3368e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3369e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3370e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3371e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3372e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3373e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (NumberFormatException e) {
3374e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3375e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3376e7c6998e0a953ae55487d4fe122739646f9280aasatok            } finally {
3377e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fis != null) {
3378e7c6998e0a953ae55487d4fe122739646f9280aasatok                    try {
3379e7c6998e0a953ae55487d4fe122739646f9280aasatok                        fis.close();
3380e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } catch (java.io.IOException e1) {
3381e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "Failed to close.");
3382e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3383e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3384e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3385e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3386e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
3387e7c6998e0a953ae55487d4fe122739646f9280aasatok
33889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
33899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
33909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
33919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3392ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
33939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Permission Denial: can't dump InputMethodManager from from pid="
33949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
33959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
33969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
33979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
33989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IInputMethod method;
34009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState client;
3401ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
34029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(pw);
3403ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
34049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
34059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("Current Input Method Manager state:");
34069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mMethodList.size();
34079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Input Methods:");
34089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
34099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo info = mMethodList.get(i);
34109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  InputMethod #" + i + ":");
34119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.dump(p, "    ");
34129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
34139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Clients:");
34149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState ci : mClients.values()) {
34159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  Client " + ci + ":");
34169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    client=" + ci.client);
34179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    inputContext=" + ci.inputContext);
34189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    sessionRequested=" + ci.sessionRequested);
34199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    curSession=" + ci.curSession);
34209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3421105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            p.println("  mCurMethodId=" + mCurMethodId);
34229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = mCurClient;
3423b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
3424b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
34259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
34269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mBoundToMethod=" + mBoundToMethod);
34279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurToken=" + mCurToken);
34289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurIntent=" + mCurIntent);
34299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = mCurMethod;
34309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurMethod=" + mCurMethod);
34319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mEnabledSession=" + mEnabledSession);
34329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mShowRequested=" + mShowRequested
34339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
34349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowForced=" + mShowForced
34359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mInputShown=" + mInputShown);
3436cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            p.println("  mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn);
34379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3438ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3439b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
34409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (client != null) {
34419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
34429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
34439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                client.client.asBinder().dump(fd, args);
34449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
34459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method client dead: " + e);
34469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3447b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3448b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method client.");
34499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3450ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3451b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
34529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (method != null) {
34539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
34549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
34559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                method.asBinder().dump(fd, args);
34569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
34579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method service dead: " + e);
34589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3459b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3460b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method service.");
34619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
34629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
34639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3464