InputMethodManagerService.java revision 2a764949c943681a4d25a17a0b203a0127a4a486
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;
151ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
15201038492ff0317f0d3cff54d8a7ee36bb31ff175satok    static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
15301038492ff0317f0d3cff54d8a7ee36bb31ff175satok
154bcacc322f83de1fe522081a20e0ac36ec8243763Satoshi Kataoka    static final long TIME_TO_RECONNECT = 3 * 1000;
155ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
156f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20;
157f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1588e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
159b6359414adabab2d64acc8ccc9e3b9c1b800b303satok    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
1608e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
1614e4569dab5c75804b01a19b2d6e6101b445c1c68satok
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Context mContext;
1637d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn    final Resources mRes;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Handler mHandler;
165d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final InputMethodSettings mSettings;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final SettingsObserver mSettingsObserver;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IWindowManager mIWindowManager;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HandlerCaller mCaller;
169119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final boolean mHasFeature;
1705ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private InputMethodFileManager mFileManager;
17101038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final HardKeyboardListener mHardKeyboardListener;
17201038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final WindowManagerService mWindowManagerService;
173ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
174c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1);
175ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // All known input methods.  mMethodMap also serves as the global
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // lock for this class.
178d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
179d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
180f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
181f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
182d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    private final InputMethodSubtypeSwitchingController mSwitchingController;
183ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1842c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    // Used to bring IME service up to visible adjustment while it is being shown.
1852c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    final ServiceConnection mVisibleConnection = new ServiceConnection() {
1862c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceConnected(ComponentName name, IBinder service) {
1872c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1882c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1892c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceDisconnected(ComponentName name) {
1902c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
1912c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    };
1922c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    boolean mVisibleBound = false;
1932c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1947cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    // Ongoing notification
195661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private NotificationManager mNotificationManager;
196661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private KeyguardManager mKeyguardManager;
197661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private StatusBarManagerService mStatusBar;
198661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private Notification mImeSwitcherNotification;
199661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private PendingIntent mImeSwitchPendingIntent;
200b858c732f665fe9610f2d913230ae625f44a8caasatok    private boolean mShowOngoingImeSwitcherForPhones;
2017cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean mNotificationShown;
2020a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok    private final boolean mImeSelectedOnBoot;
2037cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SessionState {
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ClientState client;
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethod method;
207c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
208c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        IInputMethodSession session;
209c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        InputChannel channel;
210ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "SessionState{uid " + client.uid + " pid " + client.pid
2149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " method " + Integer.toHexString(
2159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(method))
2169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " session " + Integer.toHexString(
2179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(session))
218c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    + " channel " + channel
2199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "}";
2209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState(ClientState _client, IInputMethod _method,
223c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                IInputMethodSession _session, InputChannel _channel) {
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = _method;
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            session = _session;
227c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            channel = _channel;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
230ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
231c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    static final class ClientState {
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethodClient client;
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputContext inputContext;
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int uid;
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int pid;
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final InputBinding binding;
237ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean sessionRequested;
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState curSession;
240ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ClientState{" + Integer.toHexString(
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.identityHashCode(this)) + " uid " + uid
2459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " pid " + pid + "}";
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState(IInputMethodClient _client, IInputContext _inputContext,
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int _uid, int _pid) {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inputContext = _inputContext;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uid = _uid;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pid = _pid;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
257ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, ClientState> mClients
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<IBinder, ClientState>();
260ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
262a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     * Set once the system is ready to run third party code.
263a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     */
264a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    boolean mSystemReady;
265ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
266a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    /**
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Id of the currently selected input method.
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurMethodId;
270ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The current binding sequence number, incremented every time there is
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new bind performed.
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCurSeq;
276ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The client that is currently bound to an input method.
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ClientState mCurClient;
281ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
283b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     * The last window token that gained focus.
284b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     */
285b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    IBinder mCurFocusedWindow;
286ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
287b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    /**
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input context last provided by the current client.
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputContext mCurInputContext;
291ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The attributes last provided by the current client.
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mCurAttribute;
296ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method ID of the input method service that we are currently
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * connected to or in the process of connecting to.
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurId;
302ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
304ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * The current subtype of the current input method.
305ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
306ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private InputMethodSubtype mCurrentSubtype;
307ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3084e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
309f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
310f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes =
311f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
312ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
313e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    // Was the keyguard locked when this client became current?
314e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean mCurClientInKeyguard;
315e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
316ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set to true if our ServiceConnection is currently actively bound to
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a service (whether or not we have gotten its IBinder back yet).
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mHaveConnection;
321ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if the client has asked for the input method to be shown.
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowRequested;
326ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were explicitly told to show the input method.
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowExplicitlyRequested;
331ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were forced to be shown.
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowForced;
336ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we last told the input method to show itself.
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputShown;
341ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The Intent used to connect to the current input method.
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Intent mCurIntent;
346ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The token we have made for the currently active input method, to
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * identify it in the future.
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mCurToken;
352ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If non-null, this is the input method service we are currently connected
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to.
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputMethod mCurMethod;
358ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time that we last initiated a bind to the input method, to determine
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if we should try to disconnect and reconnect to it.
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mLastBindTime;
364ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Have we called mCurMethod.bindInput()?
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mBoundToMethod;
369ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Currently enabled session.  Only touched by service thread, not
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * protected by a lock.
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SessionState mEnabledSession;
375ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * True if the screen is on.  The value is true initially.
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mScreenOn = true;
380ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
381857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
382857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mImeWindowVis;
383857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
38405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog.Builder mDialogBuilder;
38505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog mSwitchingDialog;
38601038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private View mSwitchingDialogTitleView;
38705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private InputMethodInfo[] mIms;
38805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private int[] mSubtypeIds;
3895b927c431f54ea47c3333afb7940d79e2e863f1asatok    private Locale mLastSystemLocale;
3904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
3914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final IPackageManager mIPackageManager;
392ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SettingsObserver extends ContentObserver {
394fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        String mLastEnabled = "";
395fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SettingsObserver(Handler handler) {
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(handler);
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver resolver = mContext.getContentResolver();
3999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resolver.registerContentObserver(Settings.Secure.getUriFor(
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
401ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            resolver.registerContentObserver(Settings.Secure.getUriFor(
402b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok                    Settings.Secure.ENABLED_INPUT_METHODS), false, this);
403b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok            resolver.registerContentObserver(Settings.Secure.getUriFor(
404ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this);
4059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
406ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override public void onChange(boolean selfChange) {
4089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
409fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                boolean enabledChanged = false;
410fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                String newEnabled = mSettings.getEnabledInputMethodsStr();
411fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                if (!mLastEnabled.equals(newEnabled)) {
412fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    mLastEnabled = newEnabled;
413fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    enabledChanged = true;
414fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
415fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                updateFromSettingsLocked(enabledChanged);
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
419ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
4214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private void updateActive() {
4224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // Inform the current client of the change in active status
4234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (mCurClient != null && mCurClient.client != null) {
4244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
4254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
4264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
4314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String action = intent.getAction();
4324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (Intent.ACTION_SCREEN_ON.equals(action)) {
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = true;
4343afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                refreshImeWindowVisibilityLocked();
4354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
4389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = false;
43915452a487a4c0274f4217cd060aa54446f30a8f3satok                setImeWindowVisibilityStatusHiddenLocked();
4404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
4414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
4424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
443105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                hideInputMethodMenu();
4444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // No need to updateActive
445105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                return;
446734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani            } else if (Intent.ACTION_USER_ADDED.equals(action)
447734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                    || Intent.ACTION_USER_REMOVED.equals(action)) {
4482a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                updateCurrentProfileIds();
449734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                return;
4509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
4518a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unexpected intent " + intent);
4529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
455ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
45621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
4574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private boolean isChangingPackagesOfCurrentUser() {
4584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final int userId = getChangingUserId();
4594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final boolean retval = userId == mSettings.getCurrentUserId();
4604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
46181f8b7c66750a0a89c8e6b6037136ca169c96f95satok                if (!retval) {
46281f8b7c66750a0a89c8e6b6037136ca169c96f95satok                    Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
46381f8b7c66750a0a89c8e6b6037136ca169c96f95satok                }
4644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return retval;
4664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
4674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
4689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
46921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
4704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
4714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return false;
4724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
47321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
4744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
47521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                final int N = mMethodList.size();
47621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curInputMethodId != null) {
47721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    for (int i=0; i<N; i++) {
47821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
47921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (imi.getId().equals(curInputMethodId)) {
48021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            for (String pkg : packages) {
48121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                if (imi.getPackageName().equals(pkg)) {
48221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    if (!doit) {
48321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        return true;
48421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    }
485723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                    resetSelectedInputMethodAndSubtypeLocked("");
48621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    chooseNewDefaultIMELocked();
48721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    return true;
48821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                }
48921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            }
49021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
49121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
49208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                }
49308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu            }
49421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return false;
49521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
496ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
49721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        @Override
49821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
4994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
5004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
5014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
50221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo curIm = null;
5044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int N = mMethodList.size();
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (curInputMethodId != null) {
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<N; i++) {
50821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
509e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imiId = imi.getId();
510e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (imiId.equals(curInputMethodId)) {
51121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            curIm = imi;
51221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
513e7c6998e0a953ae55487d4fe122739646f9280aasatok
51421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        int change = isPackageDisappearing(imi.getPackageName());
515e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (isPackageModified(imi.getPackageName())) {
516e7c6998e0a953ae55487d4fe122739646f9280aasatok                            mFileManager.deleteAllInputMethodSubtypes(imiId);
517e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
51821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (change == PACKAGE_TEMPORARY_CHANGE
51921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                || change == PACKAGE_PERMANENT_CHANGE) {
5208a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Input method uninstalled, disabling: "
52121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    + imi.getComponent());
52221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            setInputMethodEnabledLocked(imi.getId(), false);
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
526ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
527f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(
528f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        mMethodList, mMethodMap, false /* resetDefaultEnabledIme */);
52921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed = false;
531ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
53208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                if (curIm != null) {
53321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    int change = isPackageDisappearing(curIm.getPackageName());
53421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (change == PACKAGE_TEMPORARY_CHANGE
53521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            || change == PACKAGE_PERMANENT_CHANGE) {
53608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        ServiceInfo si = null;
53708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        try {
5384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            si = mIPackageManager.getServiceInfo(
5394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    curIm.getComponent(), 0, mSettings.getCurrentUserId());
5404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        } catch (RemoteException ex) {
54108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
54208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (si == null) {
54308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Uh oh, current input method is no longer around!
54408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Pick another one...
5458a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
54615452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
54721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            if (!chooseNewDefaultIMELocked()) {
54808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                changed = true;
54908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                curIm = null;
5508a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.i(TAG, "Unsetting current input method");
551723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                resetSelectedInputMethodAndSubtypeLocked("");
55208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
55308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
55408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
55521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
556ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
55721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curIm == null) {
55821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // We currently don't have a default input method... is
55921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // one now available?
56021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    changed = chooseNewDefaultIMELocked();
56121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
562ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
56321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (changed) {
564fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(false);
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
569ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
570c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private static final class MethodCallback extends IInputSessionCallback.Stub {
571e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard        private final InputMethodManagerService mParentIMMS;
572c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final IInputMethod mMethod;
573c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final InputChannel mChannel;
574ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
575c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        MethodCallback(InputMethodManagerService imms, IInputMethod method,
576c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel) {
577e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard            mParentIMMS = imms;
578c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mMethod = method;
579c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mChannel = channel;
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
581ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
582e7c6998e0a953ae55487d4fe122739646f9280aasatok        @Override
583c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        public void sessionCreated(IInputMethodSession session) {
5846b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            long ident = Binder.clearCallingIdentity();
5856b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            try {
5866b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                mParentIMMS.onSessionCreated(mMethod, session, mChannel);
5876b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            } finally {
5886b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                Binder.restoreCallingIdentity(ident);
5896b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            }
5909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
592ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
59301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private class HardKeyboardListener
59401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            implements WindowManagerService.OnHardKeyboardStatusChangeListener {
59501038492ff0317f0d3cff54d8a7ee36bb31ff175satok        @Override
59601038492ff0317f0d3cff54d8a7ee36bb31ff175satok        public void onHardKeyboardStatusChange(boolean available, boolean enabled) {
59701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mHandler.sendMessage(mHandler.obtainMessage(
59801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    MSG_HARD_KEYBOARD_SWITCH_CHANGED, available ? 1 : 0, enabled ? 1 : 0));
59901038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
60001038492ff0317f0d3cff54d8a7ee36bb31ff175satok
60101038492ff0317f0d3cff54d8a7ee36bb31ff175satok        public void handleHardKeyboardStatusChange(boolean available, boolean enabled) {
60201038492ff0317f0d3cff54d8a7ee36bb31ff175satok            if (DEBUG) {
60301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                Slog.w(TAG, "HardKeyboardStatusChanged: available = " + available + ", enabled = "
60401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        + enabled);
60501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
60601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            synchronized(mMethodMap) {
60701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
60801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        && mSwitchingDialog.isShowing()) {
60901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mSwitchingDialogTitleView.findViewById(
61001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            com.android.internal.R.id.hard_keyboard_section).setVisibility(
61101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    available ? View.VISIBLE : View.GONE);
61201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
61301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
61401038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
61501038492ff0317f0d3cff54d8a7ee36bb31ff175satok    }
61601038492ff0317f0d3cff54d8a7ee36bb31ff175satok
61701038492ff0317f0d3cff54d8a7ee36bb31ff175satok    public InputMethodManagerService(Context context, WindowManagerService windowManager) {
6184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mIPackageManager = AppGlobals.getPackageManager();
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
6207d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn        mRes = context.getResources();
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new Handler(this);
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIWindowManager = IWindowManager.Stub.asInterface(
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.WINDOW_SERVICE));
624ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
625e7c6998e0a953ae55487d4fe122739646f9280aasatok            @Override
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void executeMessage(Message msg) {
6279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleMessage(msg);
6289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
629ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        }, true /*asyncHandler*/);
63001038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mWindowManagerService = windowManager;
63101038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mHardKeyboardListener = new HardKeyboardListener();
632119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        mHasFeature = context.getPackageManager().hasSystemFeature(
633119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                PackageManager.FEATURE_INPUT_METHODS);
6347cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6357cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification = new Notification();
6367cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
6377cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.when = 0;
6387cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT;
6397cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.tickerText = null;
6407cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.defaults = 0; // please be quiet
6417cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.sound = null;
6427cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mImeSwitcherNotification.vibrate = null;
643590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
644590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler        // Tag this notification specially so SystemUI knows it's important
645fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
646fd7f1e00399e53a392941928ed5a55ca77b1b721John Spurlock        mImeSwitcherNotification.category = Notification.CATEGORY_SYSTEM;
647590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
6487cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
649683e2383c8549f95e00bade15daed3dbddf13950satok        mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
650b858c732f665fe9610f2d913230ae625f44a8caasatok
651b858c732f665fe9610f2d913230ae625f44a8caasatok        mShowOngoingImeSwitcherForPhones = false;
6527cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
6534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final IntentFilter broadcastFilter = new IntentFilter();
6544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
6554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
6564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
657734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
658734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
6594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
660ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
6617cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mNotificationShown = false;
6624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        int userId = 0;
6634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        try {
6644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            ActivityManagerNative.getDefault().registerUserSwitchObserver(
6654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    new IUserSwitchObserver.Stub() {
6664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
6685ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            synchronized(mMethodMap) {
6695ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                                switchUserLocked(newUserId);
6705ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            }
6714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            if (reply != null) {
6724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                try {
6734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    reply.sendResult(null);
6744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                } catch (RemoteException e) {
6754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                }
6764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            }
6774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
6784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
6794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
6804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
6814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
6824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    });
6834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
6844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } catch (RemoteException e) {
6854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
6864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
68781f8b7c66750a0a89c8e6b6037136ca169c96f95satok        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
688913a8925c07e854a80bf5df87561f290d3a56d61satok
689d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        // mSettings should be created before buildInputMethodListLocked
690df31ae6a3011d47421a6ac10021f9649dc34a156satok        mSettings = new InputMethodSettings(
6914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
6922a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
6935ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, userId);
694d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mSwitchingController = new InputMethodSubtypeSwitchingController(mSettings);
695d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka        mSwitchingController.resetCircularListLocked(context);
6960a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
6970a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        // Just checking if defaultImiId is empty or not
6984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
699f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (DEBUG) {
700f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "Initial default ime = " + defaultImiId);
701f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
7020a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
7030a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
704f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        buildInputMethodListLocked(mMethodList, mMethodMap,
705f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
706d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        mSettings.enableAllIMEsIfThereIsNoEnabledIME();
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7080a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!mImeSelectedOnBoot) {
7090a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            Slog.w(TAG, "No IME selected. Choose the most applicable IME.");
7105b927c431f54ea47c3333afb7940d79e2e863f1asatok            resetDefaultImeLocked(context);
7115b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7125b927c431f54ea47c3333afb7940d79e2e863f1asatok
7135b927c431f54ea47c3333afb7940d79e2e863f1asatok        mSettingsObserver = new SettingsObserver(mHandler);
714fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        updateFromSettingsLocked(true);
7155b927c431f54ea47c3333afb7940d79e2e863f1asatok
7165b927c431f54ea47c3333afb7940d79e2e863f1asatok        // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
7175b927c431f54ea47c3333afb7940d79e2e863f1asatok        // according to the new system locale.
7185b927c431f54ea47c3333afb7940d79e2e863f1asatok        final IntentFilter filter = new IntentFilter();
7195b927c431f54ea47c3333afb7940d79e2e863f1asatok        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
7205b927c431f54ea47c3333afb7940d79e2e863f1asatok        mContext.registerReceiver(
7215b927c431f54ea47c3333afb7940d79e2e863f1asatok                new BroadcastReceiver() {
7225b927c431f54ea47c3333afb7940d79e2e863f1asatok                    @Override
7235b927c431f54ea47c3333afb7940d79e2e863f1asatok                    public void onReceive(Context context, Intent intent) {
7245b927c431f54ea47c3333afb7940d79e2e863f1asatok                        synchronized(mMethodMap) {
725ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            resetStateIfCurrentLocaleChangedLocked();
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
7285b927c431f54ea47c3333afb7940d79e2e863f1asatok                }, filter);
7295b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7305b927c431f54ea47c3333afb7940d79e2e863f1asatok
7315b927c431f54ea47c3333afb7940d79e2e863f1asatok    private void resetDefaultImeLocked(Context context) {
7325b927c431f54ea47c3333afb7940d79e2e863f1asatok        // Do not reset the default (current) IME when it is a 3rd-party IME
7338e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        if (mCurMethodId != null
7348e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
7355b927c431f54ea47c3333afb7940d79e2e863f1asatok            return;
7365b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7375b927c431f54ea47c3333afb7940d79e2e863f1asatok
7385b927c431f54ea47c3333afb7940d79e2e863f1asatok        InputMethodInfo defIm = null;
7395b927c431f54ea47c3333afb7940d79e2e863f1asatok        for (InputMethodInfo imi : mMethodList) {
7405b927c431f54ea47c3333afb7940d79e2e863f1asatok            if (defIm == null) {
7418e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                if (InputMethodUtils.isValidSystemDefaultIme(
7428e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSystemReady, imi, context)) {
7435b927c431f54ea47c3333afb7940d79e2e863f1asatok                    defIm = imi;
7445b927c431f54ea47c3333afb7940d79e2e863f1asatok                    Slog.i(TAG, "Selected default: " + imi.getId());
7455b927c431f54ea47c3333afb7940d79e2e863f1asatok                }
7469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7475b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7485b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm == null && mMethodList.size() > 0) {
7498e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            defIm = InputMethodUtils.getMostApplicableDefaultIME(
7508e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
7515b927c431f54ea47c3333afb7940d79e2e863f1asatok            Slog.i(TAG, "No default found, using " + defIm.getId());
7525b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7535b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm != null) {
7545b927c431f54ea47c3333afb7940d79e2e863f1asatok            setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
7555b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
7565b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
7575b927c431f54ea47c3333afb7940d79e2e863f1asatok
7587f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka    private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
7597f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            final boolean resetDefaultEnabledIme) {
7604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!mSystemReady) {
7614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // not system ready
7624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
7634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
7644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final Locale newLocale = mRes.getConfiguration().locale;
7654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!updateOnlyWhenLocaleChanged
7664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
7674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                hideCurrentInputLocked(0, null);
7694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurMethodId = null;
7702ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
7714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
7724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
7734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.i(TAG, "Locale has been changed to " + newLocale);
7744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
775d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            // CircularList should be reset when the locale is changed.
776d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            mSwitchingController.resetCircularListLocked(mContext);
7777f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            buildInputMethodListLocked(mMethodList, mMethodMap, resetDefaultEnabledIme);
7784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selectedImiId = mSettings.getSelectedInputMethod();
7804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (TextUtils.isEmpty(selectedImiId)) {
7814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // This is the first time of the user switch and
7824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // set the current ime to the proper one.
7834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    resetDefaultImeLocked(mContext);
7844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
785d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka            } else {
786d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                // If the locale is changed, needs to reset the default ime
787d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                resetDefaultImeLocked(mContext);
7884e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
789fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            updateFromSettingsLocked(true);
7904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            mLastSystemLocale = newLocale;
7914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
7924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                try {
7934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    startInputInnerLocked();
7944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } catch (RuntimeException e) {
7954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    Slog.w(TAG, "Unexpected exception", e);
7964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
7974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
7984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
7994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
801ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka    private void resetStateIfCurrentLocaleChangedLocked() {
8027f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */,
8037f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka                true /* resetDefaultImeLocked */);
8044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8065ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private void switchUserLocked(int newUserId) {
8074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mSettings.setCurrentUserId(newUserId);
8082a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
8095ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        // InputMethodFileManager should be reset when the user is changed
8105ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
8117f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
8127c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // For secondary users, the list of enabled IMEs may not have been updated since the
8137c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // callbacks to PackageMonitor are ignored for the secondary user. Here, defaultImiId may
8147c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // not be empty even if the IME has been uninstalled by the primary user.
8157c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // Even in such cases, IMMS works fine because it will find the most applicable
8167c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // IME for that user.
817ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
8187f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        if (DEBUG) {
8197f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            Slog.d(TAG, "Switch user: " + newUserId + " current ime = " + defaultImiId);
8207f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        }
8217f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(false  /* updateOnlyWhenLocaleChanged */,
822ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                initialUserSwitch /* needsToResetDefaultIme */);
823ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        if (initialUserSwitch) {
824ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka            InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(),
825ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
826ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        }
8274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
8284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8292a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy    void updateCurrentProfileIds() {
8302a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        List<UserInfo> profiles =
8312a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
8322a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
8332a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        for (int i = 0; i < currentProfileIds.length; i++) {
8342a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy            currentProfileIds[i] = profiles.get(i).id;
835734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        }
8362a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        mSettings.setCurrentProfileIds(currentProfileIds);
837734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani    }
838734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws RemoteException {
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.onTransact(code, data, reply, flags);
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The input method manager only throws security exceptions, so let's
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // log all others.
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!(e instanceof SecurityException)) {
848164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf(TAG, "Input Method Manager Crash", e);
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
854a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning(StatusBarManagerService statusBar) {
855a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        synchronized (mMethodMap) {
8564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
8574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "--- systemReady");
8584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
859a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            if (!mSystemReady) {
860a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn                mSystemReady = true;
8614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mKeyguardManager =
8624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
863661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mNotificationManager = (NotificationManager)
864661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
865661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mStatusBar = statusBar;
866661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                statusBar.setIconVisibility("ime", false);
867661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                updateImeWindowStatusLocked();
868b858c732f665fe9610f2d913230ae625f44a8caasatok                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
869b858c732f665fe9610f2d913230ae625f44a8caasatok                        com.android.internal.R.bool.show_ongoing_ime_switcher);
87001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mShowOngoingImeSwitcherForPhones) {
87101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mWindowManagerService.setOnHardKeyboardStatusChangeListener(
87201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mHardKeyboardListener);
87301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
874f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(mMethodList, mMethodMap,
875f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
8760a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (!mImeSelectedOnBoot) {
8770a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                    Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
878ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    resetStateIfCurrentLocaleChangedLocked();
879ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
880ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mContext.getPackageManager(),
881ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mSettings.getEnabledInputMethodListLocked());
8820a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
8830a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                mLastSystemLocale = mRes.getConfiguration().locale;
884cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                try {
885cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    startInputInnerLocked();
886cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                } catch (RuntimeException e) {
8878a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Unexpected exception", e);
888cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
889a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            }
890a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
892ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
89315452a487a4c0274f4217cd060aa54446f30a8f3satok    private void setImeWindowVisibilityStatusHiddenLocked() {
89415452a487a4c0274f4217cd060aa54446f30a8f3satok        mImeWindowVis = 0;
89515452a487a4c0274f4217cd060aa54446f30a8f3satok        updateImeWindowStatusLocked();
89615452a487a4c0274f4217cd060aa54446f30a8f3satok    }
89715452a487a4c0274f4217cd060aa54446f30a8f3satok
8983afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    private void refreshImeWindowVisibilityLocked() {
8993afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final Configuration conf = mRes.getConfiguration();
9003afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean haveHardKeyboard = conf.keyboard
9013afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                != Configuration.KEYBOARD_NOKEYS;
9023afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        final boolean hardKeyShown = haveHardKeyboard
9033afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                && conf.hardKeyboardHidden
9043afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok                        != Configuration.HARDKEYBOARDHIDDEN_YES;
905e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
906e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean isScreenLocked = isKeyguardLocked();
907e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        final boolean inputActive = !isScreenLocked && (mInputShown || hardKeyShown);
90836439b43121751ae94e703da52b2763aa17d0720John Spurlock        // We assume the softkeyboard is shown when the input is active as long as the
90936439b43121751ae94e703da52b2763aa17d0720John Spurlock        // hard keyboard is not shown.
91036439b43121751ae94e703da52b2763aa17d0720John Spurlock        final boolean inputVisible = inputActive && !hardKeyShown;
91136439b43121751ae94e703da52b2763aa17d0720John Spurlock        mImeWindowVis = (inputActive ? InputMethodService.IME_ACTIVE : 0)
91236439b43121751ae94e703da52b2763aa17d0720John Spurlock                | (inputVisible ? InputMethodService.IME_VISIBLE : 0);
9133afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok        updateImeWindowStatusLocked();
9143afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok    }
9153afd6c0d4d5c2c80cf0450941babaee32ec9c7eesatok
91615452a487a4c0274f4217cd060aa54446f30a8f3satok    private void updateImeWindowStatusLocked() {
917dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok        setImeWindowStatus(mCurToken, mImeWindowVis, mBackDisposition);
918661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    }
919661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn
9204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // ---------------------------------------------------------------------------------------
9214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
9224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 1) it comes from the system process
9234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 2) the calling process' user id is identical to the current user id IMMS thinks.
9244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean calledFromValidUser() {
9254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int uid = Binder.getCallingUid();
9264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int userId = UserHandle.getUserId(uid);
9274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
9284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
9294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
9304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + " calling userId = " + userId + ", foreground user id = "
93187c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
93287c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + InputMethodUtils.getApiCallStack());
9334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9342a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
9354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return true;
9364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
937135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka
938135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
939135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // foreground user, not for the user of that process. Accordingly InputMethodManagerService
940135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // must not manage background users' states in any functions.
941135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Note that privacy-sensitive IPCs, such as setInputMethod, are still securely guarded
942135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // by a token.
943135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        if (mContext.checkCallingOrSelfPermission(
944135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
945135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        == PackageManager.PERMISSION_GRANTED) {
946135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            if (DEBUG) {
947135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                Slog.d(TAG, "--- Access granted because the calling process has "
948135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        + "the INTERACT_ACROSS_USERS_FULL permission");
949135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            }
950135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            return true;
951135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        }
9520766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka        Slog.w(TAG, "--- IPC called from background users. Ignore. \n"
9530766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                + InputMethodUtils.getStackTrace());
954135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        return false;
9554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
9574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean bindCurrentInputMethodService(
9584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Intent service, ServiceConnection conn, int flags) {
9594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (service == null || conn == null) {
9604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
9614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
9624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
96327b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani        return mContext.bindServiceAsUser(service, conn, flags,
96427b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                new UserHandle(mSettings.getCurrentUserId()));
9654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
967e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
9689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getInputMethodList() {
9694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
9704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
9714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
9724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
9749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ArrayList<InputMethodInfo>(mMethodList);
9759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
978e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getEnabledInputMethodList() {
9804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
9814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
9824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
9834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
985d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return mSettings.getEnabledInputMethodListLocked();
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9898e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    /**
990b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka     * @param imiId if null, returns enabled subtypes for the current imi
9918e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     * @return enabled subtypes of the specified imi
9928e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     */
993e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
994b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
99516331c8a1d33defccc5cbb18694def79196c921bsatok            boolean allowsImplicitlySelectedSubtypes) {
9964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
9974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
998b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            return Collections.<InputMethodSubtype>emptyList();
9994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
100067ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        synchronized (mMethodMap) {
1001b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            final InputMethodInfo imi;
1002b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imiId == null && mCurMethodId != null) {
10038e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                imi = mMethodMap.get(mCurMethodId);
1004b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            } else {
1005b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                imi = mMethodMap.get(imiId);
1006b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            }
1007b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imi == null) {
1008b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                return Collections.<InputMethodSubtype>emptyList();
10098e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            }
10108e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            return mSettings.getEnabledInputMethodSubtypeListLocked(
10118e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mContext, imi, allowsImplicitlySelectedSubtypes);
101267ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        }
101367ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok    }
101467ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok
1015e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addClient(IInputMethodClient client,
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IInputContext inputContext, int uid, int pid) {
10184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClients.put(client.asBinder(), new ClientState(client,
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    inputContext, uid, pid));
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1026ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1027e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
10289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeClient(IInputMethodClient client) {
10294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
10304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
10314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1033c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ClientState cs = mClients.remove(client.asBinder());
1034c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (cs != null) {
1035c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
1036c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1039ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void executeOrSendMessage(IInterface target, Message msg) {
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         if (target.asBinder() instanceof Binder) {
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             mCaller.sendMessage(msg);
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         } else {
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             handleMessage(msg);
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             msg.recycle();
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         }
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1048ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1049b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void unbindCurrentClientLocked() {
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != null) {
10518a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client = "
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurClient.client.asBinder());
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBoundToMethod) {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBoundToMethod = false;
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_INPUT, mCurMethod));
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1060a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn
1061a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1062a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    MSG_SET_ACTIVE, 0, mCurClient));
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient.sessionRequested = false;
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient = null;
1067ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1068105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1071ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getImeShowFlags() {
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_FORCED
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    | InputMethod.SHOW_EXPLICIT;
10779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mShowExplicitlyRequested) {
10789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_EXPLICIT;
10799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1082ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getAppShowFlags() {
10849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
10859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
10869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_FORCED;
10879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mShowExplicitlyRequested) {
10889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_IMPLICIT;
10899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
10919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1092ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10937663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult attachNewInputLocked(boolean initial) {
10949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBoundToMethod) {
10959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
10969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
10979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBoundToMethod = true;
10989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SessionState session = mCurClient.curSession;
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initial) {
11019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_START_INPUT, session, mCurInputContext, mCurAttribute));
11039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
11059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_RESTART_INPUT, session, mCurInputContext, mCurAttribute));
11069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowRequested) {
11088a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
11094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            showCurrentInputLocked(getAppShowFlags(), null);
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11111951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown        return new InputBindResult(session.session,
11121951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                session.channel != null ? session.channel.dup() : null, mCurId, mCurSeq);
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1114ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBindResult startInputLocked(IInputMethodClient client,
11167663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If no method is currently selected, do nothing.
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethodId == null) {
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNoBinding;
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1121ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState cs = mClients.get(client.asBinder());
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cs == null) {
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("unknown client "
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + client.asBinder());
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1127ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check with the window manager to make sure this client actually
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // has a window with focus.  If not, reject.  This is thread safe
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // because if the focus changes some time before or after, the
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // next client receiving focus that has any interest in input will
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // be calling through here after that change happens.
11358a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Starting input on non-focused client " + cs.client
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
11409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1141ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11427663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
11437663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    }
11447663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11457663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult startInputUncheckedLocked(ClientState cs,
11467663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
11477663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        // If no method is currently selected, do nothing.
11487663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        if (mCurMethodId == null) {
11497663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            return mNoBinding;
11507663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        }
11517663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != cs) {
1153e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            // Was the keyguard locked when switching over to the new client?
1154e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            mCurClientInKeyguard = isKeyguardLocked();
11559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the client is changing, we need to switch over to the new
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // one.
1157b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
11588a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "switching to client: client = "
1159e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
11609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the screen is on, inform the new client it is active
11629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mScreenOn) {
1163a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                executeOrSendMessage(cs.client, mCaller.obtainMessageIO(
1164a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, cs));
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1167ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Bump up the sequence for this client and attach it.
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurSeq++;
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurSeq <= 0) mCurSeq = 1;
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurClient = cs;
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurInputContext = inputContext;
11739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurAttribute = attribute;
1174ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check if the input method is changing.
11769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurId != null && mCurId.equals(mCurMethodId)) {
11779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cs.curSession != null) {
11789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Fast case: if we are already connected to the input method,
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // then just return it.
11807663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return attachNewInputLocked(
11817663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mHaveConnection) {
11849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
11859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Return to client, and we will get back with it when
11869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we have had a session made for it.
1187c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(cs);
1188c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return new InputBindResult(null, null, mCurId, mCurSeq);
11899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (SystemClock.uptimeMillis()
11909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        < (mLastBindTime+TIME_TO_RECONNECT)) {
11919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // In this case we have connected to the service, but
11929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // don't yet have its interface.  If it hasn't been too
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // long since we did the connection, we'll return to
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the client and wait to get the service interface so
11959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we can report back.  If it has been too long, we want
11969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to fall through so we can try a disconnect/reconnect
11979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to see if we can get back in touch with the service.
1198c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return new InputBindResult(null, null, mCurId, mCurSeq);
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1200ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                    EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
1201ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                            mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1205ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1206a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        return startInputInnerLocked();
1207a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    }
1208ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1209a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    InputBindResult startInputInnerLocked() {
1210a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (mCurMethodId == null) {
1211a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            return mNoBinding;
1212a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1213ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1214a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (!mSystemReady) {
1215a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // If the system is not yet ready, we shouldn't be running third
1216a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // party code.
1217c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return new InputBindResult(null, null, mCurMethodId, mCurSeq);
1218a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1219ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(mCurMethodId);
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1224ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12252ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn        unbindCurrentMethodLocked(false, true);
1226ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
12289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent.setComponent(info.getComponent());
1229dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1230dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                com.android.internal.R.string.input_method_binding_label);
1231dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1232dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
12334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
1234f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND
1235f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_SHOWING_UI)) {
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastBindTime = SystemClock.uptimeMillis();
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHaveConnection = true;
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurId = info.getId();
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurToken = new Binder();
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
1241ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIWindowManager.addWindowToken(mCurToken,
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
12449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1246c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            return new InputBindResult(null, null, mCurId, mCurSeq);
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIntent = null;
12498a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Failure connecting to input method service: "
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurIntent);
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1254ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1255e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBindResult startInput(IInputMethodClient client,
12577663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
12584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
12594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
12604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final long ident = Binder.clearCallingIdentity();
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
12647663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return startInputLocked(client, inputContext, attribute, controlFlags);
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1270ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1271e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishInput(IInputMethodClient client) {
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1274ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1275e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceConnected(ComponentName name, IBinder service) {
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCurMethod = IInputMethod.Stub.asInterface(service);
1280cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                if (mCurToken == null) {
12818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Service connected without a token!");
12822ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                    unbindCurrentMethodLocked(false, false);
1283cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    return;
1284cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1285e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
1286cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
1287cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
12889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1289c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
1290c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(mCurClient);
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1296c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void onSessionCreated(IInputMethod method, IInputMethodSession session,
1297c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel channel) {
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && method != null
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && mCurMethod.asBinder() == method.asBinder()) {
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1302c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCurClient.curSession = new SessionState(mCurClient,
1304c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                            method, session, channel);
13057663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    InputBindResult res = attachNewInputLocked(true);
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (res.method != null) {
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                MSG_BIND_METHOD, mCurClient.client, res));
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1310c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return;
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1314c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1315c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        // Session abandoned.  Close its associated input channel.
1316c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        channel.dispose();
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1318ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13192ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn    void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
13202c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mVisibleBound) {
13212c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
13222c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
13232c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
13242c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1325b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mHaveConnection) {
1326b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mContext.unbindService(this);
1327b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mHaveConnection = false;
1328b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1329ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1330b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mCurToken != null) {
1331b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            try {
13328a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
13332ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
1334e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    // The current IME is shown. Hence an IME switch (transition) is happening.
1335e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    mWindowManagerService.saveLastInputMethodWindowForTransition();
1336e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                }
1337b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mIWindowManager.removeWindowToken(mCurToken);
1338b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            } catch (RemoteException e) {
1339b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
1340b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mCurToken = null;
1341b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1342ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1343105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mCurId = null;
1344b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        clearCurMethodLocked();
1345ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1346b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (reportToClient && mCurClient != null) {
1347b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1348b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
1349b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1350b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    }
1351c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1352c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void requestClientSessionLocked(ClientState cs) {
1353c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (!cs.sessionRequested) {
1354c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
1355c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
1356c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            cs.sessionRequested = true;
1357c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
1358c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    MSG_CREATE_SESSION, mCurMethod, channels[1],
1359c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    new MethodCallback(this, mCurMethod, channels[0])));
1360c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
1361c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1362c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1363c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void clearClientSessionLocked(ClientState cs) {
1364c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        finishSessionLocked(cs.curSession);
1365c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.curSession = null;
1366c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.sessionRequested = false;
1367c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1368c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1369c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private void finishSessionLocked(SessionState sessionState) {
1370c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (sessionState != null) {
1371c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.session != null) {
1372c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                try {
1373c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    sessionState.session.finishSession();
1374c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } catch (RemoteException e) {
1375c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    Slog.w(TAG, "Session failed to close due to remote exception", e);
1376c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    setImeWindowVisibilityStatusHiddenLocked();
1377c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
1378c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.session = null;
1379c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
1380c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.channel != null) {
1381c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel.dispose();
1382c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel = null;
13830c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            }
13840c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor        }
13850c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor    }
1386ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1387b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void clearCurMethodLocked() {
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState cs : mClients.values()) {
1390c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13920c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor
1393c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            finishSessionLocked(mEnabledSession);
13940c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            mEnabledSession = null;
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurMethod = null;
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1397661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        if (mStatusBar != null) {
1398661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn            mStatusBar.setIconVisibility("ime", false);
1399661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        }
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1401ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1402e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceDisconnected(ComponentName name) {
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14058a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
14069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mCurIntent=" + mCurIntent);
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && mCurIntent != null
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && name.equals(mCurIntent.getComponent())) {
1409b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                clearCurMethodLocked();
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We consider this to be a new bind attempt, since the system
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // should now try to restart the service for us.
14129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastBindTime = SystemClock.uptimeMillis();
14139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mShowRequested = mInputShown;
14149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputShown = false;
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
14179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
14189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1423f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
1425cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (token == null || mCurToken != token) {
1429cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                Slog.w(TAG, "Ignoring setInputMethod of uid " + uid + " token: " + token);
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1432ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (iconId == 0) {
14358a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
1436661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1437661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", false);
1438661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (packageName != null) {
14408a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
14416179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    CharSequence contentDescription = null;
14426179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    try {
14434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        // Use PackageManager to load label
14444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        final PackageManager packageManager = mContext.getPackageManager();
14456179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        contentDescription = packageManager.getApplicationLabel(
14464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mIPackageManager.getApplicationInfo(packageName, 0,
14474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                        mSettings.getCurrentUserId()));
14484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    } catch (RemoteException e) {
14496179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        /* ignore */
14506179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    }
1451661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1452661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIcon("ime", packageName, iconId, 0,
1453661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                contentDescription  != null
1454661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                        ? contentDescription.toString() : null);
1455661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", true);
1456661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
14647cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean needsToShowImeSwitchOngoingNotification() {
14657cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        if (!mShowOngoingImeSwitcherForPhones) return false;
14662c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        if (isScreenLocked()) return false;
14677cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        synchronized (mMethodMap) {
14687cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
14697cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            final int N = imis.size();
1470b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N > 2) return true;
1471b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (N < 1) return false;
1472b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int nonAuxCount = 0;
1473b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            int auxCount = 0;
1474b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype nonAuxSubtype = null;
1475b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            InputMethodSubtype auxSubtype = null;
14767cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            for(int i = 0; i < N; ++i) {
14777cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final InputMethodInfo imi = imis.get(i);
14788e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final List<InputMethodSubtype> subtypes =
14798e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
14807cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                final int subtypeCount = subtypes.size();
14817cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                if (subtypeCount == 0) {
1482b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    ++nonAuxCount;
14837cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
14847cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    for (int j = 0; j < subtypeCount; ++j) {
1485b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        final InputMethodSubtype subtype = subtypes.get(j);
1486b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        if (!subtype.isAuxiliary()) {
1487b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++nonAuxCount;
1488b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            nonAuxSubtype = subtype;
1489b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        } else {
1490b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            ++auxCount;
1491b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                            auxSubtype = subtype;
14927cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        }
14937cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
14947cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
14957cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            }
1496b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            if (nonAuxCount > 1 || auxCount > 1) {
1497b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1498b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            } else if (nonAuxCount == 1 && auxCount == 1) {
1499b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                if (nonAuxSubtype != null && auxSubtype != null
15009747f8977c55013e656a1e666a1647bb331954cesatok                        && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
15019747f8977c55013e656a1e666a1647bb331954cesatok                                || auxSubtype.overridesImplicitlyEnabledSubtype()
15029747f8977c55013e656a1e666a1647bb331954cesatok                                || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
1503b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                        && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
1504b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                    return false;
1505b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                }
1506b6359414adabab2d64acc8ccc9e3b9c1b800b303satok                return true;
1507b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            }
1508b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            return false;
15097cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        }
15107cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    }
15117cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
1512e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean isKeyguardLocked() {
1513e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
1514e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    }
1515e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
15164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Caution! This method is called in this class. Handle multi-user carefully
1517dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("deprecation")
1518f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
1519857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
15204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final long ident = Binder.clearCallingIdentity();
152106487a58be22b100daf3f950b9a1d25c3ea42aa2satok        try {
152206487a58be22b100daf3f950b9a1d25c3ea42aa2satok            if (token == null || mCurToken != token) {
15234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                int uid = Binder.getCallingUid();
1524857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                Slog.w(TAG, "Ignoring setImeWindowStatus of uid " + uid + " token: " + token);
152506487a58be22b100daf3f950b9a1d25c3ea42aa2satok                return;
152606487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
152706487a58be22b100daf3f950b9a1d25c3ea42aa2satok            synchronized (mMethodMap) {
1528e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                // apply policy for binder calls
1529e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
1530e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    vis = 0;
1531e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                }
1532857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mImeWindowVis = vis;
1533857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato                mBackDisposition = backDisposition;
1534661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                if (mStatusBar != null) {
1535661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    mStatusBar.setImeWindowStatus(token, vis, backDisposition);
1536661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                }
1537217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                final boolean iconVisibility = ((vis & (InputMethodService.IME_ACTIVE)) != 0)
1538217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                        && (mWindowManagerService.isHardKeyboardAvailable()
1539217fd2903d09d40cabcdade9f2a162dc6513f800jungheang.lee                                || (vis & (InputMethodService.IME_VISIBLE)) != 0);
15405bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
15415bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                if (imi != null && iconVisibility && needsToShowImeSwitchOngoingNotification()) {
15424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // Used to load label
15437cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    final CharSequence title = mRes.getText(
15447cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                            com.android.internal.R.string.select_input_method);
1545b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                    final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
1546b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            mContext, imi, mCurrentSubtype);
15475bc8e732bd831a308a5bc1720b0e4c9300d32f67satok
15487cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    mImeSwitcherNotification.setLatestEventInfo(
15495bc8e732bd831a308a5bc1720b0e4c9300d32f67satok                            mContext, title, summary, mImeSwitchPendingIntent);
1550661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mNotificationManager != null) {
1551135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1552b282726d8604dad3ac06e9d8bf167f19332a05d7Satoshi Kataoka                            Slog.d(TAG, "--- show notification: label =  " + summary);
1553135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1554135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.notifyAsUser(null,
1555661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                com.android.internal.R.string.select_input_method,
1556135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                mImeSwitcherNotification, UserHandle.ALL);
1557661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mNotificationShown = true;
1558661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
15597cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                } else {
1560661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mNotificationShown && mNotificationManager != null) {
1561135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        if (DEBUG) {
1562135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                            Slog.d(TAG, "--- hide notification");
1563135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        }
1564135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        mNotificationManager.cancelAsUser(null,
1565135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                                com.android.internal.R.string.select_input_method, UserHandle.ALL);
15667cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                        mNotificationShown = false;
15677cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
15687cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
156906487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
157006487a58be22b100daf3f950b9a1d25c3ea42aa2satok        } finally {
157106487a58be22b100daf3f950b9a1d25c3ea42aa2satok            Binder.restoreCallingIdentity(ident);
157206487a58be22b100daf3f950b9a1d25c3ea42aa2satok        }
157306487a58be22b100daf3f950b9a1d25c3ea42aa2satok    }
157406487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1575e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1576f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
15774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
15784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
15794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1580f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1581f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
1582f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            for (int i = 0; i < spans.length; ++i) {
1583f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                SuggestionSpan ss = spans[i];
158442c5a1666c4e576ccd5974233513100aad2c1534satok                if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
1585f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                    mSecureSuggestionSpans.put(ss, currentImi);
1586f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                }
1587f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1588f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1589f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1590f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1591e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1592f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
15934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
15944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
15954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1596f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1597f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
1598f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            // TODO: Do not send the intent if the process of the targetImi is already dead.
1599f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            if (targetImi != null) {
1600f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final String[] suggestions = span.getSuggestions();
1601f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                if (index < 0 || index >= suggestions.length) return false;
160242c5a1666c4e576ccd5974233513100aad2c1534satok                final String className = span.getNotificationTargetClassName();
1603f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final Intent intent = new Intent();
1604f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // Ensures that only a class in the original IME package will receive the
1605f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // notification.
160642c5a1666c4e576ccd5974233513100aad2c1534satok                intent.setClassName(targetImi.getPackageName(), className);
1607f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
1608f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
1609f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
1610f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
1611f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                final long ident = Binder.clearCallingIdentity();
1612f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                try {
1613f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
1614f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                } finally {
1615f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    Binder.restoreCallingIdentity(ident);
1616f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                }
1617f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                return true;
1618f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1619f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1620f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        return false;
1621f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1622f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1623fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn    void updateFromSettingsLocked(boolean enabledMayChange) {
1624fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        if (enabledMayChange) {
1625fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
1626fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            for (int i=0; i<enabled.size(); i++) {
1627fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // We allow the user to select "disabled until used" apps, so if they
1628fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // are enabling one of those here we now need to make it enabled.
1629fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                InputMethodInfo imm = enabled.get(i);
1630fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                try {
1631fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
1632fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
1633fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            mSettings.getCurrentUserId());
16347987a3172b0502ea70a26d80e7cd16ca7e460035Satoshi Kataoka                    if (ai != null && ai.enabledSetting
1635fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
1636ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        if (DEBUG) {
1637ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            Slog.d(TAG, "Update state(" + imm.getId()
1638ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                                    + "): DISABLED_UNTIL_USED -> DEFAULT");
1639ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        }
1640fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
1641fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
16423fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(),
16433fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                mContext.getBasePackageName());
1644fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    }
1645fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                } catch (RemoteException e) {
1646fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
1647fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            }
1648fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        }
1649b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
1650b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
1651b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
1652b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // enabled.
16534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String id = mSettings.getSelectedInputMethod();
165403eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        // There is no input method selected, try to choose new applicable input method.
165503eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
16564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            id = mSettings.getSelectedInputMethod();
165703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        }
165803eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (!TextUtils.isEmpty(id)) {
16599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
16608e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
16619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException e) {
16628a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unknown input method from prefs: " + id, e);
1663105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mCurMethodId = null;
16642ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1666f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.clear();
1667b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        } else {
1668b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            // There is no longer an input method set, so stop any current one.
1669105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCurMethodId = null;
16702ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn            unbindCurrentMethodLocked(true, false);
16719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1673ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1674ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /* package */ void setInputMethodLocked(String id, int subtypeId) {
16759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(id);
16769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
1677913a8925c07e854a80bf5df87561f290d3a56d61satok            throw new IllegalArgumentException("Unknown id: " + id);
16789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1679ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1680d81e950265356c81276b73da68a535ffa48d72f0satok        // See if we need to notify a subtype change within the same IME.
16819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.equals(mCurMethodId)) {
1682d81e950265356c81276b73da68a535ffa48d72f0satok            final int subtypeCount = info.getSubtypeCount();
1683d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeCount <= 0) {
1684d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1685d81e950265356c81276b73da68a535ffa48d72f0satok            }
1686d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype oldSubtype = mCurrentSubtype;
1687d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype newSubtype;
1688d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeId >= 0 && subtypeId < subtypeCount) {
1689d81e950265356c81276b73da68a535ffa48d72f0satok                newSubtype = info.getSubtypeAt(subtypeId);
1690d81e950265356c81276b73da68a535ffa48d72f0satok            } else {
1691d81e950265356c81276b73da68a535ffa48d72f0satok                // If subtype is null, try to find the most applicable one from
1692d81e950265356c81276b73da68a535ffa48d72f0satok                // getCurrentInputMethodSubtype.
16934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                newSubtype = getCurrentInputMethodSubtypeLocked();
1694d81e950265356c81276b73da68a535ffa48d72f0satok            }
1695d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype == null || oldSubtype == null) {
1696d81e950265356c81276b73da68a535ffa48d72f0satok                Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
1697d81e950265356c81276b73da68a535ffa48d72f0satok                        + ", new subtype = " + newSubtype);
1698d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1699d81e950265356c81276b73da68a535ffa48d72f0satok            }
1700d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype != oldSubtype) {
1701d81e950265356c81276b73da68a535ffa48d72f0satok                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
1702d81e950265356c81276b73da68a535ffa48d72f0satok                if (mCurMethod != null) {
1703d81e950265356c81276b73da68a535ffa48d72f0satok                    try {
1704d81e950265356c81276b73da68a535ffa48d72f0satok                        refreshImeWindowVisibilityLocked();
1705d81e950265356c81276b73da68a535ffa48d72f0satok                        mCurMethod.changeInputMethodSubtype(newSubtype);
1706d81e950265356c81276b73da68a535ffa48d72f0satok                    } catch (RemoteException e) {
1707d81e950265356c81276b73da68a535ffa48d72f0satok                        Slog.w(TAG, "Failed to call changeInputMethodSubtype");
1708ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
1709ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                }
1710ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            }
17119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
17129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1713ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1714d81e950265356c81276b73da68a535ffa48d72f0satok        // Changing to a different IME.
17159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long ident = Binder.clearCallingIdentity();
17169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1717ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // Set a subtype to this input method.
1718ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // subtypeId the name of a subtype which will be set.
1719723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
1720723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
1721723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // because mCurMethodId is stored as a history in
1722723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // setSelectedInputMethodAndSubtypeLocked().
1723723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mCurMethodId = id;
17249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
17259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ActivityManagerNative.isSystemReady()) {
17269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
17271c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
17289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.putExtra("input_method_id", id);
1729cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani                mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
17309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1731b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
17329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
17339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
17349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1736ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
173742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
17384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean showSoftInput(IInputMethodClient client, int flags,
17394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
17404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
17414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
17424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1743cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
17449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
17459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
17469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
17479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
17489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
17499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
17509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
17519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
17529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
17539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1754cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
17554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
17569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
17579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
17584df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
17599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
17609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1761ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1762e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
17634df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return showCurrentInputLocked(flags, resultReceiver);
17649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
17659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
17669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
17679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1769ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
17704df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
17719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = true;
17729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
17739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
17749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
17759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
17769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
17779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowForced = true;
17789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1779ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1780cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        if (!mSystemReady) {
1781cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            return false;
1782cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        }
1783ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
17844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res = false;
17859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
1786e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
17874df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
17884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
17894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    resultReceiver));
17909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputShown = true;
17912c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            if (mHaveConnection && !mVisibleBound) {
17924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                bindCurrentInputMethodService(
1793f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                        mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
1794f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                                | Context.BIND_TREAT_LIKE_ACTIVITY);
17952c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                mVisibleBound = true;
17962c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            }
17974df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
17989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mHaveConnection && SystemClock.uptimeMillis()
179959b424c3b6121c9579fc5efcc785ba084072a5casatok                >= (mLastBindTime+TIME_TO_RECONNECT)) {
18009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The client has asked to have the input method shown, but
18019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we have been sitting here too long with a connection to the
18029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // service and no interface received, so let's disconnect/connect
18039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to try to prod things along.
1804ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,
18059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemClock.uptimeMillis()-mLastBindTime,1);
180659b424c3b6121c9579fc5efcc785ba084072a5casatok            Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
18079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.unbindService(this);
18084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
18092c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                    | Context.BIND_NOT_VISIBLE);
18104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } else {
18114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
18124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
18134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
18144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
18159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1816ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18174df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
18189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1819ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
182042c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
18214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean hideSoftInput(IInputMethodClient client, int flags,
18224df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
18234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
18244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
18254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1826cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
18279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
18289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
18309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
18319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
18329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
18339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
18349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
18359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
18369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
1837cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
1838cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                                    + uid + ": " + client);
183915452a487a4c0274f4217cd060aa54446f30a8f3satok                            setImeWindowVisibilityStatusHiddenLocked();
18404df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
18419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
18429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
184315452a487a4c0274f4217cd060aa54446f30a8f3satok                        setImeWindowVisibilityStatusHiddenLocked();
18444df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
18459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
18469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1847ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18488a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
18494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return hideCurrentInputLocked(flags, resultReceiver);
18509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
18519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
18529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
18539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1855ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
18564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
18579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
18589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mShowExplicitlyRequested || mShowForced)) {
1859e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
18604df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
18619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
1863e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
18644df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
18659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18664df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res;
18679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInputShown && mCurMethod != null) {
18684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
18694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
18704df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
18714df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
18724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = false;
18739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18742c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mHaveConnection && mVisibleBound) {
18752c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
18762c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
18772c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
18789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputShown = false;
18799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = false;
18809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowExplicitlyRequested = false;
18819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowForced = false;
18824df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
18839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1884ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
188542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
18867663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
18877663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            int controlFlags, int softInputMode, int windowFlags,
18887663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            EditorInfo attribute, IInputContext inputContext) {
18898d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        // Needs to check the validity before clearing calling identity
18908d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        final boolean calledFromValidUser = calledFromValidUser();
18918d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
18927663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        InputBindResult res = null;
18939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
18949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
18959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
18968a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
18977663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " controlFlags=#" + Integer.toHexString(controlFlags)
18989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " softInputMode=#" + Integer.toHexString(softInputMode)
18997663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " windowFlags=#" + Integer.toHexString(windowFlags));
1900ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19017663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                ClientState cs = mClients.get(client.asBinder());
19027663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (cs == null) {
19037663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    throw new IllegalArgumentException("unknown client "
19047663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            + client.asBinder());
19057663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
19067663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
19077663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                try {
19087663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
19097663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // Check with the window manager to make sure this client actually
19107663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // has a window with focus.  If not, reject.  This is thread safe
19117663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // because if the focus changes some time before or after, the
19127663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // next client receiving focus that has any interest in input will
19137663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // be calling through here after that change happens.
19147663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        Slog.w(TAG, "Focus gain on non-focused client " + cs.client
19157663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
19167663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return null;
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
19187663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                } catch (RemoteException e) {
19199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
1920ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19218d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                if (!calledFromValidUser) {
19228d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "A background user is requesting window. Hiding IME.");
19238d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "If you want to interect with IME, you need "
19248d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                            + "android.permission.INTERACT_ACROSS_USERS_FULL");
19258d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    hideCurrentInputLocked(0, null);
19268d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    return null;
19278d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                }
19288d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
1929b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                if (mCurFocusedWindow == windowToken) {
1930ac92087a9a1c464d4b0a58c82dae01cbaa088e89Dianne Hackborn                    Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
19313573950e0b30178dc963de3fa00aba2ebcfd552dSatoshi Kataoka                            + " attribute=" + attribute + ", token = " + windowToken);
19327663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (attribute != null) {
19337663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return startInputUncheckedLocked(cs, inputContext, attribute,
19347663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                controlFlags);
19357663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    }
19367663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    return null;
1937b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
1938b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mCurFocusedWindow = windowToken;
1939ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
19407d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // Should we auto-show the IME even if the caller has not
19417d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // specified what should be done with it?
19427d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // We only do this automatically if the window can resize
19437d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // to accommodate the IME (so what the user sees will give
19447d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // them good context without input information being obscured
19457d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // by the IME) or if running on a large screen where there
19467d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // is more room for the target window + IME.
19477d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                final boolean doAutoShow =
19487d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
19497d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
19507d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        || mRes.getConfiguration().isLayoutSizeAtLeast(
19517d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                Configuration.SCREENLAYOUT_SIZE_LARGE);
19527663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                final boolean isTextEditor =
19537663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0;
19547663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
19557663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // We want to start input before showing the IME, but after closing
19567663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // it.  We want to do this after closing it to help the IME disappear
19577663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // more quickly (not get stuck behind it initializing itself for the
19587663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // new focused input, even if its window wants to hide the IME).
19597663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                boolean didStart = false;
19607d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
19637d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        if (!isTextEditor || !doAutoShow) {
19649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // There is no focus view, and this window will
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // be behind any soft input window, so hide the
19679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // soft input window if it is shown.
19688a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
19694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
19709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
19717d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        } else if (isTextEditor && doAutoShow && (softInputMode &
19727d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
19739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // There is a focus view, and we are navigating forward
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // into the window, so show the input window for the user.
19757663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // We only do this automatically if the window can resize
19767663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // to accommodate the IME (so what the user sees will give
19777d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // them good context without input information being obscured
19787d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // by the IME) or if running on a large screen where there
19797d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // is more room for the target window + IME.
19808a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
19817663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
19827663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
19837663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
19847663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
19857663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
19864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
19879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
19889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
19899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
19909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Do nothing.
19919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
19958a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
19964df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            hideCurrentInputLocked(0, null);
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
20008a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to hide input");
20014df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        hideCurrentInputLocked(0, null);
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
20049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
20059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
20068a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
20077663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
20087663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
20097663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
20107663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
20117663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
20124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
20168a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to always show input");
20177663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        if (attribute != null) {
20187663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            res = startInputUncheckedLocked(cs, inputContext, attribute,
20197663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                    controlFlags);
20207663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            didStart = true;
20217663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        }
20224df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
20257663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20267663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (!didStart && attribute != null) {
20277663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    res = startInputUncheckedLocked(cs, inputContext, attribute,
20287663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            controlFlags);
20297663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
20309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20347663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
20357663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return res;
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2037ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
203842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void showInputMethodPickerFromClient(IInputMethodClient client) {
20404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurClient == null || client == null
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || mCurClient.client.asBinder() != client.asBinder()) {
204647a44916e2fb33cf4751906386d5f5c903b28d8bsatok                Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
2047cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + ": " + client);
20489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2050440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // Always call subtype picker, because subtype picker is a superset of input method
2051440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // picker.
2052ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mHandler.sendEmptyMessage(MSG_SHOW_IM_SUBTYPE_PICKER);
2053ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2054ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2055ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
205642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethod(IBinder token, String id) {
20584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20612820351489537698ad153c6397edf3270455edc5satok        setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
20622820351489537698ad153c6397edf3270455edc5satok    }
20632820351489537698ad153c6397edf3270455edc5satok
206442c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20652820351489537698ad153c6397edf3270455edc5satok    public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
20664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
20692820351489537698ad153c6397edf3270455edc5satok        synchronized (mMethodMap) {
20702820351489537698ad153c6397edf3270455edc5satok            if (subtype != null) {
20718e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodWithSubtypeId(token, id, InputMethodUtils.getSubtypeIdFromHashCode(
20722820351489537698ad153c6397edf3270455edc5satok                        mMethodMap.get(id), subtype.hashCode()));
20732820351489537698ad153c6397edf3270455edc5satok            } else {
20742820351489537698ad153c6397edf3270455edc5satok                setInputMethod(token, id);
20752820351489537698ad153c6397edf3270455edc5satok            }
20762820351489537698ad153c6397edf3270455edc5satok        }
2077ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2078ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
207942c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
2080b416a71e56cdd50742eb897366a140775aa4cd61satok    public void showInputMethodAndSubtypeEnablerFromClient(
2081217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            IInputMethodClient client, String inputMethodId) {
20824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
20844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2085b416a71e56cdd50742eb897366a140775aa4cd61satok        synchronized (mMethodMap) {
2086b416a71e56cdd50742eb897366a140775aa4cd61satok            if (mCurClient == null || client == null
2087b416a71e56cdd50742eb897366a140775aa4cd61satok                || mCurClient.client.asBinder() != client.asBinder()) {
2088b416a71e56cdd50742eb897366a140775aa4cd61satok                Slog.w(TAG, "Ignoring showInputMethodAndSubtypeEnablerFromClient of: " + client);
2089b416a71e56cdd50742eb897366a140775aa4cd61satok            }
20907fee71f66afef6421b92fa48e63d4bc73f5d0c27satok            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
20917fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                    MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
2092b416a71e56cdd50742eb897366a140775aa4cd61satok        }
2093b416a71e56cdd50742eb897366a140775aa4cd61satok    }
2094b416a71e56cdd50742eb897366a140775aa4cd61satok
20954fc87d61c29886c848789208c9e32ba9ac4e5dd3satok    @Override
2096735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    public boolean switchToLastInputMethod(IBinder token) {
20974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
20994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2100735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        synchronized (mMethodMap) {
2101c445bcd0bce630948ee029d7c70b28226f0b6c9csatok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
21024fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            final InputMethodInfo lastImi;
2103208d5634047111811de16fb63c43d0bc8b4fe6desatok            if (lastIme != null) {
21044fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = mMethodMap.get(lastIme.first);
21054fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
21064fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = null;
21074fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
21084fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            String targetLastImiId = null;
21094fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            int subtypeId = NOT_A_SUBTYPE_ID;
21104fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (lastIme != null && lastImi != null) {
21114fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
21124fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
21134fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
21144fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        : mCurrentSubtype.hashCode();
21154fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // If the last IME is the same as the current IME and the last subtype is not
21164fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // defined, there is no need to switch to the last IME.
21174fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
21184fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    targetLastImiId = lastIme.first;
21198e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
21204fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
21214fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
21224fc87d61c29886c848789208c9e32ba9ac4e5dd3satok
21238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            if (TextUtils.isEmpty(targetLastImiId)
21248e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    && !InputMethodUtils.canAddToLastInputMethod(mCurrentSubtype)) {
21254fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // This is a safety net. If the currentSubtype can't be added to the history
21264fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // and the framework couldn't find the last ime, we will make the last ime be
21274fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // the most applicable enabled keyboard subtype of the system imes.
21284fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
21294fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (enabled != null) {
21304fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final int N = enabled.size();
21314fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final String locale = mCurrentSubtype == null
21324fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            ? mRes.getConfiguration().locale.toString()
21334fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            : mCurrentSubtype.getLocale();
21344fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    for (int i = 0; i < N; ++i) {
21354fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        final InputMethodInfo imi = enabled.get(i);
21368e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        if (imi.getSubtypeCount() > 0 && InputMethodUtils.isSystemIme(imi)) {
21374fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            InputMethodSubtype keyboardSubtype =
21388e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                    InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes,
21398e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.getSubtypes(imi),
21408e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, locale, true);
21414fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            if (keyboardSubtype != null) {
21424fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                targetLastImiId = imi.getId();
21438e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
21444fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                        imi, keyboardSubtype.hashCode());
21454fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                if(keyboardSubtype.getLocale().equals(locale)) {
21464fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                    break;
21474fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                }
21484fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            }
21494fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        }
21504fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    }
21514fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
21524fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
2153c445bcd0bce630948ee029d7c70b28226f0b6c9csatok
21544fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (!TextUtils.isEmpty(targetLastImiId)) {
2155c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                if (DEBUG) {
21564fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
21574fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            + ", from: " + mCurMethodId + ", " + subtypeId);
2158735cf38b8c7f8f91ad087511e44fe79018fa61d6satok                }
21594fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                setInputMethodWithSubtypeId(token, targetLastImiId, subtypeId);
2160c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                return true;
21614fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
21624fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                return false;
2163735cf38b8c7f8f91ad087511e44fe79018fa61d6satok            }
2164735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        }
2165735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    }
2166735cf38b8c7f8f91ad087511e44fe79018fa61d6satok
2167e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2168688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
21694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
21704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
21714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2172688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        synchronized (mMethodMap) {
2173d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethod(
2174688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                    onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
2175688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            if (nextSubtype == null) {
2176688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                return false;
2177688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            }
2178688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            setInputMethodWithSubtypeId(token, nextSubtype.mImi.getId(), nextSubtype.mSubtypeId);
2179688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            return true;
2180688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        }
2181688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    }
2182688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok
2183688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    @Override
21842b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    public boolean shouldOfferSwitchingToNextInputMethod(IBinder token) {
21852b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        if (!calledFromValidUser()) {
21862b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return false;
21872b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
21882b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        synchronized (mMethodMap) {
2189d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethod(
21902b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                    false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
21912b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            if (nextSubtype == null) {
21922b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                return false;
21932b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            }
21942b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return true;
21952b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
21962b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    }
21972b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka
21982b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    @Override
219968f1b78b7b9139a0e34285ff641a664e664a14b8satok    public InputMethodSubtype getLastInputMethodSubtype() {
22004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
22024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
220368f1b78b7b9139a0e34285ff641a664e664a14b8satok        synchronized (mMethodMap) {
220468f1b78b7b9139a0e34285ff641a664e664a14b8satok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
220568f1b78b7b9139a0e34285ff641a664e664a14b8satok            // TODO: Handle the case of the last IME with no subtypes
220668f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastIme == null || TextUtils.isEmpty(lastIme.first)
220768f1b78b7b9139a0e34285ff641a664e664a14b8satok                    || TextUtils.isEmpty(lastIme.second)) return null;
220868f1b78b7b9139a0e34285ff641a664e664a14b8satok            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
220968f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastImi == null) return null;
221068f1b78b7b9139a0e34285ff641a664e664a14b8satok            try {
221168f1b78b7b9139a0e34285ff641a664e664a14b8satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
22128e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final int lastSubtypeId =
22138e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
22140e7d7d632309409e2bc51d5317cf7a92a7541433satok                if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
22150e7d7d632309409e2bc51d5317cf7a92a7541433satok                    return null;
22160e7d7d632309409e2bc51d5317cf7a92a7541433satok                }
22170e7d7d632309409e2bc51d5317cf7a92a7541433satok                return lastImi.getSubtypeAt(lastSubtypeId);
221868f1b78b7b9139a0e34285ff641a664e664a14b8satok            } catch (NumberFormatException e) {
221968f1b78b7b9139a0e34285ff641a664e664a14b8satok                return null;
222068f1b78b7b9139a0e34285ff641a664e664a14b8satok            }
222168f1b78b7b9139a0e34285ff641a664e664a14b8satok        }
222268f1b78b7b9139a0e34285ff641a664e664a14b8satok    }
222368f1b78b7b9139a0e34285ff641a664e664a14b8satok
2224e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2225ee5e77cafec2eae70890abdcc1646ed39b06edddsatok    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
22264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
22274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
22284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
222991e88122cf28a48fd2e2260da7d3d87dd437227asatok        // By this IPC call, only a process which shares the same uid with the IME can add
223091e88122cf28a48fd2e2260da7d3d87dd437227asatok        // additional input method subtypes to the IME.
2231ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
2232e7c6998e0a953ae55487d4fe122739646f9280aasatok        synchronized (mMethodMap) {
223391e88122cf28a48fd2e2260da7d3d87dd437227asatok            final InputMethodInfo imi = mMethodMap.get(imiId);
2234ee5e77cafec2eae70890abdcc1646ed39b06edddsatok            if (imi == null) return;
22354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String[] packageInfos;
22364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            try {
22374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
22384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } catch (RemoteException e) {
22394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.e(TAG, "Failed to get package infos");
22404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
22414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
224291e88122cf28a48fd2e2260da7d3d87dd437227asatok            if (packageInfos != null) {
224391e88122cf28a48fd2e2260da7d3d87dd437227asatok                final int packageNum = packageInfos.length;
224491e88122cf28a48fd2e2260da7d3d87dd437227asatok                for (int i = 0; i < packageNum; ++i) {
224591e88122cf28a48fd2e2260da7d3d87dd437227asatok                    if (packageInfos[i].equals(imi.getPackageName())) {
224691e88122cf28a48fd2e2260da7d3d87dd437227asatok                        mFileManager.addInputMethodSubtypes(imi, subtypes);
2247c593380d1bccbfbd45c404954b2670b65acc287fsatok                        final long ident = Binder.clearCallingIdentity();
2248c593380d1bccbfbd45c404954b2670b65acc287fsatok                        try {
2249f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                            buildInputMethodListLocked(mMethodList, mMethodMap,
2250f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                                    false /* resetDefaultEnabledIme */);
2251c593380d1bccbfbd45c404954b2670b65acc287fsatok                        } finally {
2252c593380d1bccbfbd45c404954b2670b65acc287fsatok                            Binder.restoreCallingIdentity(ident);
2253c593380d1bccbfbd45c404954b2670b65acc287fsatok                        }
2254ee5e77cafec2eae70890abdcc1646ed39b06edddsatok                        return;
225591e88122cf28a48fd2e2260da7d3d87dd437227asatok                    }
225691e88122cf28a48fd2e2260da7d3d87dd437227asatok                }
225791e88122cf28a48fd2e2260da7d3d87dd437227asatok            }
2258e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
2259ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        return;
2260e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
2261e7c6998e0a953ae55487d4fe122739646f9280aasatok
2262658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    @Override
2263658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    public int getInputMethodWindowVisibleHeight() {
2264658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka        return mWindowManagerService.getInputMethodWindowVisibleHeight();
2265658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    }
2266658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka
2267d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    @Override
2268d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    public void notifyTextCommitted() {
2269d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (DEBUG) {
2270d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka            Slog.d(TAG, "Got the notification of commitText");
2271d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2272d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
2273d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (imi != null) {
2274d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka            mSwitchingController.onCommitText(imi, mCurrentSubtype);
2275d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2276d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    }
2277d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
22782820351489537698ad153c6397edf3270455edc5satok    private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (token == null) {
22819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mContext.checkCallingOrSelfPermission(
22829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        android.Manifest.permission.WRITE_SECURE_SETTINGS)
22839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        != PackageManager.PERMISSION_GRANTED) {
22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    throw new SecurityException(
22859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            "Using null token requires permission "
22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            + android.Manifest.permission.WRITE_SECURE_SETTINGS);
22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
22889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else if (mCurToken != token) {
2289cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
2290cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + " token: " + token);
22919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
22929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2294c593380d1bccbfbd45c404954b2670b65acc287fsatok            final long ident = Binder.clearCallingIdentity();
22959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2296ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                setInputMethodLocked(id, subtypeId);
22979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
22989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
22999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
230342c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideMySoftInput(IBinder token, int flags) {
23054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
23099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (token == null || mCurToken != token) {
2310cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                if (DEBUG) Slog.w(TAG, "Ignoring hideInputMethod of uid "
2311cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + " token: " + token);
23129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
23139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
23159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
23164df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                hideCurrentInputLocked(flags, null);
23174df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } finally {
23184df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                Binder.restoreCallingIdentity(ident);
23194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
23204df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
23214df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
2322ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
232342c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23244df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void showMySoftInput(IBinder token, int flags) {
23254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23284df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        synchronized (mMethodMap) {
23294df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            if (token == null || mCurToken != token) {
2330cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                Slog.w(TAG, "Ignoring showMySoftInput of uid "
2331cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + " token: " + token);
23324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return;
23334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
23344df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            long ident = Binder.clearCallingIdentity();
23354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            try {
23364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                showCurrentInputLocked(flags, null);
23379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
23389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
23399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
23429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
23439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setEnabledSessionInMainThread(SessionState session) {
23449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledSession != session) {
23459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mEnabledSession != null) {
23469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
23478a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
23489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mEnabledSession.method.setSessionEnabled(
23499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            mEnabledSession.session, false);
23509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
23519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledSession = session;
23549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
23558a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
23569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                session.method.setSessionEnabled(
23579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        session.session, true);
23589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
23599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2362ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
236342c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean handleMessage(Message msg) {
2365758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov        SomeArgs args;
23669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (msg.what) {
23679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_IM_PICKER:
23689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                showInputMethodMenu();
23699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2370ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2371ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            case MSG_SHOW_IM_SUBTYPE_PICKER:
2372ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                showInputMethodSubtypeMenu();
2373ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                return true;
2374ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
237547a44916e2fb33cf4751906386d5f5c903b28d8bsatok            case MSG_SHOW_IM_SUBTYPE_ENABLER:
2376758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
23777fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                showInputMethodAndSubtypeEnabler((String)args.arg1);
2378758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
2379217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                return true;
2380217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2381217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            case MSG_SHOW_IM_CONFIG:
2382217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                showConfigureInputMethods();
238347a44916e2fb33cf4751906386d5f5c903b28d8bsatok                return true;
238447a44916e2fb33cf4751906386d5f5c903b28d8bsatok
23859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2386ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
23879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_INPUT:
23889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
23899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)msg.obj).unbindInput();
23909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
23919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the method dying.
23929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
23949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_BIND_INPUT:
2395758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
23969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
23979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);
23989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
23999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2400758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_SOFT_INPUT:
2403758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2405e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
24066efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + msg.arg1 + ", " + args.arg2 + ")");
2407ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
24089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2410758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_HIDE_SOFT_INPUT:
2413758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2415e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
24166efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + args.arg2 + ")");
2417ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
24189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2420758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_ATTACH_TOKEN:
2423758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2425e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
24269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
24279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2429758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2431c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            case MSG_CREATE_SESSION: {
2432758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24331951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethod method = (IInputMethod)args.arg1;
2434c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel = (InputChannel)args.arg2;
24359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24361951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    method.createSession(channel, (IInputSessionCallback)args.arg3);
24379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2438c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } finally {
24391951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
24401951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
24411951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (channel != null && Binder.isProxy(method)) {
2442c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        channel.dispose();
2443c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    }
24449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2445758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2447c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
24489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2449ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_START_INPUT:
2451758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
24549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
24559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.startInput((IInputContext)args.arg2,
24569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
24579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2459758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_RESTART_INPUT:
2462758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
24659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
24669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.restartInput((IInputContext)args.arg2,
24679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
24689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2470758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2472ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2474ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
24759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_METHOD:
24769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1);
24789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the last client dying.
24809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
24819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24821951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            case MSG_BIND_METHOD: {
2483758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
24841951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethodClient client = (IInputMethodClient)args.arg1;
24851951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                InputBindResult res = (InputBindResult)args.arg2;
24869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
24871951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    client.onBindMethod(res);
24889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
24898a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Client died receiving input method " + args.arg2);
24901951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                } finally {
24911951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
24921951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
24931951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (res.channel != null && Binder.isProxy(client)) {
24941951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                        res.channel.dispose();
24951951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    }
24969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2497758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
24989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
24991951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            }
2500a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            case MSG_SET_ACTIVE:
2501a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                try {
2502a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    ((ClientState)msg.obj).client.setActive(msg.arg1 != 0);
2503a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                } catch (RemoteException e) {
2504a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    Slog.w(TAG, "Got RemoteException sending setActive(false) notification to pid "
2505a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).pid + " uid "
2506a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).uid);
2507a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                }
2508a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                return true;
250901038492ff0317f0d3cff54d8a7ee36bb31ff175satok
251001038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // --------------------------------------------------------------
251101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
251201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                mHardKeyboardListener.handleHardKeyboardStatusChange(
251301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        msg.arg1 == 1, msg.arg2 == 1);
251401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                return true;
25159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
25179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2519dc9ddaee9a710cf6f5d7f37350650f82e706c706satok    private boolean chooseNewDefaultIMELocked() {
25208e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
25218e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mSettings.getEnabledInputMethodListLocked());
2522dc9ddaee9a710cf6f5d7f37350650f82e706c706satok        if (imi != null) {
252303eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            if (DEBUG) {
252403eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                Slog.d(TAG, "New default IME was selected: " + imi.getId());
252503eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            }
2526723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            resetSelectedInputMethodAndSubtypeLocked(imi.getId());
25276da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            return true;
25286da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
25296da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
25306da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        return false;
25316da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger    }
25326da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
25339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
2534f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) {
25354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
2536f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
25370766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                    + " \n ------ \n" + InputMethodUtils.getStackTrace());
25384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
25399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        list.clear();
25409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map.clear();
2541ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // Use for queryIntentServicesAsUser
25434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final PackageManager pm = mContext.getPackageManager();
25444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
2545e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani        if (disabledSysImes == null) disabledSysImes = "";
25469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
25489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new Intent(InputMethod.SERVICE_INTERFACE),
2549fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
2550fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                mSettings.getCurrentUserId());
2551ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2552e7c6998e0a953ae55487d4fe122739646f9280aasatok        final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
2553e7c6998e0a953ae55487d4fe122739646f9280aasatok                mFileManager.getAllAdditionalInputMethodSubtypes();
25549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < services.size(); ++i) {
25559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = services.get(i);
25569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ServiceInfo si = ri.serviceInfo;
25579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ComponentName compName = new ComponentName(si.packageName, si.name);
25589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(
25599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    si.permission)) {
25608a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Skipping input method " + compName
25619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": it does not require the permission "
25629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.BIND_INPUT_METHOD);
25639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
25649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25668a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.d(TAG, "Checking " + compName);
25679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2569e7c6998e0a953ae55487d4fe122739646f9280aasatok                InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes);
25709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list.add(p);
2571e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                final String id = p.getId();
2572e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                map.put(id, p);
25739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
2575f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "Found an input method " + p);
25769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2577ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
25789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
25798a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
25809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
25818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
25829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25846da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
2585f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (resetDefaultEnabledIme) {
2586f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            final ArrayList<InputMethodInfo> defaultEnabledIme =
2587f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list);
2588f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            for (int i = 0; i < defaultEnabledIme.size(); ++i) {
2589f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                final InputMethodInfo imi =  defaultEnabledIme.get(i);
2590f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                if (DEBUG) {
2591f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "--- enable ime = " + imi);
2592f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                }
2593f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                setInputMethodEnabledLocked(imi.getId(), true);
2594f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            }
2595f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
2596f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
25974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
25980a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!TextUtils.isEmpty(defaultImiId)) {
25990a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            if (!map.containsKey(defaultImiId)) {
26000a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
26010a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (chooseNewDefaultIMELocked()) {
2602fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(true);
26030a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
26040a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            } else {
26050a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                // Double check that the default IME is certainly enabled.
26060a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                setInputMethodEnabledLocked(defaultImiId, true);
26076da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            }
26086da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
26099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2610ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2612ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2613ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenu() {
2614ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(false);
2615ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2616ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2617ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodSubtypeMenu() {
2618ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        showInputMethodMenuInternal(true);
2619ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2620ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2621217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
2622f49688fa17b70313c0734f00df73bc3308a749e9Tadashi G. Takaoka        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
262347a44916e2fb33cf4751906386d5f5c903b28d8bsatok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
262486417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
262586417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
26267fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        if (!TextUtils.isEmpty(inputMethodId)) {
26272548020c364c4119d134c84cc7a00ffca2dcbe7bTadashi G. Takaoka            intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId);
26287fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        }
26293ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
2630217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    }
2631217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2632217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showConfigureInputMethods() {
2633217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
2634217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2635217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
2636217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
26373ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
263847a44916e2fb33cf4751906386d5f5c903b28d8bsatok    }
263947a44916e2fb33cf4751906386d5f5c903b28d8bsatok
26402c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    private boolean isScreenLocked() {
26412c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        return mKeyguardManager != null
26422c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
26432c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    }
2644ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private void showInputMethodMenuInternal(boolean showSubtypes) {
26458a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Show switching menu");
26469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Context context = mContext;
26482c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        final boolean isScreenLocked = isScreenLocked();
2649ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String lastInputMethodId = mSettings.getSelectedInputMethod();
26518e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
26528a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
2653ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26547f35c8cc88bea5230f001dd4356f864845d202e5satok        synchronized (mMethodMap) {
2655bb4aa0683c8a0a1e617c6d5f03eda33f49b89ed9satok            final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
2656d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(
2657d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                            mContext);
26587f35c8cc88bea5230f001dd4356f864845d202e5satok            if (immis == null || immis.size() == 0) {
26597f35c8cc88bea5230f001dd4356f864845d202e5satok                return;
26607f35c8cc88bea5230f001dd4356f864845d202e5satok            }
2661ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
26628cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            hideInputMethodMenuLocked();
26639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2664688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            final List<ImeSubtypeListItem> imList =
2665d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSwitchingController.getSortedInputMethodAndSubtypeList(
2666688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                            showSubtypes, mInputShown, isScreenLocked);
2667913a8925c07e854a80bf5df87561f290d3a56d61satok
2668c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
26694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
2670c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                if (currentSubtype != null) {
2671c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                    final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
26728e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
26738e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            currentImi, currentSubtype.hashCode());
2674c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                }
2675c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            }
2676c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok
2677761eb3762f3602dd1859905ee4ba80f0ef6aec56Ken Wakasa            final int N = imList.size();
2678ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mIms = new InputMethodInfo[N];
2679ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mSubtypeIds = new int[N];
26808cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            int checkedItem = 0;
26818cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            for (int i = 0; i < N; ++i) {
268205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                final ImeSubtypeListItem item = imList.get(i);
268305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mIms[i] = item.mImi;
268405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mSubtypeIds[i] = item.mSubtypeId;
26858cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                if (mIms[i].getId().equals(lastInputMethodId)) {
2686ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    int subtypeId = mSubtypeIds[i];
2687ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    if ((subtypeId == NOT_A_SUBTYPE_ID)
2688ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0)
2689ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (subtypeId == lastInputMethodSubtypeId)) {
2690ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                        checkedItem = i;
2691ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
26928cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                }
26939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
269405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TypedArray a = context.obtainStyledAttributes(null,
26958cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    com.android.internal.R.styleable.DialogPreference,
26968cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    com.android.internal.R.attr.alertDialogStyle, 0);
26978cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            mDialogBuilder = new AlertDialog.Builder(context)
26988cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    .setOnCancelListener(new OnCancelListener() {
269942c5a1666c4e576ccd5974233513100aad2c1534satok                        @Override
27008cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        public void onCancel(DialogInterface dialog) {
27019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            hideInputMethodMenu();
27028cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        }
27038cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    })
27048cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    .setIcon(a.getDrawable(
27058cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                            com.android.internal.R.styleable.DialogPreference_dialogTitle));
27068cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            a.recycle();
270701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final LayoutInflater inflater =
270801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    (LayoutInflater)mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
270901038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final View tv = inflater.inflate(
271001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.layout.input_method_switch_dialog_title, null);
271101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mDialogBuilder.setCustomTitle(tv);
271201038492ff0317f0d3cff54d8a7ee36bb31ff175satok
271301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // Setup layout for a toggle switch of the hardware keyboard
271401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView = tv;
271501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView.findViewById(
271601038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.id.hard_keyboard_section).setVisibility(
271701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mWindowManagerService.isHardKeyboardAvailable() ?
271801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    View.VISIBLE : View.GONE);
271901038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final Switch hardKeySwitch =  ((Switch)mSwitchingDialogTitleView.findViewById(
272001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.id.hard_keyboard_switch));
272101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            hardKeySwitch.setChecked(mWindowManagerService.isHardKeyboardEnabled());
272201038492ff0317f0d3cff54d8a7ee36bb31ff175satok            hardKeySwitch.setOnCheckedChangeListener(
272301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    new OnCheckedChangeListener() {
272401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        @Override
272501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        public void onCheckedChanged(
272601038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                CompoundButton buttonView, boolean isChecked) {
272701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mWindowManagerService.setHardKeyboardEnabled(isChecked);
272804dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            // Ensure that the input method dialog is dismissed when changing
272904dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            // the hardware keyboard state.
273004dd24d4baf7f78e7b47c9f91e82dfb44fd48190Satoshi Kataoka                            hideInputMethodMenu();
273101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        }
273201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    });
2733d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok
273405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(context,
273505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    com.android.internal.R.layout.simple_list_item_2_single_choice, imList,
273605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    checkedItem);
273705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
273805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mDialogBuilder.setSingleChoiceItems(adapter, checkedItem,
27398cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    new AlertDialog.OnClickListener() {
274042c5a1666c4e576ccd5974233513100aad2c1534satok                        @Override
27418cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                        public void onClick(DialogInterface dialog, int which) {
27428cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                            synchronized (mMethodMap) {
2743ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                if (mIms == null || mIms.length <= which
2744ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                        || mSubtypeIds == null || mSubtypeIds.length <= which) {
27458cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                    return;
27468cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                }
27478cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                InputMethodInfo im = mIms[which];
2748ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                int subtypeId = mSubtypeIds[which];
2749d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka                                adapter.mCheckedItem = which;
2750d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka                                adapter.notifyDataSetChanged();
27518cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                hideInputMethodMenu();
27528cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                if (im != null) {
2753ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    if ((subtypeId < 0)
2754586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                                            || (subtypeId >= im.getSubtypeCount())) {
2755ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                        subtypeId = NOT_A_SUBTYPE_ID;
2756ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    }
2757ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                                    setInputMethodLocked(im.getId(), subtypeId);
27588cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                                }
275920cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn                            }
27609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
27618cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                    });
27629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2763bc81b692d51a9cd6f9d61584aacd8308ac3366easatok            if (showSubtypes && !isScreenLocked) {
276482beadfa067b1e286fa604f8d7960d769411c954satok                mDialogBuilder.setPositiveButton(
276582beadfa067b1e286fa604f8d7960d769411c954satok                        com.android.internal.R.string.configure_input_methods,
27667f35c8cc88bea5230f001dd4356f864845d202e5satok                        new DialogInterface.OnClickListener() {
276742c5a1666c4e576ccd5974233513100aad2c1534satok                            @Override
27687f35c8cc88bea5230f001dd4356f864845d202e5satok                            public void onClick(DialogInterface dialog, int whichButton) {
2769217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                                showConfigureInputMethods();
27707f35c8cc88bea5230f001dd4356f864845d202e5satok                            }
27717f35c8cc88bea5230f001dd4356f864845d202e5satok                        });
27727f35c8cc88bea5230f001dd4356f864845d202e5satok            }
27739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog = mDialogBuilder.create();
2774e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.setCanceledOnTouchOutside(true);
27759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.getWindow().setType(
27769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
2777c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
2778c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
2779e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
27809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.show();
27819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
27829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2783ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
278405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> {
278505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final LayoutInflater mInflater;
278605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final int mTextViewResourceId;
278705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final List<ImeSubtypeListItem> mItemsList;
2788d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka        public int mCheckedItem;
278905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public ImeSubtypeListAdapter(Context context, int textViewResourceId,
279005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                List<ImeSubtypeListItem> itemsList, int checkedItem) {
279105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            super(context, textViewResourceId, itemsList);
279205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mTextViewResourceId = textViewResourceId;
279305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mItemsList = itemsList;
279405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mCheckedItem = checkedItem;
279505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mInflater = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
279605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
279705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
279805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        @Override
279905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public View getView(int position, View convertView, ViewGroup parent) {
280005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final View view = convertView != null ? convertView
280105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    : mInflater.inflate(mTextViewResourceId, null);
280205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (position < 0 || position >= mItemsList.size()) return view;
280305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListItem item = mItemsList.get(position);
280405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence imeName = item.mImeName;
280505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence subtypeName = item.mSubtypeName;
280605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1);
280705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2);
280805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (TextUtils.isEmpty(subtypeName)) {
280905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(imeName);
281005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.GONE);
281105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            } else {
281205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(subtypeName);
281305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setText(imeName);
281405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.VISIBLE);
281505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            }
281605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final RadioButton radioButton =
281705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
281805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            radioButton.setChecked(position == mCheckedItem);
281905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            return view;
282005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
282105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    }
282205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
28239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hideInputMethodMenu() {
2824105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        synchronized (mMethodMap) {
2825105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
2826105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
2827105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
2828ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2829105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void hideInputMethodMenuLocked() {
28308a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Hide switching menu");
28319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2832105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mSwitchingDialog != null) {
2833105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog.dismiss();
2834105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog = null;
28359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2836ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2837105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mDialogBuilder = null;
2838105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIms = null;
28399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2840ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
28419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2842ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
284342c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
28449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setInputMethodEnabled(String id, boolean enabled) {
28454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
28464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
28474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
28484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
28499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
28509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mContext.checkCallingOrSelfPermission(
28519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
28529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    != PackageManager.PERMISSION_GRANTED) {
28539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new SecurityException(
28549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Requires permission "
28559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
28569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
285721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
28589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
28599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
286021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                return setInputMethodEnabledLocked(id, enabled);
286121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } finally {
286221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Binder.restoreCallingIdentity(ident);
286321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
286421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
286521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
28668e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
286721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    boolean setInputMethodEnabledLocked(String id, boolean enabled) {
286821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        // Make sure this is a valid input method.
286921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        InputMethodInfo imm = mMethodMap.get(id);
287021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (imm == null) {
2871d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
287221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
2873ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2874d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
2875d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                .getEnabledInputMethodsAndSubtypeListLocked();
2876ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2877d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        if (enabled) {
2878d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            for (Pair<String, ArrayList<String>> pair: enabledInputMethodsList) {
2879d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                if (pair.first.equals(id)) {
2880d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // We are enabling this input method, but it is already enabled.
2881d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // Nothing to do. The previous state was enabled.
2882d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    return true;
28839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
288421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
2885d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            mSettings.appendAndPutEnabledInputMethodLocked(id, false);
2886d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            // Previous state was disabled.
2887d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return false;
2888d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        } else {
2889d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            StringBuilder builder = new StringBuilder();
2890d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
2891d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    builder, enabledInputMethodsList, id)) {
2892d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Disabled input method is currently selected, switch to another one.
28934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selId = mSettings.getSelectedInputMethod();
289403eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
289503eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
289603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    resetSelectedInputMethodAndSubtypeLocked("");
2897d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                }
2898d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Previous state was enabled.
2899d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                return true;
2900d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            } else {
2901d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // We are disabling the input method but it is already disabled.
2902d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Nothing to do.  The previous state was disabled.
29039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
29049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
29059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
29074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
2908723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
2909723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            boolean setSubtypeOnly) {
2910723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Update the history of InputMethod and Subtype
29118e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
2912723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
2913723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Set Subtype here
2914723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi == null || subtypeId < 0) {
2915723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
29160ba75bb22c2992f649ee5f7605a2b45442ad4862Tadashi G. Takaoka            mCurrentSubtype = null;
2917723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        } else {
2918586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa            if (subtypeId < imi.getSubtypeCount()) {
2919586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                InputMethodSubtype subtype = imi.getSubtypeAt(subtypeId);
2920586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mSettings.putSelectedSubtype(subtype.hashCode());
2921586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mCurrentSubtype = subtype;
2922723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            } else {
2923723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
2924d81e950265356c81276b73da68a535ffa48d72f0satok                // If the subtype is not specified, choose the most applicable one
29254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
2926723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
2927723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
2928723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
29294c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Workaround.
29304c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // ASEC is not ready in the IMMS constructor. Accordingly, forward-locked
29314c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMEs are not recognized and considered uninstalled.
29324c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Actually, we can't move everything after SystemReady because
29334c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMMS needs to run in the encryption lock screen. So, we just skip changing
29344c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the default IME here and try cheking the default IME again in systemReady().
29354c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: Do nothing before system ready and implement a separated logic for
29364c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the encryption lock screen.
29374c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: ASEC should be ready before IMMS is instantiated.
29384c0e7152e74d091eb78af8baacd38287ba95a1a1satok        if (mSystemReady && !setSubtypeOnly) {
2939723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // Set InputMethod here
2940723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
29411ab852fbcfe155c9d4373b7130f8515591669634satok        }
2942ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2943ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
2944723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
2945723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        InputMethodInfo imi = mMethodMap.get(newDefaultIme);
2946723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        int lastSubtypeId = NOT_A_SUBTYPE_ID;
2947723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // newDefaultIme is empty when there is no candidate for the selected IME.
2948723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
2949723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme);
2950723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            if (subtypeHashCode != null) {
2951723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                try {
29528e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
2953723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                            imi, Integer.valueOf(subtypeHashCode));
2954723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                } catch (NumberFormatException e) {
2955723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                    Slog.w(TAG, "HashCode for subtype looks broken: " + subtypeHashCode, e);
2956723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                }
2957723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
2958723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
2959723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
2960723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    }
2961723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
29624e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // If there are no selected shortcuts, tries finding the most applicable ones.
29634e4569dab5c75804b01a19b2d6e6101b445c1c68satok    private Pair<InputMethodInfo, InputMethodSubtype>
29644e4569dab5c75804b01a19b2d6e6101b445c1c68satok            findLastResortApplicableShortcutInputMethodAndSubtypeLocked(String mode) {
29654e4569dab5c75804b01a19b2d6e6101b445c1c68satok        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
29664e4569dab5c75804b01a19b2d6e6101b445c1c68satok        InputMethodInfo mostApplicableIMI = null;
2967cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        InputMethodSubtype mostApplicableSubtype = null;
29684e4569dab5c75804b01a19b2d6e6101b445c1c68satok        boolean foundInSystemIME = false;
29694e4569dab5c75804b01a19b2d6e6101b445c1c68satok
29704e4569dab5c75804b01a19b2d6e6101b445c1c68satok        // Search applicable subtype for each InputMethodInfo
29714e4569dab5c75804b01a19b2d6e6101b445c1c68satok        for (InputMethodInfo imi: imis) {
29727599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            final String imiId = imi.getId();
29737599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (foundInSystemIME && !imiId.equals(mCurMethodId)) {
29747599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                continue;
29757599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
2976cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            InputMethodSubtype subtype = null;
2977df31ae6a3011d47421a6ac10021f9649dc34a156satok            final List<InputMethodSubtype> enabledSubtypes =
29788e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
2979df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 1. Search by the current subtype's locale from enabledSubtypes.
29804e4569dab5c75804b01a19b2d6e6101b445c1c68satok            if (mCurrentSubtype != null) {
29818e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
2982df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
29834e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
2984df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 2. Search by the system locale from enabledSubtypes.
2985df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
2986cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
29878e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
2988df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, null, true);
29897599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
2990a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
29918e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    InputMethodUtils.getOverridingImplicitlyEnabledSubtypes(imi, mode);
2992a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> subtypesForSearch =
2993a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                    overridingImplicitlyEnabledSubtypes.isEmpty()
29948e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            ? InputMethodUtils.getSubtypes(imi)
29958e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            : overridingImplicitlyEnabledSubtypes;
29967599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 4. Search by the current subtype's locale from all subtypes.
29977599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (subtype == null && mCurrentSubtype != null) {
29988e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
2999a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
30004e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
30017599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 5. Search by the system locale from all subtypes.
30027599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 6. Search the first enabled subtype matched with mode from all subtypes.
3003cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
30048e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3005a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, null, true);
30064e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3007cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype != null) {
30087599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (imiId.equals(mCurMethodId)) {
30094e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    // The current input method is the most applicable IME.
30104e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3011cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
30124e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    break;
30134e4569dab5c75804b01a19b2d6e6101b445c1c68satok                } else if (!foundInSystemIME) {
30147599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    // The system input method is 2nd applicable IME.
30154e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3016cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
30177599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    if ((imi.getServiceInfo().applicationInfo.flags
30187599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
30197599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                        foundInSystemIME = true;
30207599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    }
30214e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
30224e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
30234e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
30244e4569dab5c75804b01a19b2d6e6101b445c1c68satok        if (DEBUG) {
3025cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (mostApplicableIMI != null) {
3026cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                Slog.w(TAG, "Most applicable shortcut input method was:"
3027cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                        + mostApplicableIMI.getId());
3028cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                if (mostApplicableSubtype != null) {
3029cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    Slog.w(TAG, "Most applicable shortcut input method subtype was:"
3030cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + "," + mostApplicableSubtype.getMode() + ","
3031cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + mostApplicableSubtype.getLocale());
3032cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                }
3033cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            }
30344e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
3035cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        if (mostApplicableIMI != null) {
30364e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
3037cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype);
30384e4569dab5c75804b01a19b2d6e6101b445c1c68satok        } else {
30394e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return null;
30404e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
30414e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
30424e4569dab5c75804b01a19b2d6e6101b445c1c68satok
3043ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3044ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return Return the current subtype of this input method.
3045ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
304642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3047ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public InputMethodSubtype getCurrentInputMethodSubtype() {
30484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
30494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
30504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
30514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
30524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        synchronized (mMethodMap) {
30534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return getCurrentInputMethodSubtypeLocked();
30544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
30554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
30564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
30574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
3058fdf419e81d795593e3792c9e78f33ed899ff098esatok        if (mCurMethodId == null) {
3059fdf419e81d795593e3792c9e78f33ed899ff098esatok            return null;
3060fdf419e81d795593e3792c9e78f33ed899ff098esatok        }
30618e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
30624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
30634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (imi == null || imi.getSubtypeCount() == 0) {
30644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
30654e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
30664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!subtypeIsSelected || mCurrentSubtype == null
30678e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
30688e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
30694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (subtypeId == NOT_A_SUBTYPE_ID) {
30704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there are no selected subtypes, the framework will try to find
30714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // the most applicable subtype from explicitly or implicitly enabled
30724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // subtypes.
30734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
30748e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
30754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there is only one explicitly or implicitly enabled subtype,
30764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // just returns it.
30774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
30784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
30794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
30808e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
30814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            mRes, explicitlyOrImplicitlyEnabledSubtypes,
30828e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, null, true);
30834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    if (mCurrentSubtype == null) {
30848e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
30854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
30864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                true);
30874e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    }
30883ef8b29fa03fe3ae1c57fd891a12afa46128fff8satok                }
30894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else {
30908e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mCurrentSubtype = InputMethodUtils.getSubtypes(imi).get(subtypeId);
30918fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok            }
30928fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok        }
30934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        return mCurrentSubtype;
3094ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3095ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3096f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
3097f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            InputMethodSubtype subtype) {
3098f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
3099f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
3100f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        } else {
3101f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3102f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            subtypes.add(subtype);
3103f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
3104f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        }
3105f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    }
3106f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok
31074e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // TODO: We should change the return type from List to List<Parcelable>
3108dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("rawtypes")
3109e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
31104e4569dab5c75804b01a19b2d6e6101b445c1c68satok    public List getShortcutInputMethodsAndSubtypes() {
31114e4569dab5c75804b01a19b2d6e6101b445c1c68satok        synchronized (mMethodMap) {
31123da922367c0dbe67b97fe97fcfca13fd93602f7asatok            ArrayList<Object> ret = new ArrayList<Object>();
3113f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            if (mShortcutInputMethodsAndSubtypes.size() == 0) {
31144e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // If there are no selected shortcut subtypes, the framework will try to find
31154e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // the most applicable subtype from all subtypes whose mode is
31164e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
3117f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                Pair<InputMethodInfo, InputMethodSubtype> info =
3118f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
31198e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_VOICE);
31207599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (info != null) {
31213da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.first);
31223da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.second);
31237599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                }
31243da922367c0dbe67b97fe97fcfca13fd93602f7asatok                return ret;
3125f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            }
3126f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
3127f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                ret.add(imi);
3128f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
3129f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    ret.add(subtype);
31304e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
31314e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3132f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            return ret;
31334e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
31344e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
31354e4569dab5c75804b01a19b2d6e6101b445c1c68satok
313642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3137b66d287e3003a0934d5714fbf15e554b3c814906satok    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
31384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
31394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
31404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
31414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
3142b66d287e3003a0934d5714fbf15e554b3c814906satok        synchronized (mMethodMap) {
3143b66d287e3003a0934d5714fbf15e554b3c814906satok            if (subtype != null && mCurMethodId != null) {
3144b66d287e3003a0934d5714fbf15e554b3c814906satok                InputMethodInfo imi = mMethodMap.get(mCurMethodId);
31458e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                int subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode());
3146b66d287e3003a0934d5714fbf15e554b3c814906satok                if (subtypeId != NOT_A_SUBTYPE_ID) {
3147b66d287e3003a0934d5714fbf15e554b3c814906satok                    setInputMethodLocked(mCurMethodId, subtypeId);
3148b66d287e3003a0934d5714fbf15e554b3c814906satok                    return true;
3149b66d287e3003a0934d5714fbf15e554b3c814906satok                }
3150b66d287e3003a0934d5714fbf15e554b3c814906satok            }
3151b66d287e3003a0934d5714fbf15e554b3c814906satok            return false;
3152b66d287e3003a0934d5714fbf15e554b3c814906satok        }
3153b66d287e3003a0934d5714fbf15e554b3c814906satok    }
3154b66d287e3003a0934d5714fbf15e554b3c814906satok
31555ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    // TODO: Cache the state for each user and reset when the cached user is removed.
3156e7c6998e0a953ae55487d4fe122739646f9280aasatok    private static class InputMethodFileManager {
3157e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String SYSTEM_PATH = "system";
3158e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String INPUT_METHOD_PATH = "inputmethod";
3159e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ADDITIONAL_SUBTYPES_FILE_NAME = "subtypes.xml";
3160e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPES = "subtypes";
3161e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPE = "subtype";
3162e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_IMI = "imi";
3163e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ID = "id";
3164e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_LABEL = "label";
3165e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ICON = "icon";
3166e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
3167e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
3168e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
3169e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
3170e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final AtomicFile mAdditionalInputMethodSubtypeFile;
3171e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final HashMap<String, InputMethodInfo> mMethodMap;
3172e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
3173e7c6998e0a953ae55487d4fe122739646f9280aasatok                new HashMap<String, List<InputMethodSubtype>>();
31745ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
3175e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (methodMap == null) {
3176e7c6998e0a953ae55487d4fe122739646f9280aasatok                throw new NullPointerException("methodMap is null");
3177e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3178e7c6998e0a953ae55487d4fe122739646f9280aasatok            mMethodMap = methodMap;
31795ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka            final File systemDir = userId == UserHandle.USER_OWNER
31805ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
31815ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    : Environment.getUserSystemDirectory(userId);
3182e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
3183e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!inputMethodDir.mkdirs()) {
3184e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
3185e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3186e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
3187e7c6998e0a953ae55487d4fe122739646f9280aasatok            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
3188e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!subtypeFile.exists()) {
3189e7c6998e0a953ae55487d4fe122739646f9280aasatok                // If "subtypes.xml" doesn't exist, create a blank file.
3190e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3191e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, methodMap);
3192e7c6998e0a953ae55487d4fe122739646f9280aasatok            } else {
3193e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                readAdditionalInputMethodSubtypes(
3194e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile);
3195e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3196e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3197e7c6998e0a953ae55487d4fe122739646f9280aasatok
3198e7c6998e0a953ae55487d4fe122739646f9280aasatok        private void deleteAllInputMethodSubtypes(String imiId) {
3199e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3200e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.remove(imiId);
3201e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3202e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3203e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3204e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3205e7c6998e0a953ae55487d4fe122739646f9280aasatok
3206e7c6998e0a953ae55487d4fe122739646f9280aasatok        public void addInputMethodSubtypes(
32074a28bde70e23b2ed151d52690da702da7f23cf5esatok                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
3208e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3209e7c6998e0a953ae55487d4fe122739646f9280aasatok                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3210e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int N = additionalSubtypes.length;
3211e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (int i = 0; i < N; ++i) {
3212e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final InputMethodSubtype subtype = additionalSubtypes[i];
3213ed2b24ecc7842b27178fc584a9e5bd5b1ab07635satok                    if (!subtypes.contains(subtype)) {
3214e7c6998e0a953ae55487d4fe122739646f9280aasatok                        subtypes.add(subtype);
3215e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                    } else {
3216e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        Slog.w(TAG, "Duplicated subtype definition found: "
3217e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                                + subtype.getLocale() + ", " + subtype.getMode());
3218e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3219e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3220e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.put(imi.getId(), subtypes);
3221e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3222e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3223e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3224e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3225e7c6998e0a953ae55487d4fe122739646f9280aasatok
3226e7c6998e0a953ae55487d4fe122739646f9280aasatok        public HashMap<String, List<InputMethodSubtype>> getAllAdditionalInputMethodSubtypes() {
3227e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3228e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                return mAdditionalSubtypesMap;
3229e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3230e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3231e7c6998e0a953ae55487d4fe122739646f9280aasatok
3232e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void writeAdditionalInputMethodSubtypes(
3233e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile,
3234e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, InputMethodInfo> methodMap) {
3235e7c6998e0a953ae55487d4fe122739646f9280aasatok            // Safety net for the case that this function is called before methodMap is set.
3236e7c6998e0a953ae55487d4fe122739646f9280aasatok            final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0;
3237e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileOutputStream fos = null;
3238e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3239e7c6998e0a953ae55487d4fe122739646f9280aasatok                fos = subtypesFile.startWrite();
3240e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlSerializer out = new FastXmlSerializer();
3241e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setOutput(fos, "utf-8");
3242e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startDocument(null, true);
3243e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3244e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startTag(null, NODE_SUBTYPES);
3245e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (String imiId : allSubtypes.keySet()) {
3246e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (isSetMethodMap && !methodMap.containsKey(imiId)) {
3247e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "IME uninstalled or not valid.: " + imiId);
3248e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3249e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3250e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.startTag(null, NODE_IMI);
3251e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.attribute(null, ATTR_ID, imiId);
3252e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final List<InputMethodSubtype> subtypesList = allSubtypes.get(imiId);
3253e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final int N = subtypesList.size();
3254e7c6998e0a953ae55487d4fe122739646f9280aasatok                    for (int i = 0; i < N; ++i) {
3255e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype = subtypesList.get(i);
3256e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.startTag(null, NODE_SUBTYPE);
3257e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
3258e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
3259e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
3260e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_MODE, subtype.getMode());
3261e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
3262e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IS_AUXILIARY,
3263e7c6998e0a953ae55487d4fe122739646f9280aasatok                                String.valueOf(subtype.isAuxiliary() ? 1 : 0));
3264e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.endTag(null, NODE_SUBTYPE);
3265e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3266e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.endTag(null, NODE_IMI);
3267e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3268e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endTag(null, NODE_SUBTYPES);
3269e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endDocument();
3270e7c6998e0a953ae55487d4fe122739646f9280aasatok                subtypesFile.finishWrite(fos);
3271e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3272e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error writing subtypes", e);
3273e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fos != null) {
3274e7c6998e0a953ae55487d4fe122739646f9280aasatok                    subtypesFile.failWrite(fos);
3275e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3276e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3277e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3278e7c6998e0a953ae55487d4fe122739646f9280aasatok
3279e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void readAdditionalInputMethodSubtypes(
3280e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile) {
3281e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (allSubtypes == null || subtypesFile == null) return;
3282e7c6998e0a953ae55487d4fe122739646f9280aasatok            allSubtypes.clear();
3283e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileInputStream fis = null;
3284e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3285e7c6998e0a953ae55487d4fe122739646f9280aasatok                fis = subtypesFile.openRead();
3286e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlPullParser parser = Xml.newPullParser();
3287e7c6998e0a953ae55487d4fe122739646f9280aasatok                parser.setInput(fis, null);
3288e7c6998e0a953ae55487d4fe122739646f9280aasatok                int type = parser.getEventType();
3289e7c6998e0a953ae55487d4fe122739646f9280aasatok                // Skip parsing until START_TAG
3290e7c6998e0a953ae55487d4fe122739646f9280aasatok                while ((type = parser.next()) != XmlPullParser.START_TAG
3291e7c6998e0a953ae55487d4fe122739646f9280aasatok                        && type != XmlPullParser.END_DOCUMENT) {}
3292e7c6998e0a953ae55487d4fe122739646f9280aasatok                String firstNodeName = parser.getName();
3293e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (!NODE_SUBTYPES.equals(firstNodeName)) {
3294e7c6998e0a953ae55487d4fe122739646f9280aasatok                    throw new XmlPullParserException("Xml doesn't start with subtypes");
3295e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3296e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int depth =parser.getDepth();
3297e7c6998e0a953ae55487d4fe122739646f9280aasatok                String currentImiId = null;
3298e7c6998e0a953ae55487d4fe122739646f9280aasatok                ArrayList<InputMethodSubtype> tempSubtypesArray = null;
3299e7c6998e0a953ae55487d4fe122739646f9280aasatok                while (((type = parser.next()) != XmlPullParser.END_TAG
3300e7c6998e0a953ae55487d4fe122739646f9280aasatok                        || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
3301e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (type != XmlPullParser.START_TAG)
3302e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3303e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final String nodeName = parser.getName();
3304e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (NODE_IMI.equals(nodeName)) {
3305e7c6998e0a953ae55487d4fe122739646f9280aasatok                        currentImiId = parser.getAttributeValue(null, ATTR_ID);
3306e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId)) {
3307e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "Invalid imi id found in subtypes.xml");
3308e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3309e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3310e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray = new ArrayList<InputMethodSubtype>();
3311e7c6998e0a953ae55487d4fe122739646f9280aasatok                        allSubtypes.put(currentImiId, tempSubtypesArray);
3312e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } else if (NODE_SUBTYPE.equals(nodeName)) {
3313e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
3314e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "IME uninstalled or not valid.: " + currentImiId);
3315e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3316e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3317e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int icon = Integer.valueOf(
3318e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_ICON));
3319e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int label = Integer.valueOf(
3320e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_LABEL));
3321e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeLocale =
3322e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LOCALE);
3323e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeMode =
3324e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
3325e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeExtraValue =
3326e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
33274a28bde70e23b2ed151d52690da702da7f23cf5esatok                        final boolean isAuxiliary = "1".equals(String.valueOf(
33284a28bde70e23b2ed151d52690da702da7f23cf5esatok                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
3329e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype =
3330e7c6998e0a953ae55487d4fe122739646f9280aasatok                                new InputMethodSubtype(label, icon, imeSubtypeLocale,
3331e7c6998e0a953ae55487d4fe122739646f9280aasatok                                        imeSubtypeMode, imeSubtypeExtraValue, isAuxiliary);
3332e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray.add(subtype);
3333e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3334e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3335e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (XmlPullParserException e) {
3336e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3337e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3338e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3339e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3340e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3341e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (NumberFormatException e) {
3342e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3343e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3344e7c6998e0a953ae55487d4fe122739646f9280aasatok            } finally {
3345e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fis != null) {
3346e7c6998e0a953ae55487d4fe122739646f9280aasatok                    try {
3347e7c6998e0a953ae55487d4fe122739646f9280aasatok                        fis.close();
3348e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } catch (java.io.IOException e1) {
3349e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "Failed to close.");
3350e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3351e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3352e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3353e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3354e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
3355e7c6998e0a953ae55487d4fe122739646f9280aasatok
33569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
33579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
33589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
33599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3360ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
33619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Permission Denial: can't dump InputMethodManager from from pid="
33629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
33639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
33649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
33659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
33669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
33679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IInputMethod method;
33689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState client;
3369ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
33709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(pw);
3371ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
33729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
33739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("Current Input Method Manager state:");
33749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mMethodList.size();
33759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Input Methods:");
33769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
33779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo info = mMethodList.get(i);
33789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  InputMethod #" + i + ":");
33799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.dump(p, "    ");
33809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
33819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Clients:");
33829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState ci : mClients.values()) {
33839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  Client " + ci + ":");
33849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    client=" + ci.client);
33859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    inputContext=" + ci.inputContext);
33869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    sessionRequested=" + ci.sessionRequested);
33879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    curSession=" + ci.curSession);
33889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3389105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            p.println("  mCurMethodId=" + mCurMethodId);
33909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = mCurClient;
3391b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
3392b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
33939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
33949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mBoundToMethod=" + mBoundToMethod);
33959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurToken=" + mCurToken);
33969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurIntent=" + mCurIntent);
33979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = mCurMethod;
33989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurMethod=" + mCurMethod);
33999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mEnabledSession=" + mEnabledSession);
34009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mShowRequested=" + mShowRequested
34019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
34029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowForced=" + mShowForced
34039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mInputShown=" + mInputShown);
3404cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            p.println("  mSystemReady=" + mSystemReady + " mScreenOn=" + mScreenOn);
34059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3406ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3407b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
34089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (client != null) {
34099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
34109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
34119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                client.client.asBinder().dump(fd, args);
34129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
34139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method client dead: " + e);
34149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3415b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3416b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method client.");
34179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3418ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3419b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
34209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (method != null) {
34219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
34229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
34239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                method.asBinder().dump(fd, args);
34249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
34259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method service dead: " + e);
34269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3427b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3428b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method service.");
34299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
34309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
34319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3432