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
18a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukawimport android.annotation.NonNull;
19adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganovimport android.content.pm.PackageManagerInternal;
2021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport com.android.internal.content.PackageMonitor;
21d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
22d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils;
248e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.os.HandlerCaller;
26758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganovimport com.android.internal.os.SomeArgs;
27e7c6998e0a953ae55487d4fe122739646f9280aasatokimport com.android.internal.util.FastXmlSerializer;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputContext;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethod;
3052a53526265c801b70eaf6dab1acf5c3f628f8a6Michael Wrightimport com.android.internal.view.IInputSessionCallback;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodClient;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodManager;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodSession;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.InputBindResult;
35adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganovimport com.android.server.pm.UserManagerService;
36ef2ea1faf6449f97a2423ecbdecce664c58bcbe1Adam Lesinskiimport com.android.server.statusbar.StatusBarManagerService;
3701038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport com.android.server.wm.WindowManagerService;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
39e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlPullParser;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
41e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlSerializer;
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative;
444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.AppGlobals;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog;
46e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawaimport android.app.AppOpsManager;
474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.IUserSwitchObserver;
48f90a33e92a7c8d4040c0e660a62336eb7293d785satokimport android.app.KeyguardManager;
497cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.Notification;
507cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.NotificationManager;
51dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackbornimport android.app.PendingIntent;
525b927c431f54ea47c3333afb7940d79e2e863f1asatokimport android.content.BroadcastReceiver;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface.OnCancelListener;
58d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaokaimport android.content.DialogInterface.OnClickListener;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
60e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.content.IntentFilter;
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ServiceConnection;
626da35a0c1205398b7df4776e359f7794584fb128Brandon Ballingerimport android.content.pm.ApplicationInfo;
634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.content.pm.IPackageManager;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ResolveInfo;
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ServiceInfo;
67734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.content.pm.UserInfo;
68e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasaniimport android.content.res.Configuration;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver;
72505e3abb8dd0d8f594280b9510adef74623630d7Alan Viveretteimport android.graphics.drawable.Drawable;
73857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onoratoimport android.inputmethodservice.InputMethodService;
747b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wrightimport android.net.Uri;
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
761ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wrenimport android.os.Bundle;
77e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.os.Environment;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IInterface;
814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.IRemoteCallback;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.Process;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport android.os.ResultReceiver;
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.UserHandle;
90734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.os.UserManager;
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
937b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport android.text.TextUtils.SimpleStringSplitter;
94f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.text.style.SuggestionSpan;
957b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport android.util.ArrayMap;
967b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport android.util.ArraySet;
9739606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
99f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.util.LruCache;
100ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.util.Pair;
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
103e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Slog;
104e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Xml;
105d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaokaimport android.view.ContextThemeWrapper;
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
107c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.view.InputChannel;
10805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.LayoutInflater;
10905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.View;
11005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.ViewGroup;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
112ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.EditorInfo;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputBinding;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethod;
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodInfo;
1169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
117fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawaimport android.view.inputmethod.InputMethodManagerInternal;
118ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.InputMethodSubtype;
119443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawaimport android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
12005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.ArrayAdapter;
12101038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton;
12201038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton.OnCheckedChangeListener;
12305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.RadioButton;
12401038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.Switch;
12505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.TextView;
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
127e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.File;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
129e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileInputStream;
130e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileOutputStream;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
1339e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewiczimport java.nio.charset.StandardCharsets;
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
135688bd47fccf1a1373e6287bc49b5b33fad12b7f3satokimport java.util.Collections;
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
1377b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport java.util.HashSet;
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
1395b927c431f54ea47c3333afb7940d79e2e863f1asatokimport java.util.Locale;
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides a system service that manages input methods.
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InputMethodManagerService extends IInputMethodManager.Stub
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements ServiceConnection, Handler.Callback {
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
1477b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static final boolean DEBUG_RESTORE = DEBUG || false;
1486ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    static final String TAG = "InputMethodManagerService";
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1507b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    private static final char INPUT_METHOD_SEPARATOR = ':';
1517b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = ';';
1527b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
153d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka    static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1;
154d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka    static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 2;
155d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka    static final int MSG_SHOW_IM_CONFIG = 3;
156ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_INPUT = 1000;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_INPUT = 1010;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_SOFT_INPUT = 1020;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_HIDE_SOFT_INPUT = 1030;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_ATTACH_TOKEN = 1040;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_CREATE_SESSION = 1050;
163ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_START_INPUT = 2000;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_RESTART_INPUT = 2010;
166ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_METHOD = 3000;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_METHOD = 3010;
169a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn    static final int MSG_SET_ACTIVE = 3020;
170fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa    static final int MSG_SET_INTERACTIVE = 3030;
1713d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
172ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
17301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
17401038492ff0317f0d3cff54d8a7ee36bb31ff175satok
175bcacc322f83de1fe522081a20e0ac36ec8243763Satoshi Kataoka    static final long TIME_TO_RECONNECT = 3 * 1000;
176ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
177f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20;
178f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1798e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
180b6359414adabab2d64acc8ccc9e3b9c1b800b303satok    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
1818e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
1824e4569dab5c75804b01a19b2d6e6101b445c1c68satok
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Context mContext;
1847d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn    final Resources mRes;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Handler mHandler;
186d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final InputMethodSettings mSettings;
1879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final SettingsObserver mSettingsObserver;
1889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IWindowManager mIWindowManager;
1899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HandlerCaller mCaller;
190119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final boolean mHasFeature;
1915ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private InputMethodFileManager mFileManager;
19201038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final HardKeyboardListener mHardKeyboardListener;
19301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final WindowManagerService mWindowManagerService;
194e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa    private final AppOpsManager mAppOpsManager;
195ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1963d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
197ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // All known input methods.  mMethodMap also serves as the global
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // lock for this class.
200d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
201d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
202f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
203f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
204d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    private final InputMethodSubtypeSwitchingController mSwitchingController;
205ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2062c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    // Used to bring IME service up to visible adjustment while it is being shown.
2072c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    final ServiceConnection mVisibleConnection = new ServiceConnection() {
2082c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceConnected(ComponentName name, IBinder service) {
2092c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
2102c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
2112c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceDisconnected(ComponentName name) {
2122c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
2132c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    };
2142c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    boolean mVisibleBound = false;
2152c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
2167cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    // Ongoing notification
217661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private NotificationManager mNotificationManager;
218661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private KeyguardManager mKeyguardManager;
219661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private StatusBarManagerService mStatusBar;
2201ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren    private Notification.Builder mImeSwitcherNotification;
221661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private PendingIntent mImeSwitchPendingIntent;
222b858c732f665fe9610f2d913230ae625f44a8caasatok    private boolean mShowOngoingImeSwitcherForPhones;
2237cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean mNotificationShown;
2240a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok    private final boolean mImeSelectedOnBoot;
2257cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
2268c6d477d30e64f3dfae20250b8274ffb37ef7bfaTadashi G. Takaoka    static class SessionState {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ClientState client;
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethod method;
229c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
230c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        IInputMethodSession session;
231c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        InputChannel channel;
232ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "SessionState{uid " + client.uid + " pid " + client.pid
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " method " + Integer.toHexString(
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(method))
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " session " + Integer.toHexString(
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(session))
240c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    + " channel " + channel
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "}";
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState(ClientState _client, IInputMethod _method,
245c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                IInputMethodSession _session, InputChannel _channel) {
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = _method;
2489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            session = _session;
249c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            channel = _channel;
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
252ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
253c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    static final class ClientState {
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethodClient client;
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputContext inputContext;
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int uid;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int pid;
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final InputBinding binding;
259ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean sessionRequested;
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState curSession;
262ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ClientState{" + Integer.toHexString(
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.identityHashCode(this)) + " uid " + uid
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " pid " + pid + "}";
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState(IInputMethodClient _client, IInputContext _inputContext,
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int _uid, int _pid) {
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inputContext = _inputContext;
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uid = _uid;
2759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pid = _pid;
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
279ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, ClientState> mClients
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<IBinder, ClientState>();
282ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
284a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     * Set once the system is ready to run third party code.
285a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     */
286a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    boolean mSystemReady;
287ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
288a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    /**
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Id of the currently selected input method.
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurMethodId;
292ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The current binding sequence number, incremented every time there is
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new bind performed.
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCurSeq;
298ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The client that is currently bound to an input method.
3019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ClientState mCurClient;
303ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
305b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     * The last window token that gained focus.
306b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     */
307b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    IBinder mCurFocusedWindow;
308ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
309b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    /**
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input context last provided by the current client.
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputContext mCurInputContext;
313ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The attributes last provided by the current client.
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mCurAttribute;
318ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method ID of the input method service that we are currently
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * connected to or in the process of connecting to.
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurId;
324ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
326ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * The current subtype of the current input method.
327ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
328ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private InputMethodSubtype mCurrentSubtype;
329ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3304e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
331f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
332f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes =
333f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
334ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
335e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    // Was the keyguard locked when this client became current?
336e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean mCurClientInKeyguard;
337e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
338ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set to true if our ServiceConnection is currently actively bound to
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a service (whether or not we have gotten its IBinder back yet).
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mHaveConnection;
343ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if the client has asked for the input method to be shown.
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowRequested;
348ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were explicitly told to show the input method.
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowExplicitlyRequested;
353ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were forced to be shown.
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowForced;
358ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we last told the input method to show itself.
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputShown;
363ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The Intent used to connect to the current input method.
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Intent mCurIntent;
368ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The token we have made for the currently active input method, to
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * identify it in the future.
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mCurToken;
374ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If non-null, this is the input method service we are currently connected
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to.
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputMethod mCurMethod;
380ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time that we last initiated a bind to the input method, to determine
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if we should try to disconnect and reconnect to it.
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mLastBindTime;
386ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Have we called mCurMethod.bindInput()?
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mBoundToMethod;
391ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Currently enabled session.  Only touched by service thread, not
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * protected by a lock.
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SessionState mEnabledSession;
397ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
399fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa     * True if the device is currently interactive with user.  The value is true initially.
4009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
401fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa    boolean mIsInteractive = true;
402ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4033d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    int mCurUserActionNotificationSequenceNumber = 0;
4043d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
405857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
406d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
407d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    /**
408d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * A set of status bits regarding the active IME.
409d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     *
410d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <p>This value is a combination of following two bits:</p>
411d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dl>
412d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dt>{@link InputMethodService#IME_ACTIVE}</dt>
413d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dd>
414d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     *   If this bit is ON, connected IME is ready to accept touch/key events.
415d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * </dd>
416d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dt>{@link InputMethodService#IME_VISIBLE}</dt>
417d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dd>
418d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     *   If this bit is ON, some of IME view, e.g. software input, candidate view, is visible.
419d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * </dd>
420d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * </dl>
421d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <em>Do not update this value outside of setImeWindowStatus.</em>
422d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     */
423857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mImeWindowVis;
424857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
42505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog.Builder mDialogBuilder;
42605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog mSwitchingDialog;
42701038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private View mSwitchingDialogTitleView;
42805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private InputMethodInfo[] mIms;
42905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private int[] mSubtypeIds;
4305b927c431f54ea47c3333afb7940d79e2e863f1asatok    private Locale mLastSystemLocale;
4317b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    private boolean mShowImeWithHardKeyboard;
4324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
4334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final IPackageManager mIPackageManager;
434ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SettingsObserver extends ContentObserver {
43681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        int mUserId;
43781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        boolean mRegistered = false;
438fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        String mLastEnabled = "";
439fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn
44081482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        /**
44181482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa         * <em>This constructor must be called within the lock.</em>
44281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa         */
4439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SettingsObserver(Handler handler) {
4449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(handler);
44581482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        }
44681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa
44781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        public void registerContentObserverLocked(int userId) {
44881482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            if (mRegistered && mUserId == userId) {
44981482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                return;
45081482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            }
4519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver resolver = mContext.getContentResolver();
45281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            if (mRegistered) {
45381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mContext.getContentResolver().unregisterContentObserver(this);
45481482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mRegistered = false;
45581482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            }
45681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            if (mUserId != userId) {
45781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mLastEnabled = "";
45881482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mUserId = userId;
45981482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            }
4609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resolver.registerContentObserver(Settings.Secure.getUriFor(
46181482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this, userId);
462ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            resolver.registerContentObserver(Settings.Secure.getUriFor(
46381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.ENABLED_INPUT_METHODS), false, this, userId);
464b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok            resolver.registerContentObserver(Settings.Secure.getUriFor(
46581482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this, userId);
4667b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            resolver.registerContentObserver(Settings.Secure.getUriFor(
46781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this, userId);
46881482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            mRegistered = true;
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
470ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4717b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        @Override public void onChange(boolean selfChange, Uri uri) {
4727b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            final Uri showImeUri =
4737b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
4757b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                if (showImeUri.equals(uri)) {
4767b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateKeyboardFromSettingsLocked();
4777b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                } else {
4787b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    boolean enabledChanged = false;
4797b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    String newEnabled = mSettings.getEnabledInputMethodsStr();
4807b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    if (!mLastEnabled.equals(newEnabled)) {
4817b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        mLastEnabled = newEnabled;
4827b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        enabledChanged = true;
4837b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    }
4847b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateInputMethodsFromSettingsLocked(enabledChanged);
485fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
48881482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa
48981482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        @Override
49081482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        public String toString() {
49181482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            return "SettingsObserver{mUserId=" + mUserId + " mRegistered=" + mRegistered
49281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    + " mLastEnabled=" + mLastEnabled + "}";
49381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        }
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
495ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
4994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String action = intent.getAction();
500fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
501105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                hideInputMethodMenu();
502fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa                // No need to update mIsInteractive
503105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                return;
504734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani            } else if (Intent.ACTION_USER_ADDED.equals(action)
505734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                    || Intent.ACTION_USER_REMOVED.equals(action)) {
5062a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                updateCurrentProfileIds();
507734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                return;
5087b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
5097b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
5107b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                if (Settings.Secure.ENABLED_INPUT_METHODS.equals(name)) {
5117b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                    final String prevValue = intent.getStringExtra(
5127b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                            Intent.EXTRA_SETTING_PREVIOUS_VALUE);
5137b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                    final String newValue = intent.getStringExtra(
5147b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                            Intent.EXTRA_SETTING_NEW_VALUE);
5157b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                    restoreEnabledInputMethods(mContext, prevValue, newValue);
5167b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5188a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unexpected intent " + intent);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
522ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
5237b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // Apply the results of a restore operation to the set of enabled IMEs.  Note that this
5247b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // does not attempt to validate on the fly with any installed device policy, so must only
5257b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // be run in the context of initial device setup.
5267b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    //
5277b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // TODO: Move this method to InputMethodUtils with adding unit tests.
5287b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static void restoreEnabledInputMethods(Context context, String prevValue, String newValue) {
5297b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        if (DEBUG_RESTORE) {
5307b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "Restoring enabled input methods:");
5317b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "prev=" + prevValue);
5327b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, " new=" + newValue);
5337b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5347b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // 'new' is the just-restored state, 'prev' is what was in settings prior to the restore
5357b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        ArrayMap<String, ArraySet<String>> prevMap = parseInputMethodsAndSubtypesString(prevValue);
5367b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        ArrayMap<String, ArraySet<String>> newMap = parseInputMethodsAndSubtypesString(newValue);
5377b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5387b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // Merge the restored ime+subtype enabled states into the live state
5397b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        for (ArrayMap.Entry<String, ArraySet<String>> entry : newMap.entrySet()) {
5407b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final String imeId = entry.getKey();
5417b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            ArraySet<String> prevSubtypes = prevMap.get(imeId);
5427b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            if (prevSubtypes == null) {
5437b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                prevSubtypes = new ArraySet<String>(2);
5447b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                prevMap.put(imeId, prevSubtypes);
5457b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            }
5467b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            prevSubtypes.addAll(entry.getValue());
5477b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5487b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5497b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final String mergedImesAndSubtypesString = buildInputMethodsAndSubtypesString(prevMap);
5507b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        if (DEBUG_RESTORE) {
5517b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "Merged IME string:");
5527b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "     " + mergedImesAndSubtypesString);
5537b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5547b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        Settings.Secure.putString(context.getContentResolver(),
5557b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                Settings.Secure.ENABLED_INPUT_METHODS, mergedImesAndSubtypesString);
5567b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    }
5577b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5587b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // TODO: Move this method to InputMethodUtils with adding unit tests.
5597b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static String buildInputMethodsAndSubtypesString(ArrayMap<String, ArraySet<String>> map) {
5607b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // we want to use the canonical InputMethodSettings implementation,
5617b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // so we convert data structures first.
5627b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        List<Pair<String, ArrayList<String>>> imeMap =
5637b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new ArrayList<Pair<String, ArrayList<String>>>(4);
5647b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        for (ArrayMap.Entry<String, ArraySet<String>> entry : map.entrySet()) {
5657b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final String imeName = entry.getKey();
5667b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final ArraySet<String> subtypeSet = entry.getValue();
5677b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final ArrayList<String> subtypes = new ArrayList<String>(2);
5687b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            if (subtypeSet != null) {
5697b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                subtypes.addAll(subtypeSet);
5707b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            }
5717b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            imeMap.add(new Pair<String, ArrayList<String>>(imeName, subtypes));
5727b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5737b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        return InputMethodSettings.buildInputMethodsSettingString(imeMap);
5747b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    }
5757b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5767b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // TODO: Move this method to InputMethodUtils with adding unit tests.
5777b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString(
5787b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final String inputMethodsAndSubtypesString) {
5797b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final ArrayMap<String, ArraySet<String>> imeMap =
5807b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new ArrayMap<String, ArraySet<String>>();
5817b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
5827b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            return imeMap;
5837b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5847b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5857b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final SimpleStringSplitter typeSplitter =
5867b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new SimpleStringSplitter(INPUT_METHOD_SEPARATOR);
5877b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final SimpleStringSplitter subtypeSplitter =
5887b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR);
5897b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        List<Pair<String, ArrayList<String>>> allImeSettings =
5907b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString,
5917b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                        typeSplitter,
5927b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                        subtypeSplitter);
5937b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        for (Pair<String, ArrayList<String>> ime : allImeSettings) {
5947b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            ArraySet<String> subtypes = new ArraySet<String>();
5957b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            if (ime.second != null) {
5967b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                subtypes.addAll(ime.second);
5977b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            }
5987b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            imeMap.put(ime.first, subtypes);
5997b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
6007b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        return imeMap;
6017b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    }
6027b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
60321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
6044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private boolean isChangingPackagesOfCurrentUser() {
6054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final int userId = getChangingUserId();
6064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final boolean retval = userId == mSettings.getCurrentUserId();
6074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
60881f8b7c66750a0a89c8e6b6037136ca169c96f95satok                if (!retval) {
60981f8b7c66750a0a89c8e6b6037136ca169c96f95satok                    Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
61081f8b7c66750a0a89c8e6b6037136ca169c96f95satok                }
6114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
6124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return retval;
6134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
6144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
61621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
6174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
6184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return false;
6194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
62021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
6214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
62221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                final int N = mMethodList.size();
62321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curInputMethodId != null) {
62421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    for (int i=0; i<N; i++) {
62521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
62621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (imi.getId().equals(curInputMethodId)) {
62721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            for (String pkg : packages) {
62821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                if (imi.getPackageName().equals(pkg)) {
62921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    if (!doit) {
63021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        return true;
63121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    }
632723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                    resetSelectedInputMethodAndSubtypeLocked("");
63321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    chooseNewDefaultIMELocked();
63421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    return true;
63521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                }
63621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            }
63721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
63821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
63908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                }
64008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu            }
64121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return false;
64221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
643ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
64421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        @Override
64521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
6464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
6474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
6484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
64921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
6509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo curIm = null;
6514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int N = mMethodList.size();
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (curInputMethodId != null) {
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<N; i++) {
65521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
656e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imiId = imi.getId();
657e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (imiId.equals(curInputMethodId)) {
65821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            curIm = imi;
65921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
660e7c6998e0a953ae55487d4fe122739646f9280aasatok
66121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        int change = isPackageDisappearing(imi.getPackageName());
662e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (isPackageModified(imi.getPackageName())) {
663e7c6998e0a953ae55487d4fe122739646f9280aasatok                            mFileManager.deleteAllInputMethodSubtypes(imiId);
664e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
66521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (change == PACKAGE_TEMPORARY_CHANGE
66621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                || change == PACKAGE_PERMANENT_CHANGE) {
6678a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Input method uninstalled, disabling: "
66821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    + imi.getComponent());
66921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            setInputMethodEnabledLocked(imi.getId(), false);
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
673ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
674f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(
675f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        mMethodList, mMethodMap, false /* resetDefaultEnabledIme */);
67621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed = false;
678ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
67908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                if (curIm != null) {
68021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    int change = isPackageDisappearing(curIm.getPackageName());
68121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (change == PACKAGE_TEMPORARY_CHANGE
68221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            || change == PACKAGE_PERMANENT_CHANGE) {
68308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        ServiceInfo si = null;
68408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        try {
6854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            si = mIPackageManager.getServiceInfo(
6864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    curIm.getComponent(), 0, mSettings.getCurrentUserId());
6874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        } catch (RemoteException ex) {
68808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
68908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (si == null) {
69008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Uh oh, current input method is no longer around!
69108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Pick another one...
6928a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
693d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                            updateSystemUiLocked(mCurToken, 0 /* vis */, mBackDisposition);
69421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            if (!chooseNewDefaultIMELocked()) {
69508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                changed = true;
69608675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                curIm = null;
6978a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.i(TAG, "Unsetting current input method");
698723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                resetSelectedInputMethodAndSubtypeLocked("");
69908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
70008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
70108675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
70221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
703ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
70421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curIm == null) {
70521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // We currently don't have a default input method... is
70621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // one now available?
70721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    changed = chooseNewDefaultIMELocked();
70854d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                } else if (!changed && isPackageModified(curIm.getPackageName())) {
70954d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                    // Even if the current input method is still available, mCurrentSubtype could
71054d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                    // be obsolete when the package is modified in practice.
71154d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                    changed = true;
71221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
713ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
71421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (changed) {
715fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(false);
7169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
720ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
721c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private static final class MethodCallback extends IInputSessionCallback.Stub {
722e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard        private final InputMethodManagerService mParentIMMS;
723c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final IInputMethod mMethod;
724c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final InputChannel mChannel;
725ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
726c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        MethodCallback(InputMethodManagerService imms, IInputMethod method,
727c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel) {
728e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard            mParentIMMS = imms;
729c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mMethod = method;
730c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mChannel = channel;
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
732ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
733e7c6998e0a953ae55487d4fe122739646f9280aasatok        @Override
734c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        public void sessionCreated(IInputMethodSession session) {
7356b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            long ident = Binder.clearCallingIdentity();
7366b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            try {
7376b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                mParentIMMS.onSessionCreated(mMethod, session, mChannel);
7386b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            } finally {
7396b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                Binder.restoreCallingIdentity(ident);
7406b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            }
7419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
743ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
74401038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private class HardKeyboardListener
74501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            implements WindowManagerService.OnHardKeyboardStatusChangeListener {
74601038492ff0317f0d3cff54d8a7ee36bb31ff175satok        @Override
7477b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        public void onHardKeyboardStatusChange(boolean available) {
7487b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED,
7497b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        available ? 1 : 0));
75001038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
75101038492ff0317f0d3cff54d8a7ee36bb31ff175satok
7527b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        public void handleHardKeyboardStatusChange(boolean available) {
75301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            if (DEBUG) {
7547b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                Slog.w(TAG, "HardKeyboardStatusChanged: available=" + available);
75501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
75601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            synchronized(mMethodMap) {
75701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
75801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        && mSwitchingDialog.isShowing()) {
75901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mSwitchingDialogTitleView.findViewById(
76001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            com.android.internal.R.id.hard_keyboard_section).setVisibility(
76101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    available ? View.VISIBLE : View.GONE);
76201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
76301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
76401038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
76501038492ff0317f0d3cff54d8a7ee36bb31ff175satok    }
76601038492ff0317f0d3cff54d8a7ee36bb31ff175satok
76701038492ff0317f0d3cff54d8a7ee36bb31ff175satok    public InputMethodManagerService(Context context, WindowManagerService windowManager) {
7684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mIPackageManager = AppGlobals.getPackageManager();
7699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
7707d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn        mRes = context.getResources();
7719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new Handler(this);
77281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        // Note: SettingsObserver doesn't register observers in its constructor.
77381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        mSettingsObserver = new SettingsObserver(mHandler);
7749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIWindowManager = IWindowManager.Stub.asInterface(
7759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.WINDOW_SERVICE));
776ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
777e7c6998e0a953ae55487d4fe122739646f9280aasatok            @Override
7789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void executeMessage(Message msg) {
7799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleMessage(msg);
7809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
781ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        }, true /*asyncHandler*/);
78201038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mWindowManagerService = windowManager;
783e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
78401038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mHardKeyboardListener = new HardKeyboardListener();
785119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        mHasFeature = context.getPackageManager().hasSystemFeature(
786119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                PackageManager.FEATURE_INPUT_METHODS);
7877cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
7881ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren        Bundle extras = new Bundle();
7891ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren        extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
7901ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren        mImeSwitcherNotification = new Notification.Builder(mContext)
7911ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setSmallIcon(com.android.internal.R.drawable.ic_notification_ime_default)
7921ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setWhen(0)
7931ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setOngoing(true)
7941ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .addExtras(extras)
7951ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setCategory(Notification.CATEGORY_SYSTEM)
7961ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setColor(com.android.internal.R.color.system_notification_accent_color);
797590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
7987cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
799683e2383c8549f95e00bade15daed3dbddf13950satok        mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
800b858c732f665fe9610f2d913230ae625f44a8caasatok
801b858c732f665fe9610f2d913230ae625f44a8caasatok        mShowOngoingImeSwitcherForPhones = false;
8027cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
8034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final IntentFilter broadcastFilter = new IntentFilter();
8044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
805734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
806734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
8077b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        broadcastFilter.addAction(Intent.ACTION_SETTING_RESTORED);
8084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
809ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
8107cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mNotificationShown = false;
8114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        int userId = 0;
8124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        try {
8134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            ActivityManagerNative.getDefault().registerUserSwitchObserver(
8144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    new IUserSwitchObserver.Stub() {
8154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
8164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
8175ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            synchronized(mMethodMap) {
8185ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                                switchUserLocked(newUserId);
8195ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            }
8204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            if (reply != null) {
8214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                try {
8224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    reply.sendResult(null);
8234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                } catch (RemoteException e) {
8244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                }
8254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            }
8264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
8274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
8294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
8304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
831429796226a8831af63a6303a58329f6b68f7b100Kenny Guy
832429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                        @Override
833429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                        public void onForegroundProfileSwitch(int newProfileId) {
834429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                            // Ignore.
835429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                        }
8364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    });
8374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
8384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } catch (RemoteException e) {
8394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
8404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
84181f8b7c66750a0a89c8e6b6037136ca169c96f95satok        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
842913a8925c07e854a80bf5df87561f290d3a56d61satok
843d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        // mSettings should be created before buildInputMethodListLocked
844df31ae6a3011d47421a6ac10021f9649dc34a156satok        mSettings = new InputMethodSettings(
8454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
846adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov
847adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov        // Let the package manager query which are the default imes
848adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov        // as they get certain permissions granted by default.
849adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov        PackageManagerInternal packageManagerInternal = LocalServices.getService(
850adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                PackageManagerInternal.class);
851adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov        packageManagerInternal.setImePackagesProvider(
852adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                new PackageManagerInternal.PackagesProvider() {
853adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                    @Override
854adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                    public String[] getPackages(int userId) {
855adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                        synchronized (mMethodMap) {
856adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            final int currentUserId = mSettings.getCurrentUserId();
857adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            // TODO: We are switching the current user id in the settings
858adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            // object to query it and then revert the user id. Ideally, we
859adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            // should call a API in settings with the user id as an argument.
860adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            mSettings.setCurrentUserId(userId);
861adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            List<InputMethodInfo> imes = mSettings
862adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                                    .getEnabledInputMethodListLocked();
863adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            String[] packageNames = null;
864adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            if (imes != null) {
865adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                                final int imeCount = imes.size();
866adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                                packageNames = new String[imeCount];
867adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                                for (int i = 0; i < imeCount; i++) {
868adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                                    InputMethodInfo ime = imes.get(i);
869adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                                    packageNames[i] = ime.getPackageName();
870adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                                }
871adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            }
872adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            mSettings.setCurrentUserId(currentUserId);
873adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                            return packageNames;
874adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                        }
875adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                    }
876adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov                });
877adc1cf46045ae756d3a9ccbccf6b0f894e4c1eddSvet Ganov
8782a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
8795ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, userId);
8805a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
8815a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
8825a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSettings, context);
8835a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
8840a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
8850a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        // Just checking if defaultImiId is empty or not
8864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
887f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (DEBUG) {
888f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "Initial default ime = " + defaultImiId);
889f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
8900a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
8910a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
8925a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
8935a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            buildInputMethodListLocked(mMethodList, mMethodMap,
8945a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
8955a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
896d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        mSettings.enableAllIMEsIfThereIsNoEnabledIME();
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8980a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!mImeSelectedOnBoot) {
8990a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            Slog.w(TAG, "No IME selected. Choose the most applicable IME.");
9005a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            synchronized (mMethodMap) {
9015a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                resetDefaultImeLocked(context);
9025a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
9035b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9045b927c431f54ea47c3333afb7940d79e2e863f1asatok
9055a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
90681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            mSettingsObserver.registerContentObserverLocked(userId);
9075a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            updateFromSettingsLocked(true);
9085a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
9095b927c431f54ea47c3333afb7940d79e2e863f1asatok
9105b927c431f54ea47c3333afb7940d79e2e863f1asatok        // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
9115b927c431f54ea47c3333afb7940d79e2e863f1asatok        // according to the new system locale.
9125b927c431f54ea47c3333afb7940d79e2e863f1asatok        final IntentFilter filter = new IntentFilter();
9135b927c431f54ea47c3333afb7940d79e2e863f1asatok        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
9145b927c431f54ea47c3333afb7940d79e2e863f1asatok        mContext.registerReceiver(
9155b927c431f54ea47c3333afb7940d79e2e863f1asatok                new BroadcastReceiver() {
9165b927c431f54ea47c3333afb7940d79e2e863f1asatok                    @Override
9175b927c431f54ea47c3333afb7940d79e2e863f1asatok                    public void onReceive(Context context, Intent intent) {
9185b927c431f54ea47c3333afb7940d79e2e863f1asatok                        synchronized(mMethodMap) {
919ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            resetStateIfCurrentLocaleChangedLocked();
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9225b927c431f54ea47c3333afb7940d79e2e863f1asatok                }, filter);
923fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        LocalServices.addService(InputMethodManagerInternal.class, new LocalServiceImpl(mHandler));
9245b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
9255b927c431f54ea47c3333afb7940d79e2e863f1asatok
9265b927c431f54ea47c3333afb7940d79e2e863f1asatok    private void resetDefaultImeLocked(Context context) {
9275b927c431f54ea47c3333afb7940d79e2e863f1asatok        // Do not reset the default (current) IME when it is a 3rd-party IME
9288e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        if (mCurMethodId != null
9298e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
9305b927c431f54ea47c3333afb7940d79e2e863f1asatok            return;
9315b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9325b927c431f54ea47c3333afb7940d79e2e863f1asatok
9335b927c431f54ea47c3333afb7940d79e2e863f1asatok        InputMethodInfo defIm = null;
9345b927c431f54ea47c3333afb7940d79e2e863f1asatok        for (InputMethodInfo imi : mMethodList) {
9356aa037887800e34bd057585106609236c950ca22Yohei Yukawa            if (defIm == null && mSystemReady) {
9366aa037887800e34bd057585106609236c950ca22Yohei Yukawa                final Locale systemLocale = context.getResources().getConfiguration().locale;
9376aa037887800e34bd057585106609236c950ca22Yohei Yukawa                if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
9386aa037887800e34bd057585106609236c950ca22Yohei Yukawa                        true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
9396aa037887800e34bd057585106609236c950ca22Yohei Yukawa                        InputMethodUtils.SUBTYPE_MODE_ANY)) {
9405b927c431f54ea47c3333afb7940d79e2e863f1asatok                    defIm = imi;
9415b927c431f54ea47c3333afb7940d79e2e863f1asatok                    Slog.i(TAG, "Selected default: " + imi.getId());
9425b927c431f54ea47c3333afb7940d79e2e863f1asatok                }
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9445b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9455b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm == null && mMethodList.size() > 0) {
9468e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            defIm = InputMethodUtils.getMostApplicableDefaultIME(
9478e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
9485baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            if (defIm != null) {
9495baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim                Slog.i(TAG, "Default found, using " + defIm.getId());
9505baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            } else {
9515baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim                Slog.i(TAG, "No default found");
9525baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            }
9535b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9545b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm != null) {
9555b927c431f54ea47c3333afb7940d79e2e863f1asatok            setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
9565b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9575b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
9585b927c431f54ea47c3333afb7940d79e2e863f1asatok
9597f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka    private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
9607f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            final boolean resetDefaultEnabledIme) {
9614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!mSystemReady) {
9624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // not system ready
9634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
9644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final Locale newLocale = mRes.getConfiguration().locale;
9664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!updateOnlyWhenLocaleChanged
9674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
9684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
9694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                hideCurrentInputLocked(0, null);
9704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurMethodId = null;
9712ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
9724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
9734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
9744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.i(TAG, "Locale has been changed to " + newLocale);
9754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
9767f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            buildInputMethodListLocked(mMethodList, mMethodMap, resetDefaultEnabledIme);
9774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
9784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selectedImiId = mSettings.getSelectedInputMethod();
9794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (TextUtils.isEmpty(selectedImiId)) {
9804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // This is the first time of the user switch and
9814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // set the current ime to the proper one.
9824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    resetDefaultImeLocked(mContext);
9834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
984d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka            } else {
985d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                // If the locale is changed, needs to reset the default ime
986d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                resetDefaultImeLocked(mContext);
9874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
988fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            updateFromSettingsLocked(true);
9894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            mLastSystemLocale = newLocale;
9904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
9914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                try {
9924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    startInputInnerLocked();
9934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } catch (RuntimeException e) {
9944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    Slog.w(TAG, "Unexpected exception", e);
9954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
9964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
9974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
1000ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka    private void resetStateIfCurrentLocaleChangedLocked() {
10017f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */,
10027f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka                true /* resetDefaultImeLocked */);
10034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
10044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
10055ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private void switchUserLocked(int newUserId) {
100690bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa        if (DEBUG) Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
100790bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa                + " currentUserId=" + mSettings.getCurrentUserId());
100890bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
100981482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        // ContentObserver should be registered again when the user is changed
101081482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        mSettingsObserver.registerContentObserverLocked(newUserId);
10114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mSettings.setCurrentUserId(newUserId);
10122a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
10135ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        // InputMethodFileManager should be reset when the user is changed
10145ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
10157f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
101690bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
101790bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa        if (DEBUG) Slog.d(TAG, "Switching user stage 2/3. newUserId=" + newUserId
101890bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa                + " defaultImiId=" + defaultImiId);
101990bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
10207c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // For secondary users, the list of enabled IMEs may not have been updated since the
10217c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // callbacks to PackageMonitor are ignored for the secondary user. Here, defaultImiId may
10227c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // not be empty even if the IME has been uninstalled by the primary user.
10237c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // Even in such cases, IMMS works fine because it will find the most applicable
10247c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // IME for that user.
1025ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
10267f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(false  /* updateOnlyWhenLocaleChanged */,
1027ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                initialUserSwitch /* needsToResetDefaultIme */);
1028ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        if (initialUserSwitch) {
1029094c71fd5c0b6b7ce4cd71d097d226a6a1acfc90Yohei Yukawa            InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
1030094c71fd5c0b6b7ce4cd71d097d226a6a1acfc90Yohei Yukawa                    mSettings.getEnabledInputMethodListLocked(), newUserId,
1031094c71fd5c0b6b7ce4cd71d097d226a6a1acfc90Yohei Yukawa                    mContext.getBasePackageName());
1032ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        }
103390bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
103490bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa        if (DEBUG) Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId
103590bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa                + " selectedIme=" + mSettings.getSelectedInputMethod());
10364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
10374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
10382a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy    void updateCurrentProfileIds() {
10392a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        List<UserInfo> profiles =
10402a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
10412a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
10422a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        for (int i = 0; i < currentProfileIds.length; i++) {
10432a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy            currentProfileIds[i] = profiles.get(i).id;
1044734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        }
10452a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        mSettings.setCurrentProfileIds(currentProfileIds);
1046734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani    }
1047734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws RemoteException {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.onTransact(code, data, reply, flags);
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The input method manager only throws security exceptions, so let's
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // log all others.
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!(e instanceof SecurityException)) {
1057164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf(TAG, "Input Method Manager Crash", e);
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1063a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning(StatusBarManagerService statusBar) {
1064a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        synchronized (mMethodMap) {
10654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
10664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "--- systemReady");
10674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
1068a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            if (!mSystemReady) {
1069a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn                mSystemReady = true;
10704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mKeyguardManager =
10714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
1072661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mNotificationManager = (NotificationManager)
1073661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
1074661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mStatusBar = statusBar;
1075661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                statusBar.setIconVisibility("ime", false);
1076d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition);
1077b858c732f665fe9610f2d913230ae625f44a8caasatok                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
1078b858c732f665fe9610f2d913230ae625f44a8caasatok                        com.android.internal.R.bool.show_ongoing_ime_switcher);
107901038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mShowOngoingImeSwitcherForPhones) {
108001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mWindowManagerService.setOnHardKeyboardStatusChangeListener(
108101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mHardKeyboardListener);
108201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
1083f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(mMethodList, mMethodMap,
1084f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
10850a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (!mImeSelectedOnBoot) {
10860a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                    Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
1087ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    resetStateIfCurrentLocaleChangedLocked();
1088094c71fd5c0b6b7ce4cd71d097d226a6a1acfc90Yohei Yukawa                    InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mIPackageManager,
1089094c71fd5c0b6b7ce4cd71d097d226a6a1acfc90Yohei Yukawa                            mSettings.getEnabledInputMethodListLocked(),
1090094c71fd5c0b6b7ce4cd71d097d226a6a1acfc90Yohei Yukawa                            mSettings.getCurrentUserId(), mContext.getBasePackageName());
10910a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
10920a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                mLastSystemLocale = mRes.getConfiguration().locale;
1093cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                try {
1094cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    startInputInnerLocked();
1095cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                } catch (RuntimeException e) {
10968a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Unexpected exception", e);
1097cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1098a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            }
1099a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
11009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1101ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
11024e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // ---------------------------------------------------------------------------------------
11034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
11044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 1) it comes from the system process
11054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 2) the calling process' user id is identical to the current user id IMMS thinks.
11064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean calledFromValidUser() {
11074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int uid = Binder.getCallingUid();
11084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int userId = UserHandle.getUserId(uid);
11094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
11104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
11114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
11124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + " calling userId = " + userId + ", foreground user id = "
111387c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
111487c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + InputMethodUtils.getApiCallStack());
11154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
11162a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
11174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return true;
11184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1119135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka
1120135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
1121135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // foreground user, not for the user of that process. Accordingly InputMethodManagerService
1122135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // must not manage background users' states in any functions.
1123135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Note that privacy-sensitive IPCs, such as setInputMethod, are still securely guarded
1124135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // by a token.
1125135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        if (mContext.checkCallingOrSelfPermission(
1126135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1127135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        == PackageManager.PERMISSION_GRANTED) {
1128135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            if (DEBUG) {
1129135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                Slog.d(TAG, "--- Access granted because the calling process has "
1130135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        + "the INTERACT_ACROSS_USERS_FULL permission");
1131135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            }
1132135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            return true;
1133135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        }
11340766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka        Slog.w(TAG, "--- IPC called from background users. Ignore. \n"
11350766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                + InputMethodUtils.getStackTrace());
1136135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        return false;
11374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
11384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
113922c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
114022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    /**
114122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * Returns true iff the caller is identified to be the current input method with the token.
114222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @param token The window token given to the input method when it was started.
114322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @return true if and only if non-null valid token is specified.
114422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     */
114522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    private boolean calledWithValidToken(IBinder token) {
114622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        if (token == null || mCurToken != token) {
114722c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            return false;
114822c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        }
114922c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        return true;
115022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    }
115122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
11524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean bindCurrentInputMethodService(
11534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Intent service, ServiceConnection conn, int flags) {
11544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (service == null || conn == null) {
11554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
11564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
11574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
115827b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani        return mContext.bindServiceAsUser(service, conn, flags,
115927b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                new UserHandle(mSettings.getCurrentUserId()));
11604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
11614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
1162e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getInputMethodList() {
11644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
11654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
11664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
11674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
11689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
11699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ArrayList<InputMethodInfo>(mMethodList);
11709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1173e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
11749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getEnabledInputMethodList() {
11754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
11764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
11774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
11784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
11799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1180d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return mSettings.getEnabledInputMethodListLocked();
11819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11848e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    /**
1185b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka     * @param imiId if null, returns enabled subtypes for the current imi
11868e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     * @return enabled subtypes of the specified imi
11878e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     */
1188e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1189b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
119016331c8a1d33defccc5cbb18694def79196c921bsatok            boolean allowsImplicitlySelectedSubtypes) {
11914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
11924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
1193b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            return Collections.<InputMethodSubtype>emptyList();
11944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
119567ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        synchronized (mMethodMap) {
1196b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            final InputMethodInfo imi;
1197b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imiId == null && mCurMethodId != null) {
11988e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                imi = mMethodMap.get(mCurMethodId);
1199b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            } else {
1200b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                imi = mMethodMap.get(imiId);
1201b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            }
1202b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imi == null) {
1203b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                return Collections.<InputMethodSubtype>emptyList();
12048e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            }
12058e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            return mSettings.getEnabledInputMethodSubtypeListLocked(
12068e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mContext, imi, allowsImplicitlySelectedSubtypes);
120767ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        }
120867ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok    }
120967ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok
1210e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addClient(IInputMethodClient client,
12129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IInputContext inputContext, int uid, int pid) {
12134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
12144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
12154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
12169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClients.put(client.asBinder(), new ClientState(client,
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    inputContext, uid, pid));
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1221ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1222e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeClient(IInputMethodClient client) {
12244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
12254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
12264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1228c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ClientState cs = mClients.remove(client.asBinder());
1229c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (cs != null) {
1230c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
1231c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1234ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void executeOrSendMessage(IInterface target, Message msg) {
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         if (target.asBinder() instanceof Binder) {
12379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             mCaller.sendMessage(msg);
12389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         } else {
12399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             handleMessage(msg);
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             msg.recycle();
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         }
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1243ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1244b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void unbindCurrentClientLocked() {
12459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != null) {
12468a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client = "
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurClient.client.asBinder());
12489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBoundToMethod) {
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBoundToMethod = false;
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_INPUT, mCurMethod));
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1255a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn
1256a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1257a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    MSG_SET_ACTIVE, 0, mCurClient));
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
12599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient.sessionRequested = false;
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient = null;
1262ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1263105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1266ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getImeShowFlags() {
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
12699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
12709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_FORCED
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    | InputMethod.SHOW_EXPLICIT;
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mShowExplicitlyRequested) {
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_EXPLICIT;
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1277ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getAppShowFlags() {
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_FORCED;
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mShowExplicitlyRequested) {
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_IMPLICIT;
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
12869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1287ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12887663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult attachNewInputLocked(boolean initial) {
12899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBoundToMethod) {
12909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
12929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBoundToMethod = true;
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SessionState session = mCurClient.curSession;
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initial) {
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_START_INPUT, session, mCurInputContext, mCurAttribute));
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_RESTART_INPUT, session, mCurInputContext, mCurAttribute));
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowRequested) {
13038a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
13044df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            showCurrentInputLocked(getAppShowFlags(), null);
13059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
13061951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown        return new InputBindResult(session.session,
13073d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                (session.channel != null ? session.channel.dup() : null),
13083d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1310ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBindResult startInputLocked(IInputMethodClient client,
13127663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
13139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If no method is currently selected, do nothing.
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethodId == null) {
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNoBinding;
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1317ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState cs = mClients.get(client.asBinder());
13199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cs == null) {
13209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("unknown client "
13219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + client.asBinder());
13229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1323ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
13269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check with the window manager to make sure this client actually
13279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // has a window with focus.  If not, reject.  This is thread safe
13289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // because if the focus changes some time before or after, the
13299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // next client receiving focus that has any interest in input will
13309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // be calling through here after that change happens.
13318a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Starting input on non-focused client " + cs.client
13329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
13339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
13349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
13369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1337ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13387663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
13397663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    }
13407663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
1341a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw    InputBindResult startInputUncheckedLocked(@NonNull ClientState cs,
1342d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa            IInputContext inputContext, @NonNull EditorInfo attribute, int controlFlags) {
13437663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        // If no method is currently selected, do nothing.
13447663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        if (mCurMethodId == null) {
13457663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            return mNoBinding;
13467663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        }
13477663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
1348d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa        if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid,
1349d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa                attribute.packageName)) {
1350d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa            Slog.e(TAG, "Rejecting this client as it reported an invalid package name."
1351d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa                    + " uid=" + cs.uid + " package=" + attribute.packageName);
1352d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa            return mNoBinding;
1353a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw        }
1354a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != cs) {
1356e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            // Was the keyguard locked when switching over to the new client?
1357e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            mCurClientInKeyguard = isKeyguardLocked();
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the client is changing, we need to switch over to the new
13599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // one.
1360b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
13618a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "switching to client: client = "
1362e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the screen is on, inform the new client it is active
1365fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            if (mIsInteractive) {
1366a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                executeOrSendMessage(cs.client, mCaller.obtainMessageIO(
1367fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa                        MSG_SET_ACTIVE, mIsInteractive ? 1 : 0, cs));
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1370ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Bump up the sequence for this client and attach it.
13729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurSeq++;
13739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurSeq <= 0) mCurSeq = 1;
13749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurClient = cs;
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurInputContext = inputContext;
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurAttribute = attribute;
1377ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check if the input method is changing.
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurId != null && mCurId.equals(mCurMethodId)) {
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cs.curSession != null) {
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Fast case: if we are already connected to the input method,
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // then just return it.
13837663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return attachNewInputLocked(
13847663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
13859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mHaveConnection) {
13879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
13889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Return to client, and we will get back with it when
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we have had a session made for it.
1390c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(cs);
13913d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    return new InputBindResult(null, null, mCurId, mCurSeq,
13923d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            mCurUserActionNotificationSequenceNumber);
13939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (SystemClock.uptimeMillis()
13949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        < (mLastBindTime+TIME_TO_RECONNECT)) {
13959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // In this case we have connected to the service, but
13969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // don't yet have its interface.  If it hasn't been too
13979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // long since we did the connection, we'll return to
13989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the client and wait to get the service interface so
13999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we can report back.  If it has been too long, we want
14009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to fall through so we can try a disconnect/reconnect
14019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to see if we can get back in touch with the service.
14023d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    return new InputBindResult(null, null, mCurId, mCurSeq,
14033d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            mCurUserActionNotificationSequenceNumber);
14049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1405ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                    EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
1406ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                            mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
14079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1410ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1411a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        return startInputInnerLocked();
1412a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    }
1413ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1414a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    InputBindResult startInputInnerLocked() {
1415a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (mCurMethodId == null) {
1416a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            return mNoBinding;
1417a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1418ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1419a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (!mSystemReady) {
1420a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // If the system is not yet ready, we shouldn't be running third
1421a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // party code.
14223d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            return new InputBindResult(null, null, mCurMethodId, mCurSeq,
14233d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    mCurUserActionNotificationSequenceNumber);
1424a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1425ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(mCurMethodId);
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
14299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1430ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14312ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn        unbindCurrentMethodLocked(false, true);
1432ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
14349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent.setComponent(info.getComponent());
1435dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1436dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                com.android.internal.R.string.input_method_binding_label);
1437dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1438dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
14394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
1440f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND
1441f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_SHOWING_UI)) {
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastBindTime = SystemClock.uptimeMillis();
14439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHaveConnection = true;
14449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurId = info.getId();
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurToken = new Binder();
14469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
1447ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
14489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIWindowManager.addWindowToken(mCurToken,
14499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14523d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            return new InputBindResult(null, null, mCurId, mCurSeq,
14533d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    mCurUserActionNotificationSequenceNumber);
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIntent = null;
14568a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Failure connecting to input method service: "
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurIntent);
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
14609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1461ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1462e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBindResult startInput(IInputMethodClient client,
14647663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
14654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
14664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
14674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final long ident = Binder.clearCallingIdentity();
14709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
14717663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return startInputLocked(client, inputContext, attribute, controlFlags);
14729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
14739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
14749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1477ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1478e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishInput(IInputMethodClient client) {
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1481ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1482e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceConnected(ComponentName name, IBinder service) {
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
14869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCurMethod = IInputMethod.Stub.asInterface(service);
1487cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                if (mCurToken == null) {
14888a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Service connected without a token!");
14892ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                    unbindCurrentMethodLocked(false, false);
1490cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    return;
1491cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1492e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
1493cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
1494cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1496c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
1497c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(mCurClient);
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1503c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void onSessionCreated(IInputMethod method, IInputMethodSession session,
1504c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel channel) {
15059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && method != null
15079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && mCurMethod.asBinder() == method.asBinder()) {
15089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1509c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
15109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCurClient.curSession = new SessionState(mCurClient,
1511c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                            method, session, channel);
15127663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    InputBindResult res = attachNewInputLocked(true);
15139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (res.method != null) {
15149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
15159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                MSG_BIND_METHOD, mCurClient.client, res));
15169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1517c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return;
15189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1521c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1522c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        // Session abandoned.  Close its associated input channel.
1523c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        channel.dispose();
15249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1525ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
15262ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn    void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
15272c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mVisibleBound) {
15282c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
15292c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
15302c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
15312c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1532b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mHaveConnection) {
1533b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mContext.unbindService(this);
1534b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mHaveConnection = false;
1535b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1536ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1537b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mCurToken != null) {
1538b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            try {
15398a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
15402ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
1541e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    // The current IME is shown. Hence an IME switch (transition) is happening.
1542e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    mWindowManagerService.saveLastInputMethodWindowForTransition();
1543e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                }
1544b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mIWindowManager.removeWindowToken(mCurToken);
1545b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            } catch (RemoteException e) {
1546b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
1547b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mCurToken = null;
1548b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1549ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1550105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mCurId = null;
1551b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        clearCurMethodLocked();
1552ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1553b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (reportToClient && mCurClient != null) {
1554b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1555b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
1556b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1557b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    }
1558c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1559c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void requestClientSessionLocked(ClientState cs) {
1560c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (!cs.sessionRequested) {
1561c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
1562c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
1563c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            cs.sessionRequested = true;
1564c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
1565c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    MSG_CREATE_SESSION, mCurMethod, channels[1],
1566c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    new MethodCallback(this, mCurMethod, channels[0])));
1567c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
1568c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1569c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1570c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void clearClientSessionLocked(ClientState cs) {
1571c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        finishSessionLocked(cs.curSession);
1572c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.curSession = null;
1573c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.sessionRequested = false;
1574c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1575c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1576c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private void finishSessionLocked(SessionState sessionState) {
1577c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (sessionState != null) {
1578c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.session != null) {
1579c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                try {
1580c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    sessionState.session.finishSession();
1581c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } catch (RemoteException e) {
1582c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    Slog.w(TAG, "Session failed to close due to remote exception", e);
1583d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    updateSystemUiLocked(mCurToken, 0 /* vis */, mBackDisposition);
1584c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
1585c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.session = null;
1586c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
1587c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.channel != null) {
1588c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel.dispose();
1589c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel = null;
15900c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            }
15910c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor        }
15920c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor    }
1593ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1594b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void clearCurMethodLocked() {
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState cs : mClients.values()) {
1597c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
15989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15990c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor
1600c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            finishSessionLocked(mEnabledSession);
16010c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            mEnabledSession = null;
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurMethod = null;
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1604661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        if (mStatusBar != null) {
1605661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn            mStatusBar.setIconVisibility("ime", false);
1606661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        }
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1608ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1609e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceDisconnected(ComponentName name) {
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
16128a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mCurIntent=" + mCurIntent);
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && mCurIntent != null
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && name.equals(mCurIntent.getComponent())) {
1616b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                clearCurMethodLocked();
16179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We consider this to be a new bind attempt, since the system
16189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // should now try to restart the service for us.
16199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastBindTime = SystemClock.uptimeMillis();
16209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mShowRequested = mInputShown;
16219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputShown = false;
16229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
16249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
16259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1630f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
16319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
16329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
16339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
16349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
1635a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                if (!calledWithValidToken(token)) {
1636a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    final int uid = Binder.getCallingUid();
1637a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    Slog.e(TAG, "Ignoring updateStatusIcon due to an invalid token. uid:" + uid
1638a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                            + " token:" + token);
1639a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    return;
1640a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                }
16419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (iconId == 0) {
16428a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
1643661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1644661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", false);
1645661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (packageName != null) {
16478a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
16486179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    CharSequence contentDescription = null;
16496179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    try {
16504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        // Use PackageManager to load label
16514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        final PackageManager packageManager = mContext.getPackageManager();
16526179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        contentDescription = packageManager.getApplicationLabel(
16534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mIPackageManager.getApplicationInfo(packageName, 0,
16544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                        mSettings.getCurrentUserId()));
16554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    } catch (RemoteException e) {
16566179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        /* ignore */
16576179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    }
1658661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1659661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIcon("ime", packageName, iconId, 0,
1660661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                contentDescription  != null
1661661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                        ? contentDescription.toString() : null);
1662661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", true);
1663661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
16649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
16679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
16689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1671d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    private boolean shouldShowImeSwitcherLocked(int visibility) {
16727cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        if (!mShowOngoingImeSwitcherForPhones) return false;
1673807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk        if (mSwitchingDialog != null) return false;
16742c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        if (isScreenLocked()) return false;
1675d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false;
1676c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (mWindowManagerService.isHardKeyboardAvailable()) {
1677c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // When physical keyboard is attached, we show the ime switcher (or notification if
1678c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
1679c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // exists in the IME switcher dialog.  Might be OK to remove this condition once
1680c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live.
1681c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            return true;
1682c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        }
1683d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if ((visibility & InputMethodService.IME_VISIBLE) == 0) return false;
1684c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa
1685c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
1686c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        final int N = imis.size();
1687c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (N > 2) return true;
1688c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (N < 1) return false;
1689c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        int nonAuxCount = 0;
1690c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        int auxCount = 0;
1691c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        InputMethodSubtype nonAuxSubtype = null;
1692c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        InputMethodSubtype auxSubtype = null;
1693c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        for(int i = 0; i < N; ++i) {
1694c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            final InputMethodInfo imi = imis.get(i);
1695c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            final List<InputMethodSubtype> subtypes =
1696c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
1697c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            final int subtypeCount = subtypes.size();
1698c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            if (subtypeCount == 0) {
1699c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                ++nonAuxCount;
1700c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            } else {
1701c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                for (int j = 0; j < subtypeCount; ++j) {
1702c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    final InputMethodSubtype subtype = subtypes.get(j);
1703c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    if (!subtype.isAuxiliary()) {
1704c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        ++nonAuxCount;
1705c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        nonAuxSubtype = subtype;
1706c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    } else {
1707c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        ++auxCount;
1708c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        auxSubtype = subtype;
17097cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
17107cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
17117cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            }
1712c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        }
1713c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (nonAuxCount > 1 || auxCount > 1) {
1714c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            return true;
1715c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        } else if (nonAuxCount == 1 && auxCount == 1) {
1716c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            if (nonAuxSubtype != null && auxSubtype != null
1717c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
1718c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                            || auxSubtype.overridesImplicitlyEnabledSubtype()
1719c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                            || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
1720c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
1721c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                return false;
1722b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            }
1723c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            return true;
17247cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        }
1725c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        return false;
17267cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    }
17277cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
1728e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean isKeyguardLocked() {
1729e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
1730e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    }
1731e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
1732dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("deprecation")
1733f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
1734857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
1735d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if (!calledWithValidToken(token)) {
1736d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final int uid = Binder.getCallingUid();
1737d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            Slog.e(TAG, "Ignoring setImeWindowStatus due to an invalid token. uid:" + uid
1738d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    + " token:" + token);
1739d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            return;
1740d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1741d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1742d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        synchronized (mMethodMap) {
1743d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            mImeWindowVis = vis;
1744d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            mBackDisposition = backDisposition;
1745d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            updateSystemUiLocked(token, vis, backDisposition);
1746d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1747d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    }
1748d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1749d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    private void updateSystemUi(IBinder token, int vis, int backDisposition) {
1750d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        synchronized (mMethodMap) {
1751d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            updateSystemUiLocked(token, vis, backDisposition);
1752d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1753d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    }
1754d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1755d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    // Caution! This method is called in this class. Handle multi-user carefully
1756d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    private void updateSystemUiLocked(IBinder token, int vis, int backDisposition) {
1757d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if (!calledWithValidToken(token)) {
1758d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final int uid = Binder.getCallingUid();
1759d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            Slog.e(TAG, "Ignoring updateSystemUiLocked due to an invalid token. uid:" + uid
1760d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    + " token:" + token);
1761d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            return;
1762d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1763d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1764d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        // TODO: Move this clearing calling identity block to setImeWindowStatus after making sure
1765d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        // all updateSystemUi happens on system previlege.
17664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final long ident = Binder.clearCallingIdentity();
176706487a58be22b100daf3f950b9a1d25c3ea42aa2satok        try {
1768d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            // apply policy for binder calls
1769d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
1770d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                vis = 0;
177106487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
1772d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            // mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked().
1773d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis);
1774d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            if (mStatusBar != null) {
1775d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                mStatusBar.setImeWindowStatus(token, vis, backDisposition,
1776d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        needsToShowImeSwitcher);
1777d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            }
1778d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
1779d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            if (imi != null && needsToShowImeSwitcher) {
1780d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                // Used to load label
1781d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                final CharSequence title = mRes.getText(
1782d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        com.android.internal.R.string.select_input_method);
1783d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
1784d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        mContext, imi, mCurrentSubtype);
17851ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                mImeSwitcherNotification.setContentTitle(title)
17861ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                        .setContentText(summary)
17871ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                        .setContentIntent(mImeSwitchPendingIntent);
1788d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                if ((mNotificationManager != null)
1789d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        && !mWindowManagerService.hasNavigationBar()) {
1790d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    if (DEBUG) {
1791d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        Slog.d(TAG, "--- show notification: label =  " + summary);
1792661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
1793d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationManager.notifyAsUser(null,
1794d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                            com.android.internal.R.string.select_input_method,
17951ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                            mImeSwitcherNotification.build(), UserHandle.ALL);
1796d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationShown = true;
1797d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                }
1798d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            } else {
1799d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                if (mNotificationShown && mNotificationManager != null) {
1800d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    if (DEBUG) {
1801d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        Slog.d(TAG, "--- hide notification");
18027cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
1803d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationManager.cancelAsUser(null,
1804d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                            com.android.internal.R.string.select_input_method, UserHandle.ALL);
1805d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationShown = false;
18067cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
180706487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
180806487a58be22b100daf3f950b9a1d25c3ea42aa2satok        } finally {
180906487a58be22b100daf3f950b9a1d25c3ea42aa2satok            Binder.restoreCallingIdentity(ident);
181006487a58be22b100daf3f950b9a1d25c3ea42aa2satok        }
181106487a58be22b100daf3f950b9a1d25c3ea42aa2satok    }
181206487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1813e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1814f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
18154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
18164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
18174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1818f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1819f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
1820f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            for (int i = 0; i < spans.length; ++i) {
1821f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                SuggestionSpan ss = spans[i];
182242c5a1666c4e576ccd5974233513100aad2c1534satok                if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
1823f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                    mSecureSuggestionSpans.put(ss, currentImi);
1824f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                }
1825f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1826f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1827f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1828f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1829e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1830f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
18314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
18324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
18334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1834f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1835f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
1836f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            // TODO: Do not send the intent if the process of the targetImi is already dead.
1837f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            if (targetImi != null) {
1838f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final String[] suggestions = span.getSuggestions();
1839f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                if (index < 0 || index >= suggestions.length) return false;
184042c5a1666c4e576ccd5974233513100aad2c1534satok                final String className = span.getNotificationTargetClassName();
1841f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final Intent intent = new Intent();
1842f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // Ensures that only a class in the original IME package will receive the
1843f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // notification.
184442c5a1666c4e576ccd5974233513100aad2c1534satok                intent.setClassName(targetImi.getPackageName(), className);
1845f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
1846f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
1847f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
1848f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
1849f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                final long ident = Binder.clearCallingIdentity();
1850f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                try {
1851f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
1852f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                } finally {
1853f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    Binder.restoreCallingIdentity(ident);
1854f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                }
1855f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                return true;
1856f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1857f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1858f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        return false;
1859f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1860f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1861fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn    void updateFromSettingsLocked(boolean enabledMayChange) {
18627b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        updateInputMethodsFromSettingsLocked(enabledMayChange);
18637b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        updateKeyboardFromSettingsLocked();
18647b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    }
18657b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
18667b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
1867fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        if (enabledMayChange) {
1868fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
1869fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            for (int i=0; i<enabled.size(); i++) {
1870fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // We allow the user to select "disabled until used" apps, so if they
1871fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // are enabling one of those here we now need to make it enabled.
1872fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                InputMethodInfo imm = enabled.get(i);
1873fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                try {
1874fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
1875fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
1876fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            mSettings.getCurrentUserId());
18777987a3172b0502ea70a26d80e7cd16ca7e460035Satoshi Kataoka                    if (ai != null && ai.enabledSetting
1878fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
1879ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        if (DEBUG) {
1880ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            Slog.d(TAG, "Update state(" + imm.getId()
1881ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                                    + "): DISABLED_UNTIL_USED -> DEFAULT");
1882ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        }
1883fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
1884fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
18853fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(),
18863fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                mContext.getBasePackageName());
1887fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    }
1888fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                } catch (RemoteException e) {
1889fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
1890fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            }
1891fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        }
1892b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
1893b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
1894b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
1895b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // enabled.
18964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String id = mSettings.getSelectedInputMethod();
189703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        // There is no input method selected, try to choose new applicable input method.
189803eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
18994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            id = mSettings.getSelectedInputMethod();
190003eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        }
190103eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (!TextUtils.isEmpty(id)) {
19029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
19038e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
19049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException e) {
19058a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unknown input method from prefs: " + id, e);
1906105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mCurMethodId = null;
19072ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
19089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1909f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.clear();
1910b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        } else {
1911b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            // There is no longer an input method set, so stop any current one.
1912105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCurMethodId = null;
19132ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn            unbindCurrentMethodLocked(true, false);
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19153d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
19163d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
19173d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
19183d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
19193d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
19207b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
19217b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    }
19227b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
19237b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    public void updateKeyboardFromSettingsLocked() {
19247b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled();
19257b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        if (mSwitchingDialog != null
19267b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                && mSwitchingDialogTitleView != null
19277b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                && mSwitchingDialog.isShowing()) {
19287b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById(
19297b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    com.android.internal.R.id.hard_keyboard_switch);
19307b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
19317b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        }
19329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1933ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1934ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /* package */ void setInputMethodLocked(String id, int subtypeId) {
19359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(id);
19369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
1937913a8925c07e854a80bf5df87561f290d3a56d61satok            throw new IllegalArgumentException("Unknown id: " + id);
19389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1939ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1940e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        if (mCurClient != null && mCurAttribute != null) {
1941a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw            // We have already made sure that the package name belongs to the application's UID.
1942a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw            // No further UID check is required.
1943a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw            if (SystemConfig.getInstance().getFixedImeApps().contains(mCurAttribute.packageName)) {
1944a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw                return;
1945e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa            }
1946e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        }
1947e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa
1948d81e950265356c81276b73da68a535ffa48d72f0satok        // See if we need to notify a subtype change within the same IME.
19499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.equals(mCurMethodId)) {
1950d81e950265356c81276b73da68a535ffa48d72f0satok            final int subtypeCount = info.getSubtypeCount();
1951d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeCount <= 0) {
1952d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1953d81e950265356c81276b73da68a535ffa48d72f0satok            }
1954d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype oldSubtype = mCurrentSubtype;
1955d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype newSubtype;
1956d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeId >= 0 && subtypeId < subtypeCount) {
1957d81e950265356c81276b73da68a535ffa48d72f0satok                newSubtype = info.getSubtypeAt(subtypeId);
1958d81e950265356c81276b73da68a535ffa48d72f0satok            } else {
1959d81e950265356c81276b73da68a535ffa48d72f0satok                // If subtype is null, try to find the most applicable one from
1960d81e950265356c81276b73da68a535ffa48d72f0satok                // getCurrentInputMethodSubtype.
19614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                newSubtype = getCurrentInputMethodSubtypeLocked();
1962d81e950265356c81276b73da68a535ffa48d72f0satok            }
1963d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype == null || oldSubtype == null) {
1964d81e950265356c81276b73da68a535ffa48d72f0satok                Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
1965d81e950265356c81276b73da68a535ffa48d72f0satok                        + ", new subtype = " + newSubtype);
1966d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1967d81e950265356c81276b73da68a535ffa48d72f0satok            }
1968d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype != oldSubtype) {
1969d81e950265356c81276b73da68a535ffa48d72f0satok                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
1970d81e950265356c81276b73da68a535ffa48d72f0satok                if (mCurMethod != null) {
1971d81e950265356c81276b73da68a535ffa48d72f0satok                    try {
1972d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition);
1973d81e950265356c81276b73da68a535ffa48d72f0satok                        mCurMethod.changeInputMethodSubtype(newSubtype);
1974d81e950265356c81276b73da68a535ffa48d72f0satok                    } catch (RemoteException e) {
1975d81e950265356c81276b73da68a535ffa48d72f0satok                        Slog.w(TAG, "Failed to call changeInputMethodSubtype");
1976ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
1977ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                }
1978ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            }
19799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1981ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1982d81e950265356c81276b73da68a535ffa48d72f0satok        // Changing to a different IME.
19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long ident = Binder.clearCallingIdentity();
19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1985ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // Set a subtype to this input method.
1986ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // subtypeId the name of a subtype which will be set.
1987723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
1988723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
1989723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // because mCurMethodId is stored as a history in
1990723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // setSelectedInputMethodAndSubtypeLocked().
1991723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mCurMethodId = id;
19929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ActivityManagerNative.isSystemReady()) {
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
19951c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.putExtra("input_method_id", id);
1997cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani                mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1999b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2004ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
200542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20064df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean showSoftInput(IInputMethodClient client, int flags,
20074df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
20084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
20104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2011cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
20129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
20139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
20199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
20209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
2022cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
20234df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
20264df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2029ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2030e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
20314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return showCurrentInputLocked(flags, resultReceiver);
20329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
20349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2037ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
20399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = true;
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
20419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
20429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
20449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
20459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowForced = true;
20469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2047ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2048cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        if (!mSystemReady) {
2049cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            return false;
2050cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        }
2051ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res = false;
20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
2054e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
20554df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
20564df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
20574df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    resultReceiver));
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputShown = true;
20592c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            if (mHaveConnection && !mVisibleBound) {
20604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                bindCurrentInputMethodService(
2061f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                        mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
2062d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                                | Context.BIND_TREAT_LIKE_ACTIVITY
2063d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                                | Context.BIND_FOREGROUND_SERVICE);
20642c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                mVisibleBound = true;
20652c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            }
20664df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
20679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mHaveConnection && SystemClock.uptimeMillis()
206859b424c3b6121c9579fc5efcc785ba084072a5casatok                >= (mLastBindTime+TIME_TO_RECONNECT)) {
20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The client has asked to have the input method shown, but
20709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we have been sitting here too long with a connection to the
20719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // service and no interface received, so let's disconnect/connect
20729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to try to prod things along.
2073ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,
20749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemClock.uptimeMillis()-mLastBindTime,1);
207559b424c3b6121c9579fc5efcc785ba084072a5casatok            Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
20769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.unbindService(this);
20774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
20782c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                    | Context.BIND_NOT_VISIBLE);
20794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } else {
20804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
20814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
20824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
20834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2085ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
20879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2088ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
208942c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean hideSoftInput(IInputMethodClient client, int flags,
20914df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
20924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
20944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2095cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
20969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
20979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
20989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
21009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
21019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
21039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
21049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
21059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
2106cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
2107cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                                    + uid + ": " + client);
21084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
21099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
21114df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
21129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
21139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2114ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
21158a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
21164df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return hideCurrentInputLocked(flags, resultReceiver);
21179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
21199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
21209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2122ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
21234df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
21249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
21259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mShowExplicitlyRequested || mShowForced)) {
2126e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
21274df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
21289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
2130e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
21314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
21329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2133ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka
2134ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // There is a chance that IMM#hideSoftInput() is called in a transient state where
2135ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // IMMS#InputShown is already updated to be true whereas IMMS#mImeWindowVis is still waiting
2136ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // to be updated with the new value sent from IME process.  Even in such a transient state
2137ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // historically we have accepted an incoming call of IMM#hideSoftInput() from the
2138ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // application process as a valid request, and have even promised such a behavior with CTS
2139ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // since Android Eclair.  That's why we need to accept IMM#hideSoftInput() even when only
2140ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // IMMS#InputShown indicates that the software keyboard is shown.
2141ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
2142ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        final boolean shouldHideSoftInput = (mCurMethod != null) && (mInputShown ||
2143ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka                (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
21444df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res;
2145ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        if (shouldHideSoftInput) {
2146ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // The IME will report its visible state again after the following message finally
2147ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // delivered to the IME process as an IPC.  Hence the inconsistency between
2148ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
2149ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // the final state.
21504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
21514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
21524df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
21534df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
21544df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = false;
21559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21562c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mHaveConnection && mVisibleBound) {
21572c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
21582c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
21592c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
21609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputShown = false;
21619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = false;
21629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowExplicitlyRequested = false;
21639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowForced = false;
21644df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
21659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2166ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
216742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
21687663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
21697663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            int controlFlags, int softInputMode, int windowFlags,
21707663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            EditorInfo attribute, IInputContext inputContext) {
21718d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        // Needs to check the validity before clearing calling identity
21728d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        final boolean calledFromValidUser = calledFromValidUser();
21738d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
21747663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        InputBindResult res = null;
21759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
21769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
21779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
21788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
21797663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " controlFlags=#" + Integer.toHexString(controlFlags)
21809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " softInputMode=#" + Integer.toHexString(softInputMode)
21817663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " windowFlags=#" + Integer.toHexString(windowFlags));
2182ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
21837663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                ClientState cs = mClients.get(client.asBinder());
21847663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (cs == null) {
21857663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    throw new IllegalArgumentException("unknown client "
21867663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            + client.asBinder());
21877663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
21887663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
21897663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                try {
21907663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
21917663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // Check with the window manager to make sure this client actually
21927663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // has a window with focus.  If not, reject.  This is thread safe
21937663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // because if the focus changes some time before or after, the
21947663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // next client receiving focus that has any interest in input will
21957663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // be calling through here after that change happens.
21967663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        Slog.w(TAG, "Focus gain on non-focused client " + cs.client
21977663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
21987663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return null;
21999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
22007663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                } catch (RemoteException e) {
22019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2202ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
22038d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                if (!calledFromValidUser) {
22048d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "A background user is requesting window. Hiding IME.");
22058d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "If you want to interect with IME, you need "
22068d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                            + "android.permission.INTERACT_ACROSS_USERS_FULL");
22078d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    hideCurrentInputLocked(0, null);
22088d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    return null;
22098d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                }
22108d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
2211b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                if (mCurFocusedWindow == windowToken) {
2212ac92087a9a1c464d4b0a58c82dae01cbaa088e89Dianne Hackborn                    Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
22133573950e0b30178dc963de3fa00aba2ebcfd552dSatoshi Kataoka                            + " attribute=" + attribute + ", token = " + windowToken);
22147663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (attribute != null) {
22157663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return startInputUncheckedLocked(cs, inputContext, attribute,
22167663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                controlFlags);
22177663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    }
22187663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    return null;
2219b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
2220b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mCurFocusedWindow = windowToken;
2221ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
22227d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // Should we auto-show the IME even if the caller has not
22237d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // specified what should be done with it?
22247d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // We only do this automatically if the window can resize
22257d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // to accommodate the IME (so what the user sees will give
22267d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // them good context without input information being obscured
22277d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // by the IME) or if running on a large screen where there
22287d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // is more room for the target window + IME.
22297d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                final boolean doAutoShow =
22307d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
22317d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
22327d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        || mRes.getConfiguration().isLayoutSizeAtLeast(
22337d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                Configuration.SCREENLAYOUT_SIZE_LARGE);
22347663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                final boolean isTextEditor =
22357663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0;
22367663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
22377663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // We want to start input before showing the IME, but after closing
22387663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // it.  We want to do this after closing it to help the IME disappear
22397663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // more quickly (not get stuck behind it initializing itself for the
22407663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // new focused input, even if its window wants to hide the IME).
22417663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                boolean didStart = false;
2242a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw
22439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
22449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
22457d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        if (!isTextEditor || !doAutoShow) {
22469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
22479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // There is no focus view, and this window will
22489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // be behind any soft input window, so hide the
22499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // soft input window if it is shown.
22508a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
22514df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
22529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
22537d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        } else if (isTextEditor && doAutoShow && (softInputMode &
22547d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
22559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // There is a focus view, and we are navigating forward
22569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // into the window, so show the input window for the user.
22577663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // We only do this automatically if the window can resize
22587663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // to accommodate the IME (so what the user sees will give
22597d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // them good context without input information being obscured
22607d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // by the IME) or if running on a large screen where there
22617d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // is more room for the target window + IME.
22628a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
22637663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
22647663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
22657663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
22667663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
22677663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
22684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
22709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
22729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Do nothing.
22739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
22759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
22769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
22778a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
22784df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            hideCurrentInputLocked(0, null);
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
22809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
22828a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to hide input");
22834df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        hideCurrentInputLocked(0, null);
22849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
22869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
22888a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
22897663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
22907663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
22917663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
22927663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
22937663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
22944df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
22959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
22969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
22988a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to always show input");
22997663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        if (attribute != null) {
23007663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            res = startInputUncheckedLocked(cs, inputContext, attribute,
23017663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                    controlFlags);
23027663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            didStart = true;
23037663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        }
23044df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
23059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
23069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
23077663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
23087663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (!didStart && attribute != null) {
23097663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    res = startInputUncheckedLocked(cs, inputContext, attribute,
23107663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            controlFlags);
23117663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
23129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
23159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
23167663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
23177663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return res;
23189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2319ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
232042c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
232114e139179be7daab6ed452105387a3922752c219Seigo Nonaka    public void showInputMethodPickerFromClient(
232214e139179be7daab6ed452105387a3922752c219Seigo Nonaka            IInputMethodClient client, int auxiliarySubtypeMode) {
23234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
23279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurClient == null || client == null
23289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || mCurClient.client.asBinder() != client.asBinder()) {
232947a44916e2fb33cf4751906386d5f5c903b28d8bsatok                Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
2330cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + ": " + client);
23319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2333440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // Always call subtype picker, because subtype picker is a superset of input method
2334440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // picker.
233514e139179be7daab6ed452105387a3922752c219Seigo Nonaka            mHandler.sendMessage(mCaller.obtainMessageI(
233614e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode));
2337ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2338ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2339ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
234042c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethod(IBinder token, String id) {
23424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23452820351489537698ad153c6397edf3270455edc5satok        setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
23462820351489537698ad153c6397edf3270455edc5satok    }
23472820351489537698ad153c6397edf3270455edc5satok
234842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23492820351489537698ad153c6397edf3270455edc5satok    public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
23504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23532820351489537698ad153c6397edf3270455edc5satok        synchronized (mMethodMap) {
23542820351489537698ad153c6397edf3270455edc5satok            if (subtype != null) {
23554e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, id,
23564e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        InputMethodUtils.getSubtypeIdFromHashCode(mMethodMap.get(id),
23574e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                                subtype.hashCode()));
23582820351489537698ad153c6397edf3270455edc5satok            } else {
23592820351489537698ad153c6397edf3270455edc5satok                setInputMethod(token, id);
23602820351489537698ad153c6397edf3270455edc5satok            }
23612820351489537698ad153c6397edf3270455edc5satok        }
2362ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2363ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
236442c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
2365b416a71e56cdd50742eb897366a140775aa4cd61satok    public void showInputMethodAndSubtypeEnablerFromClient(
2366217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            IInputMethodClient client, String inputMethodId) {
23674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23694e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2370b416a71e56cdd50742eb897366a140775aa4cd61satok        synchronized (mMethodMap) {
2371b416a71e56cdd50742eb897366a140775aa4cd61satok            if (mCurClient == null || client == null
2372b416a71e56cdd50742eb897366a140775aa4cd61satok                || mCurClient.client.asBinder() != client.asBinder()) {
2373b416a71e56cdd50742eb897366a140775aa4cd61satok                Slog.w(TAG, "Ignoring showInputMethodAndSubtypeEnablerFromClient of: " + client);
2374b416a71e56cdd50742eb897366a140775aa4cd61satok            }
23757fee71f66afef6421b92fa48e63d4bc73f5d0c27satok            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
23767fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                    MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
2377b416a71e56cdd50742eb897366a140775aa4cd61satok        }
2378b416a71e56cdd50742eb897366a140775aa4cd61satok    }
2379b416a71e56cdd50742eb897366a140775aa4cd61satok
23804fc87d61c29886c848789208c9e32ba9ac4e5dd3satok    @Override
2381735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    public boolean switchToLastInputMethod(IBinder token) {
23824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23834e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
23844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2385735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        synchronized (mMethodMap) {
2386c445bcd0bce630948ee029d7c70b28226f0b6c9csatok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
23874fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            final InputMethodInfo lastImi;
2388208d5634047111811de16fb63c43d0bc8b4fe6desatok            if (lastIme != null) {
23894fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = mMethodMap.get(lastIme.first);
23904fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
23914fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = null;
23924fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
23934fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            String targetLastImiId = null;
23944fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            int subtypeId = NOT_A_SUBTYPE_ID;
23954fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (lastIme != null && lastImi != null) {
23964fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
23974fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
23984fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
23994fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        : mCurrentSubtype.hashCode();
24004fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // If the last IME is the same as the current IME and the last subtype is not
24014fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // defined, there is no need to switch to the last IME.
24024fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
24034fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    targetLastImiId = lastIme.first;
24048e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
24054fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
24064fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
24074fc87d61c29886c848789208c9e32ba9ac4e5dd3satok
24088e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            if (TextUtils.isEmpty(targetLastImiId)
24098e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    && !InputMethodUtils.canAddToLastInputMethod(mCurrentSubtype)) {
24104fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // This is a safety net. If the currentSubtype can't be added to the history
24114fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // and the framework couldn't find the last ime, we will make the last ime be
24124fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // the most applicable enabled keyboard subtype of the system imes.
24134fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
24144fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (enabled != null) {
24154fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final int N = enabled.size();
24164fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final String locale = mCurrentSubtype == null
24174fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            ? mRes.getConfiguration().locale.toString()
24184fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            : mCurrentSubtype.getLocale();
24194fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    for (int i = 0; i < N; ++i) {
24204fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        final InputMethodInfo imi = enabled.get(i);
24218e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        if (imi.getSubtypeCount() > 0 && InputMethodUtils.isSystemIme(imi)) {
24224fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            InputMethodSubtype keyboardSubtype =
24238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                    InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes,
24248e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.getSubtypes(imi),
24258e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, locale, true);
24264fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            if (keyboardSubtype != null) {
24274fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                targetLastImiId = imi.getId();
24288e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
24294fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                        imi, keyboardSubtype.hashCode());
24304fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                if(keyboardSubtype.getLocale().equals(locale)) {
24314fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                    break;
24324fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                }
24334fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            }
24344fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        }
24354fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    }
24364fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
24374fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
2438c445bcd0bce630948ee029d7c70b28226f0b6c9csatok
24394fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (!TextUtils.isEmpty(targetLastImiId)) {
2440c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                if (DEBUG) {
24414fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
24424fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            + ", from: " + mCurMethodId + ", " + subtypeId);
2443735cf38b8c7f8f91ad087511e44fe79018fa61d6satok                }
24444e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
2445c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                return true;
24464fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
24474fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                return false;
2448735cf38b8c7f8f91ad087511e44fe79018fa61d6satok            }
2449735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        }
2450735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    }
2451735cf38b8c7f8f91ad087511e44fe79018fa61d6satok
2452e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2453688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
24544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
24554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
24564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2457688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        synchronized (mMethodMap) {
2458a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2459a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2460a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring switchToNextInputMethod due to an invalid token. uid:" + uid
2461a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + " token:" + token);
2462a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2463a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
24645a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
2465688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                    onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
2466688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            if (nextSubtype == null) {
2467688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                return false;
2468688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            }
24694e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
24704e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    nextSubtype.mSubtypeId);
2471688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            return true;
2472688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        }
2473688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    }
2474688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok
2475688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    @Override
24762b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    public boolean shouldOfferSwitchingToNextInputMethod(IBinder token) {
24772b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        if (!calledFromValidUser()) {
24782b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return false;
24792b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
24802b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        synchronized (mMethodMap) {
2481a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2482a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2483a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring shouldOfferSwitchingToNextInputMethod due to an invalid "
2484a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + "token. uid:" + uid + " token:" + token);
2485a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2486a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
24875a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
24882b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                    false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
24892b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            if (nextSubtype == null) {
24902b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                return false;
24912b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            }
24922b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return true;
24932b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
24942b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    }
24952b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka
24962b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    @Override
249768f1b78b7b9139a0e34285ff641a664e664a14b8satok    public InputMethodSubtype getLastInputMethodSubtype() {
24984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
24994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
25004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
250168f1b78b7b9139a0e34285ff641a664e664a14b8satok        synchronized (mMethodMap) {
250268f1b78b7b9139a0e34285ff641a664e664a14b8satok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
250368f1b78b7b9139a0e34285ff641a664e664a14b8satok            // TODO: Handle the case of the last IME with no subtypes
250468f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastIme == null || TextUtils.isEmpty(lastIme.first)
250568f1b78b7b9139a0e34285ff641a664e664a14b8satok                    || TextUtils.isEmpty(lastIme.second)) return null;
250668f1b78b7b9139a0e34285ff641a664e664a14b8satok            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
250768f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastImi == null) return null;
250868f1b78b7b9139a0e34285ff641a664e664a14b8satok            try {
250968f1b78b7b9139a0e34285ff641a664e664a14b8satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
25108e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final int lastSubtypeId =
25118e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
25120e7d7d632309409e2bc51d5317cf7a92a7541433satok                if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
25130e7d7d632309409e2bc51d5317cf7a92a7541433satok                    return null;
25140e7d7d632309409e2bc51d5317cf7a92a7541433satok                }
25150e7d7d632309409e2bc51d5317cf7a92a7541433satok                return lastImi.getSubtypeAt(lastSubtypeId);
251668f1b78b7b9139a0e34285ff641a664e664a14b8satok            } catch (NumberFormatException e) {
251768f1b78b7b9139a0e34285ff641a664e664a14b8satok                return null;
251868f1b78b7b9139a0e34285ff641a664e664a14b8satok            }
251968f1b78b7b9139a0e34285ff641a664e664a14b8satok        }
252068f1b78b7b9139a0e34285ff641a664e664a14b8satok    }
252168f1b78b7b9139a0e34285ff641a664e664a14b8satok
2522e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2523ee5e77cafec2eae70890abdcc1646ed39b06edddsatok    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
25244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
25254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
25264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
252791e88122cf28a48fd2e2260da7d3d87dd437227asatok        // By this IPC call, only a process which shares the same uid with the IME can add
252891e88122cf28a48fd2e2260da7d3d87dd437227asatok        // additional input method subtypes to the IME.
2529ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
2530e7c6998e0a953ae55487d4fe122739646f9280aasatok        synchronized (mMethodMap) {
253191e88122cf28a48fd2e2260da7d3d87dd437227asatok            final InputMethodInfo imi = mMethodMap.get(imiId);
2532ee5e77cafec2eae70890abdcc1646ed39b06edddsatok            if (imi == null) return;
25334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String[] packageInfos;
25344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            try {
25354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
25364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } catch (RemoteException e) {
25374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.e(TAG, "Failed to get package infos");
25384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
25394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
254091e88122cf28a48fd2e2260da7d3d87dd437227asatok            if (packageInfos != null) {
254191e88122cf28a48fd2e2260da7d3d87dd437227asatok                final int packageNum = packageInfos.length;
254291e88122cf28a48fd2e2260da7d3d87dd437227asatok                for (int i = 0; i < packageNum; ++i) {
254391e88122cf28a48fd2e2260da7d3d87dd437227asatok                    if (packageInfos[i].equals(imi.getPackageName())) {
254491e88122cf28a48fd2e2260da7d3d87dd437227asatok                        mFileManager.addInputMethodSubtypes(imi, subtypes);
2545c593380d1bccbfbd45c404954b2670b65acc287fsatok                        final long ident = Binder.clearCallingIdentity();
2546c593380d1bccbfbd45c404954b2670b65acc287fsatok                        try {
2547f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                            buildInputMethodListLocked(mMethodList, mMethodMap,
2548f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                                    false /* resetDefaultEnabledIme */);
2549c593380d1bccbfbd45c404954b2670b65acc287fsatok                        } finally {
2550c593380d1bccbfbd45c404954b2670b65acc287fsatok                            Binder.restoreCallingIdentity(ident);
2551c593380d1bccbfbd45c404954b2670b65acc287fsatok                        }
2552ee5e77cafec2eae70890abdcc1646ed39b06edddsatok                        return;
255391e88122cf28a48fd2e2260da7d3d87dd437227asatok                    }
255491e88122cf28a48fd2e2260da7d3d87dd437227asatok                }
255591e88122cf28a48fd2e2260da7d3d87dd437227asatok            }
2556e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
2557ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        return;
2558e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
2559e7c6998e0a953ae55487d4fe122739646f9280aasatok
2560658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    @Override
2561658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    public int getInputMethodWindowVisibleHeight() {
2562658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka        return mWindowManagerService.getInputMethodWindowVisibleHeight();
2563658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    }
2564658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka
2565d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    @Override
25663d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    public void notifyUserAction(int sequenceNumber) {
2567d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (DEBUG) {
25683d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            Slog.d(TAG, "Got the notification of a user action. sequenceNumber:" + sequenceNumber);
2569d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
25705a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
25713d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            if (mCurUserActionNotificationSequenceNumber != sequenceNumber) {
25723d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                if (DEBUG) {
25733d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    Slog.d(TAG, "Ignoring the user action notification due to the sequence number "
25743d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + "mismatch. expected:" + mCurUserActionNotificationSequenceNumber
25753d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + " actual: " + sequenceNumber);
25763d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                }
25773d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                return;
25783d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            }
25795a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
25805a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            if (imi != null) {
25810297051162193ef2b7d906409868e404f77e4c31Yohei Yukawa                mSwitchingController.onUserActionLocked(imi, mCurrentSubtype);
25825a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
2583d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2584d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    }
2585d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
25862820351489537698ad153c6397edf3270455edc5satok    private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
25879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
25884e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, id, subtypeId);
25894e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
25904e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    }
25919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25924e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
25934e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        if (token == null) {
25944e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            if (mContext.checkCallingOrSelfPermission(
25954e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
25964e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    != PackageManager.PERMISSION_GRANTED) {
25974e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                throw new SecurityException(
25984e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        "Using null token requires permission "
25994e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
26009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26014e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } else if (mCurToken != token) {
26024e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
26034e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    + " token: " + token);
26044e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            return;
26054e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
26064e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa
26074e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        final long ident = Binder.clearCallingIdentity();
26084e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        try {
26094e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodLocked(id, subtypeId);
26104e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } finally {
26114e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Binder.restoreCallingIdentity(ident);
26129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
26149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
261542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
26169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideMySoftInput(IBinder token, int flags) {
26174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
26184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
26194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
26209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
262122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
262222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
262322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring hideInputMethod due to an invalid token. uid:"
262422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
26259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
26269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
26289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
26294df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                hideCurrentInputLocked(flags, null);
26304df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } finally {
26314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                Binder.restoreCallingIdentity(ident);
26324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
26334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
26344df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
2635ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
263642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
26374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void showMySoftInput(IBinder token, int flags) {
26384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
26394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
26404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
26414df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        synchronized (mMethodMap) {
264222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
264322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
264422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring showMySoftInput due to an invalid token. uid:"
264522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
26464df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return;
26474df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
26484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            long ident = Binder.clearCallingIdentity();
26494df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            try {
26504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                showCurrentInputLocked(flags, null);
26519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
26529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
26539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
26569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setEnabledSessionInMainThread(SessionState session) {
26589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledSession != session) {
26599d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
26609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26618a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
26629d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false);
26639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
26649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
26659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledSession = session;
26679d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
26689d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                try {
26699d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
26709d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true);
26719d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                } catch (RemoteException e) {
26729d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                }
26739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2676ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
267742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
26789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean handleMessage(Message msg) {
2679758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov        SomeArgs args;
26809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (msg.what) {
2681ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            case MSG_SHOW_IM_SUBTYPE_PICKER:
268214e139179be7daab6ed452105387a3922752c219Seigo Nonaka                final boolean showAuxSubtypes;
268314e139179be7daab6ed452105387a3922752c219Seigo Nonaka                switch (msg.arg1) {
268414e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO:
268514e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        // This is undocumented so far, but IMM#showInputMethodPicker() has been
268614e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        // implemented so that auxiliary subtypes will be excluded when the soft
268714e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        // keyboard is invisible.
268814e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        showAuxSubtypes = mInputShown;
268914e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        break;
269014e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
269114e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        showAuxSubtypes = true;
269214e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        break;
269314e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES:
269414e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        showAuxSubtypes = false;
269514e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        break;
269614e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    default:
269714e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1);
269814e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        return false;
269914e139179be7daab6ed452105387a3922752c219Seigo Nonaka                }
270014e139179be7daab6ed452105387a3922752c219Seigo Nonaka                showInputMethodMenu(showAuxSubtypes);
2701ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                return true;
2702ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
270347a44916e2fb33cf4751906386d5f5c903b28d8bsatok            case MSG_SHOW_IM_SUBTYPE_ENABLER:
2704758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27057fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                showInputMethodAndSubtypeEnabler((String)args.arg1);
2706758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
2707217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                return true;
2708217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2709217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            case MSG_SHOW_IM_CONFIG:
2710217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                showConfigureInputMethods();
271147a44916e2fb33cf4751906386d5f5c903b28d8bsatok                return true;
271247a44916e2fb33cf4751906386d5f5c903b28d8bsatok
27139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2714ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_INPUT:
27169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)msg.obj).unbindInput();
27189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the method dying.
27209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
27219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_BIND_INPUT:
2723758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);
27269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2728758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_SOFT_INPUT:
2731758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2733e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
27346efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + msg.arg1 + ", " + args.arg2 + ")");
2735ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
27369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2738758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_HIDE_SOFT_INPUT:
2741758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2743e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
27446efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + args.arg2 + ")");
2745ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
27469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2748758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_ATTACH_TOKEN:
2751758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2753e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
27549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
27559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2757758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2759c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            case MSG_CREATE_SESSION: {
2760758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27611951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethod method = (IInputMethod)args.arg1;
2762c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel = (InputChannel)args.arg2;
27639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27641951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    method.createSession(channel, (IInputSessionCallback)args.arg3);
27659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2766c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } finally {
27671951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
27681951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
27691951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (channel != null && Binder.isProxy(method)) {
2770c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        channel.dispose();
2771c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    }
27729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2773758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2775c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
27769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2777ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_START_INPUT:
2779758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
27829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
27839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.startInput((IInputContext)args.arg2,
27849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
27859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2787758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_RESTART_INPUT:
2790758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
27939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
27949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.restartInput((IInputContext)args.arg2,
27959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
27969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2798758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2800ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
28019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2802ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
28039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_METHOD:
28049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
28059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1);
28069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
28079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the last client dying.
28089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
28099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
28101951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            case MSG_BIND_METHOD: {
2811758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
28121951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethodClient client = (IInputMethodClient)args.arg1;
28131951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                InputBindResult res = (InputBindResult)args.arg2;
28149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
28151951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    client.onBindMethod(res);
28169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
28178a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Client died receiving input method " + args.arg2);
28181951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                } finally {
28191951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
28201951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
28211951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (res.channel != null && Binder.isProxy(client)) {
28221951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                        res.channel.dispose();
28231951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    }
28249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2825758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
28269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
28271951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            }
2828a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            case MSG_SET_ACTIVE:
2829a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                try {
2830a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    ((ClientState)msg.obj).client.setActive(msg.arg1 != 0);
2831a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                } catch (RemoteException e) {
2832a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    Slog.w(TAG, "Got RemoteException sending setActive(false) notification to pid "
2833a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).pid + " uid "
2834a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).uid);
2835a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                }
2836a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                return true;
2837fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            case MSG_SET_INTERACTIVE:
2838fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa                handleSetInteractive(msg.arg1 != 0);
2839fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa                return true;
28403d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
28413d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                final int sequenceNumber = msg.arg1;
2842080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                final ClientState clientState = (ClientState)msg.obj;
28433d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                try {
2844080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                    clientState.client.setUserActionNotificationSequenceNumber(sequenceNumber);
28453d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                } catch (RemoteException e) {
28463d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    Slog.w(TAG, "Got RemoteException sending "
28473d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + "setUserActionNotificationSequenceNumber("
28483d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + sequenceNumber + ") notification to pid "
2849080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                            + clientState.pid + " uid "
2850080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                            + clientState.uid);
28513d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                }
28523d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                return true;
28533d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            }
285401038492ff0317f0d3cff54d8a7ee36bb31ff175satok
285501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // --------------------------------------------------------------
285601038492ff0317f0d3cff54d8a7ee36bb31ff175satok            case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
28577b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1);
285801038492ff0317f0d3cff54d8a7ee36bb31ff175satok                return true;
28599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
28609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
28619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
28629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2863fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa    private void handleSetInteractive(final boolean interactive) {
2864fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        synchronized (mMethodMap) {
2865fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            mIsInteractive = interactive;
2866fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            updateSystemUiLocked(mCurToken, interactive ? mImeWindowVis : 0, mBackDisposition);
2867fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa
2868fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            // Inform the current client of the change in active status
2869fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            if (mCurClient != null && mCurClient.client != null) {
2870fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
2871fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa                        MSG_SET_ACTIVE, mIsInteractive ? 1 : 0, mCurClient));
2872fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            }
2873fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        }
2874fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa    }
2875fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa
2876dc9ddaee9a710cf6f5d7f37350650f82e706c706satok    private boolean chooseNewDefaultIMELocked() {
28778e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
28788e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mSettings.getEnabledInputMethodListLocked());
2879dc9ddaee9a710cf6f5d7f37350650f82e706c706satok        if (imi != null) {
288003eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            if (DEBUG) {
288103eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                Slog.d(TAG, "New default IME was selected: " + imi.getId());
288203eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            }
2883723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            resetSelectedInputMethodAndSubtypeLocked(imi.getId());
28846da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            return true;
28856da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
28866da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
28876da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        return false;
28886da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger    }
28896da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
28909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
2891f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) {
28924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
2893f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
28940766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                    + " \n ------ \n" + InputMethodUtils.getStackTrace());
28954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
28969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        list.clear();
28979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map.clear();
2898ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
28994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // Use for queryIntentServicesAsUser
29004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final PackageManager pm = mContext.getPackageManager();
29014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
2902e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani        if (disabledSysImes == null) disabledSysImes = "";
29039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
29059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new Intent(InputMethod.SERVICE_INTERFACE),
2906fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
2907fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                mSettings.getCurrentUserId());
2908ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2909e7c6998e0a953ae55487d4fe122739646f9280aasatok        final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
2910e7c6998e0a953ae55487d4fe122739646f9280aasatok                mFileManager.getAllAdditionalInputMethodSubtypes();
29119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < services.size(); ++i) {
29129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = services.get(i);
29139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ServiceInfo si = ri.serviceInfo;
29149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ComponentName compName = new ComponentName(si.packageName, si.name);
29159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(
29169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    si.permission)) {
29178a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Skipping input method " + compName
29189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": it does not require the permission "
29199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.BIND_INPUT_METHOD);
29209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
29219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
29229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29238a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.d(TAG, "Checking " + compName);
29249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2926e7c6998e0a953ae55487d4fe122739646f9280aasatok                InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes);
29279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list.add(p);
2928e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                final String id = p.getId();
2929e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                map.put(id, p);
29309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
2932f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "Found an input method " + p);
29339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2934ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
29368a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
29379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
29388a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
29399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
29409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29416da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
2942f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (resetDefaultEnabledIme) {
2943f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            final ArrayList<InputMethodInfo> defaultEnabledIme =
2944f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list);
2945f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            for (int i = 0; i < defaultEnabledIme.size(); ++i) {
2946f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                final InputMethodInfo imi =  defaultEnabledIme.get(i);
2947f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                if (DEBUG) {
2948f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "--- enable ime = " + imi);
2949f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                }
2950f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                setInputMethodEnabledLocked(imi.getId(), true);
2951f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            }
2952f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
2953f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
29544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
29550a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!TextUtils.isEmpty(defaultImiId)) {
29560a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            if (!map.containsKey(defaultImiId)) {
29570a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
29580a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (chooseNewDefaultIMELocked()) {
29597b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateInputMethodsFromSettingsLocked(true);
29600a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
29610a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            } else {
29620a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                // Double check that the default IME is certainly enabled.
29630a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                setInputMethodEnabledLocked(defaultImiId, true);
29646da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            }
29656da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
29663d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
29673d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
29683d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
29693d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
2970c834a2590cc7ac478ba2ef5a6d8eb7ce471df132Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
29719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2972ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2974ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2975217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
2976f49688fa17b70313c0734f00df73bc3308a749e9Tadashi G. Takaoka        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
297747a44916e2fb33cf4751906386d5f5c903b28d8bsatok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
297886417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
297986417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
29807fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        if (!TextUtils.isEmpty(inputMethodId)) {
29812548020c364c4119d134c84cc7a00ffca2dcbe7bTadashi G. Takaoka            intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId);
29827fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        }
29833ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
2984217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    }
2985217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2986217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showConfigureInputMethods() {
2987217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
2988217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2989217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
2990217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
29913ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
299247a44916e2fb33cf4751906386d5f5c903b28d8bsatok    }
299347a44916e2fb33cf4751906386d5f5c903b28d8bsatok
29942c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    private boolean isScreenLocked() {
29952c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        return mKeyguardManager != null
29962c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
29972c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    }
2998d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka
299914e139179be7daab6ed452105387a3922752c219Seigo Nonaka    private void showInputMethodMenu(boolean showAuxSubtypes) {
300014e139179be7daab6ed452105387a3922752c219Seigo Nonaka        if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);
30019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
30029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Context context = mContext;
30032c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        final boolean isScreenLocked = isScreenLocked();
3004ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
30054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String lastInputMethodId = mSettings.getSelectedInputMethod();
30068e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
30078a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
3008ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
30097f35c8cc88bea5230f001dd4356f864845d202e5satok        synchronized (mMethodMap) {
3010bb4aa0683c8a0a1e617c6d5f03eda33f49b89ed9satok            final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
3011d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(
3012d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                            mContext);
30137f35c8cc88bea5230f001dd4356f864845d202e5satok            if (immis == null || immis.size() == 0) {
30147f35c8cc88bea5230f001dd4356f864845d202e5satok                return;
30157f35c8cc88bea5230f001dd4356f864845d202e5satok            }
3016ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
30178cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            hideInputMethodMenuLocked();
30189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3019688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            final List<ImeSubtypeListItem> imList =
30205a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSwitchingController.getSortedInputMethodAndSubtypeListLocked(
302114e139179be7daab6ed452105387a3922752c219Seigo Nonaka                            true /* showSubtypes */, showAuxSubtypes, isScreenLocked);
3022913a8925c07e854a80bf5df87561f290d3a56d61satok
3023c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
30244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
3025c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                if (currentSubtype != null) {
3026c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                    final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
30278e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
30288e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            currentImi, currentSubtype.hashCode());
3029c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                }
3030c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            }
3031c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok
3032761eb3762f3602dd1859905ee4ba80f0ef6aec56Ken Wakasa            final int N = imList.size();
3033ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mIms = new InputMethodInfo[N];
3034ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mSubtypeIds = new int[N];
30358cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            int checkedItem = 0;
30368cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            for (int i = 0; i < N; ++i) {
303705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                final ImeSubtypeListItem item = imList.get(i);
303805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mIms[i] = item.mImi;
303905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mSubtypeIds[i] = item.mSubtypeId;
30408cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                if (mIms[i].getId().equals(lastInputMethodId)) {
3041ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    int subtypeId = mSubtypeIds[i];
3042ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    if ((subtypeId == NOT_A_SUBTYPE_ID)
3043ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0)
3044ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (subtypeId == lastInputMethodSubtypeId)) {
3045ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                        checkedItem = i;
3046ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
30478cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                }
30489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3049505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3050505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Context settingsContext = new ContextThemeWrapper(context,
3051505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.style.Theme_DeviceDefault_Settings);
3052505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3053505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mDialogBuilder = new AlertDialog.Builder(settingsContext);
3054d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mDialogBuilder.setOnCancelListener(new OnCancelListener() {
3055d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
3056d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onCancel(DialogInterface dialog) {
3057d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    hideInputMethodMenu();
3058d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
3059d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            });
3060505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3061505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Context dialogContext = mDialogBuilder.getContext();
3062505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final TypedArray a = dialogContext.obtainStyledAttributes(null,
3063505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.styleable.DialogPreference,
3064505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.attr.alertDialogStyle, 0);
3065505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Drawable dialogIcon = a.getDrawable(
3066505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.styleable.DialogPreference_dialogIcon);
3067505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            a.recycle();
3068505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3069505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mDialogBuilder.setIcon(dialogIcon);
3070505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3071505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final LayoutInflater inflater = (LayoutInflater) dialogContext.getSystemService(
3072505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    Context.LAYOUT_INFLATER_SERVICE);
307301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final View tv = inflater.inflate(
307401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.layout.input_method_switch_dialog_title, null);
307501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mDialogBuilder.setCustomTitle(tv);
307601038492ff0317f0d3cff54d8a7ee36bb31ff175satok
307701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // Setup layout for a toggle switch of the hardware keyboard
307801038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView = tv;
3079d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mSwitchingDialogTitleView
3080d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    .findViewById(com.android.internal.R.id.hard_keyboard_section)
3081d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    .setVisibility(mWindowManagerService.isHardKeyboardAvailable()
3082d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            ? View.VISIBLE : View.GONE);
3083505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Switch hardKeySwitch = (Switch) mSwitchingDialogTitleView.findViewById(
3084d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    com.android.internal.R.id.hard_keyboard_switch);
30857b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
3086d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
3087d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
3088d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
30897b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    mSettings.setShowImeWithHardKeyboard(isChecked);
3090d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    // Ensure that the input method dialog is dismissed when changing
3091d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    // the hardware keyboard state.
3092d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    hideInputMethodMenu();
3093d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
3094d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            });
3095d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka
3096505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(dialogContext,
3097d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    com.android.internal.R.layout.input_method_switch_item, imList, checkedItem);
3098d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            final OnClickListener choiceListener = new OnClickListener() {
3099d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
3100d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onClick(final DialogInterface dialog, final int which) {
3101d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    synchronized (mMethodMap) {
3102d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        if (mIms == null || mIms.length <= which || mSubtypeIds == null
3103d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                                || mSubtypeIds.length <= which) {
3104d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            return;
310501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        }
3106d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        final InputMethodInfo im = mIms[which];
3107d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        int subtypeId = mSubtypeIds[which];
3108d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        adapter.mCheckedItem = which;
3109d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        adapter.notifyDataSetChanged();
3110d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        hideInputMethodMenu();
3111d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        if (im != null) {
3112d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) {
3113d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                                subtypeId = NOT_A_SUBTYPE_ID;
311420cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn                            }
3115d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            setInputMethodLocked(im.getId(), subtypeId);
31169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
3117d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    }
3118d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
3119d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            };
3120d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener);
31219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3122d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka            if (!isScreenLocked) {
3123d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                final OnClickListener positiveListener = new OnClickListener() {
3124d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    @Override
3125d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    public void onClick(DialogInterface dialog, int whichButton) {
3126d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        showConfigureInputMethods();
3127d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    }
3128d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                };
312982beadfa067b1e286fa604f8d7960d769411c954satok                mDialogBuilder.setPositiveButton(
3130d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        com.android.internal.R.string.configure_input_methods, positiveListener);
31317f35c8cc88bea5230f001dd4356f864845d202e5satok            }
31329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog = mDialogBuilder.create();
3133e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.setCanceledOnTouchOutside(true);
31349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.getWindow().setType(
31359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
3136c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
3137c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
3138e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
3139d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            updateSystemUi(mCurToken, mImeWindowVis, mBackDisposition);
31409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.show();
31419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
31429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3143ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
314405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> {
314505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final LayoutInflater mInflater;
314605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final int mTextViewResourceId;
314705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final List<ImeSubtypeListItem> mItemsList;
3148d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka        public int mCheckedItem;
314905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public ImeSubtypeListAdapter(Context context, int textViewResourceId,
315005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                List<ImeSubtypeListItem> itemsList, int checkedItem) {
315105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            super(context, textViewResourceId, itemsList);
3152505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
315305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mTextViewResourceId = textViewResourceId;
315405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mItemsList = itemsList;
315505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mCheckedItem = checkedItem;
3156505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
315705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
315805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
315905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        @Override
316005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public View getView(int position, View convertView, ViewGroup parent) {
316105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final View view = convertView != null ? convertView
316205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    : mInflater.inflate(mTextViewResourceId, null);
316305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (position < 0 || position >= mItemsList.size()) return view;
316405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListItem item = mItemsList.get(position);
316505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence imeName = item.mImeName;
316605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence subtypeName = item.mSubtypeName;
316705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1);
316805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2);
316905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (TextUtils.isEmpty(subtypeName)) {
317005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(imeName);
317105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.GONE);
317205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            } else {
317305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(subtypeName);
317405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setText(imeName);
317505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.VISIBLE);
317605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            }
317705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final RadioButton radioButton =
317805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
317905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            radioButton.setChecked(position == mCheckedItem);
318005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            return view;
318105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
318205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    }
318305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
31849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hideInputMethodMenu() {
3185105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        synchronized (mMethodMap) {
3186105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
3187105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
3188105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
3189ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3190105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void hideInputMethodMenuLocked() {
31918a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Hide switching menu");
31929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3193105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mSwitchingDialog != null) {
3194105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog.dismiss();
3195105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog = null;
31969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3197ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3198d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition);
3199105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mDialogBuilder = null;
3200105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIms = null;
32019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3202ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
32039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
3204ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
320542c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
32069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setInputMethodEnabled(String id, boolean enabled) {
32074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
32084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
32094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
32104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
32119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
32129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mContext.checkCallingOrSelfPermission(
32139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
32149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    != PackageManager.PERMISSION_GRANTED) {
32159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new SecurityException(
32169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Requires permission "
32179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
32189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
321921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
32209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
32219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
322221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                return setInputMethodEnabledLocked(id, enabled);
322321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } finally {
322421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Binder.restoreCallingIdentity(ident);
322521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
322621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
322721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
32288e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
322921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    boolean setInputMethodEnabledLocked(String id, boolean enabled) {
323021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        // Make sure this is a valid input method.
323121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        InputMethodInfo imm = mMethodMap.get(id);
323221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (imm == null) {
3233d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
323421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
3235ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3236d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
3237d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                .getEnabledInputMethodsAndSubtypeListLocked();
3238ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3239d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        if (enabled) {
3240d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            for (Pair<String, ArrayList<String>> pair: enabledInputMethodsList) {
3241d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                if (pair.first.equals(id)) {
3242d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // We are enabling this input method, but it is already enabled.
3243d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // Nothing to do. The previous state was enabled.
3244d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    return true;
32459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
324621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
3247d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            mSettings.appendAndPutEnabledInputMethodLocked(id, false);
3248d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            // Previous state was disabled.
3249d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return false;
3250d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        } else {
3251d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            StringBuilder builder = new StringBuilder();
3252d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
3253d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    builder, enabledInputMethodsList, id)) {
3254d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Disabled input method is currently selected, switch to another one.
32554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selId = mSettings.getSelectedInputMethod();
325603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
325703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
325803eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    resetSelectedInputMethodAndSubtypeLocked("");
3259d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                }
3260d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Previous state was enabled.
3261d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                return true;
3262d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            } else {
3263d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // We are disabling the input method but it is already disabled.
3264d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Nothing to do.  The previous state was disabled.
32659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
32669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
32679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
32689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
32694df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
3270723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
3271723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            boolean setSubtypeOnly) {
3272723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Update the history of InputMethod and Subtype
32738e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
3274723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
32753d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        mCurUserActionNotificationSequenceNumber =
32763d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                Math.max(mCurUserActionNotificationSequenceNumber + 1, 1);
32773d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        if (DEBUG) {
32783d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            Slog.d(TAG, "Bump mCurUserActionNotificationSequenceNumber:"
32793d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    + mCurUserActionNotificationSequenceNumber);
32803d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        }
32813d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
32823d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        if (mCurClient != null && mCurClient.client != null) {
32833d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
32843d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
3285080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                    mCurUserActionNotificationSequenceNumber, mCurClient));
32863d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        }
32873d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
3288723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Set Subtype here
3289723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi == null || subtypeId < 0) {
3290723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
32910ba75bb22c2992f649ee5f7605a2b45442ad4862Tadashi G. Takaoka            mCurrentSubtype = null;
3292723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        } else {
3293586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa            if (subtypeId < imi.getSubtypeCount()) {
3294586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                InputMethodSubtype subtype = imi.getSubtypeAt(subtypeId);
3295586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mSettings.putSelectedSubtype(subtype.hashCode());
3296586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mCurrentSubtype = subtype;
3297723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            } else {
3298723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
3299d81e950265356c81276b73da68a535ffa48d72f0satok                // If the subtype is not specified, choose the most applicable one
33004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
3301723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3302723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3303723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
33044c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Workaround.
33054c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // ASEC is not ready in the IMMS constructor. Accordingly, forward-locked
33064c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMEs are not recognized and considered uninstalled.
33074c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Actually, we can't move everything after SystemReady because
33084c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMMS needs to run in the encryption lock screen. So, we just skip changing
33094c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the default IME here and try cheking the default IME again in systemReady().
33104c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: Do nothing before system ready and implement a separated logic for
33114c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the encryption lock screen.
33124c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: ASEC should be ready before IMMS is instantiated.
33134c0e7152e74d091eb78af8baacd38287ba95a1a1satok        if (mSystemReady && !setSubtypeOnly) {
3314723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // Set InputMethod here
3315723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
33161ab852fbcfe155c9d4373b7130f8515591669634satok        }
3317ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3318ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3319723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
3320723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        InputMethodInfo imi = mMethodMap.get(newDefaultIme);
3321723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        int lastSubtypeId = NOT_A_SUBTYPE_ID;
3322723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // newDefaultIme is empty when there is no candidate for the selected IME.
3323723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
3324723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme);
3325723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            if (subtypeHashCode != null) {
3326723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                try {
33278e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
3328723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                            imi, Integer.valueOf(subtypeHashCode));
3329723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                } catch (NumberFormatException e) {
3330723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                    Slog.w(TAG, "HashCode for subtype looks broken: " + subtypeHashCode, e);
3331723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                }
3332723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3333723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3334723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
3335723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    }
3336723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
33374e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // If there are no selected shortcuts, tries finding the most applicable ones.
33384e4569dab5c75804b01a19b2d6e6101b445c1c68satok    private Pair<InputMethodInfo, InputMethodSubtype>
33394e4569dab5c75804b01a19b2d6e6101b445c1c68satok            findLastResortApplicableShortcutInputMethodAndSubtypeLocked(String mode) {
33404e4569dab5c75804b01a19b2d6e6101b445c1c68satok        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
33414e4569dab5c75804b01a19b2d6e6101b445c1c68satok        InputMethodInfo mostApplicableIMI = null;
3342cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        InputMethodSubtype mostApplicableSubtype = null;
33434e4569dab5c75804b01a19b2d6e6101b445c1c68satok        boolean foundInSystemIME = false;
33444e4569dab5c75804b01a19b2d6e6101b445c1c68satok
33454e4569dab5c75804b01a19b2d6e6101b445c1c68satok        // Search applicable subtype for each InputMethodInfo
33464e4569dab5c75804b01a19b2d6e6101b445c1c68satok        for (InputMethodInfo imi: imis) {
33477599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            final String imiId = imi.getId();
33487599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (foundInSystemIME && !imiId.equals(mCurMethodId)) {
33497599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                continue;
33507599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3351cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            InputMethodSubtype subtype = null;
3352df31ae6a3011d47421a6ac10021f9649dc34a156satok            final List<InputMethodSubtype> enabledSubtypes =
33538e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
3354df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 1. Search by the current subtype's locale from enabledSubtypes.
33554e4569dab5c75804b01a19b2d6e6101b445c1c68satok            if (mCurrentSubtype != null) {
33568e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3357df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
33584e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3359df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 2. Search by the system locale from enabledSubtypes.
3360df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
3361cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
33628e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3363df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, null, true);
33647599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3365a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
33668e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    InputMethodUtils.getOverridingImplicitlyEnabledSubtypes(imi, mode);
3367a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> subtypesForSearch =
3368a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                    overridingImplicitlyEnabledSubtypes.isEmpty()
33698e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            ? InputMethodUtils.getSubtypes(imi)
33708e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            : overridingImplicitlyEnabledSubtypes;
33717599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 4. Search by the current subtype's locale from all subtypes.
33727599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (subtype == null && mCurrentSubtype != null) {
33738e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3374a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
33754e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
33767599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 5. Search by the system locale from all subtypes.
33777599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 6. Search the first enabled subtype matched with mode from all subtypes.
3378cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
33798e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3380a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, null, true);
33814e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3382cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype != null) {
33837599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (imiId.equals(mCurMethodId)) {
33844e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    // The current input method is the most applicable IME.
33854e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3386cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
33874e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    break;
33884e4569dab5c75804b01a19b2d6e6101b445c1c68satok                } else if (!foundInSystemIME) {
33897599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    // The system input method is 2nd applicable IME.
33904e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3391cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
33927599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    if ((imi.getServiceInfo().applicationInfo.flags
33937599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
33947599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                        foundInSystemIME = true;
33957599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    }
33964e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
33974e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
33984e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
33994e4569dab5c75804b01a19b2d6e6101b445c1c68satok        if (DEBUG) {
3400cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (mostApplicableIMI != null) {
3401cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                Slog.w(TAG, "Most applicable shortcut input method was:"
3402cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                        + mostApplicableIMI.getId());
3403cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                if (mostApplicableSubtype != null) {
3404cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    Slog.w(TAG, "Most applicable shortcut input method subtype was:"
3405cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + "," + mostApplicableSubtype.getMode() + ","
3406cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + mostApplicableSubtype.getLocale());
3407cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                }
3408cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            }
34094e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
3410cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        if (mostApplicableIMI != null) {
34114e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
3412cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype);
34134e4569dab5c75804b01a19b2d6e6101b445c1c68satok        } else {
34144e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return null;
34154e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
34164e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
34174e4569dab5c75804b01a19b2d6e6101b445c1c68satok
3418ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3419ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return Return the current subtype of this input method.
3420ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
342142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3422ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public InputMethodSubtype getCurrentInputMethodSubtype() {
34234e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
34244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
34254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
34264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
34274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        synchronized (mMethodMap) {
34284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return getCurrentInputMethodSubtypeLocked();
34294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
34304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
34314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
34324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
3433fdf419e81d795593e3792c9e78f33ed899ff098esatok        if (mCurMethodId == null) {
3434fdf419e81d795593e3792c9e78f33ed899ff098esatok            return null;
3435fdf419e81d795593e3792c9e78f33ed899ff098esatok        }
34368e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
34374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
34384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (imi == null || imi.getSubtypeCount() == 0) {
34394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
34404e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
34414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!subtypeIsSelected || mCurrentSubtype == null
34428e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
34438e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
34444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (subtypeId == NOT_A_SUBTYPE_ID) {
34454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there are no selected subtypes, the framework will try to find
34464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // the most applicable subtype from explicitly or implicitly enabled
34474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // subtypes.
34484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
34498e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
34504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there is only one explicitly or implicitly enabled subtype,
34514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // just returns it.
34524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
34534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
34544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
34558e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
34564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            mRes, explicitlyOrImplicitlyEnabledSubtypes,
34578e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, null, true);
34584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    if (mCurrentSubtype == null) {
34598e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
34604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
34614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                true);
34624e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    }
34633ef8b29fa03fe3ae1c57fd891a12afa46128fff8satok                }
34644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else {
34658e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mCurrentSubtype = InputMethodUtils.getSubtypes(imi).get(subtypeId);
34668fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok            }
34678fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok        }
34684e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        return mCurrentSubtype;
3469ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3470ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3471f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
3472f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            InputMethodSubtype subtype) {
3473f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
3474f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
3475f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        } else {
3476f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3477f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            subtypes.add(subtype);
3478f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
3479f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        }
3480f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    }
3481f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok
34824e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // TODO: We should change the return type from List to List<Parcelable>
3483dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("rawtypes")
3484e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
34854e4569dab5c75804b01a19b2d6e6101b445c1c68satok    public List getShortcutInputMethodsAndSubtypes() {
34864e4569dab5c75804b01a19b2d6e6101b445c1c68satok        synchronized (mMethodMap) {
34873da922367c0dbe67b97fe97fcfca13fd93602f7asatok            ArrayList<Object> ret = new ArrayList<Object>();
3488f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            if (mShortcutInputMethodsAndSubtypes.size() == 0) {
34894e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // If there are no selected shortcut subtypes, the framework will try to find
34904e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // the most applicable subtype from all subtypes whose mode is
34914e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
3492f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                Pair<InputMethodInfo, InputMethodSubtype> info =
3493f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
34948e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_VOICE);
34957599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (info != null) {
34963da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.first);
34973da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.second);
34987599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                }
34993da922367c0dbe67b97fe97fcfca13fd93602f7asatok                return ret;
3500f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            }
3501f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
3502f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                ret.add(imi);
3503f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
3504f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    ret.add(subtype);
35054e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
35064e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3507f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            return ret;
35084e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
35094e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
35104e4569dab5c75804b01a19b2d6e6101b445c1c68satok
351142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3512b66d287e3003a0934d5714fbf15e554b3c814906satok    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
35134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
35144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
35154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
35164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
3517b66d287e3003a0934d5714fbf15e554b3c814906satok        synchronized (mMethodMap) {
3518b66d287e3003a0934d5714fbf15e554b3c814906satok            if (subtype != null && mCurMethodId != null) {
3519b66d287e3003a0934d5714fbf15e554b3c814906satok                InputMethodInfo imi = mMethodMap.get(mCurMethodId);
35208e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                int subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode());
3521b66d287e3003a0934d5714fbf15e554b3c814906satok                if (subtypeId != NOT_A_SUBTYPE_ID) {
3522b66d287e3003a0934d5714fbf15e554b3c814906satok                    setInputMethodLocked(mCurMethodId, subtypeId);
3523b66d287e3003a0934d5714fbf15e554b3c814906satok                    return true;
3524b66d287e3003a0934d5714fbf15e554b3c814906satok                }
3525b66d287e3003a0934d5714fbf15e554b3c814906satok            }
3526b66d287e3003a0934d5714fbf15e554b3c814906satok            return false;
3527b66d287e3003a0934d5714fbf15e554b3c814906satok        }
3528b66d287e3003a0934d5714fbf15e554b3c814906satok    }
3529b66d287e3003a0934d5714fbf15e554b3c814906satok
35305ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    // TODO: Cache the state for each user and reset when the cached user is removed.
3531e7c6998e0a953ae55487d4fe122739646f9280aasatok    private static class InputMethodFileManager {
3532e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String SYSTEM_PATH = "system";
3533e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String INPUT_METHOD_PATH = "inputmethod";
3534e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ADDITIONAL_SUBTYPES_FILE_NAME = "subtypes.xml";
3535e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPES = "subtypes";
3536e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPE = "subtype";
3537e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_IMI = "imi";
3538e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ID = "id";
3539e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_LABEL = "label";
3540e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ICON = "icon";
3541e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
3542e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
3543e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
3544e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
3545e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final AtomicFile mAdditionalInputMethodSubtypeFile;
3546e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final HashMap<String, InputMethodInfo> mMethodMap;
3547e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
3548e7c6998e0a953ae55487d4fe122739646f9280aasatok                new HashMap<String, List<InputMethodSubtype>>();
35495ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
3550e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (methodMap == null) {
3551e7c6998e0a953ae55487d4fe122739646f9280aasatok                throw new NullPointerException("methodMap is null");
3552e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3553e7c6998e0a953ae55487d4fe122739646f9280aasatok            mMethodMap = methodMap;
35545ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka            final File systemDir = userId == UserHandle.USER_OWNER
35555ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
35565ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    : Environment.getUserSystemDirectory(userId);
3557e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
3558df5af484f882ede16931a61a866f2ffefbe491abYohei Yukawa            if (!inputMethodDir.exists() && !inputMethodDir.mkdirs()) {
3559e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
3560e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3561e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
3562e7c6998e0a953ae55487d4fe122739646f9280aasatok            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
3563e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!subtypeFile.exists()) {
3564e7c6998e0a953ae55487d4fe122739646f9280aasatok                // If "subtypes.xml" doesn't exist, create a blank file.
3565e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3566e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, methodMap);
3567e7c6998e0a953ae55487d4fe122739646f9280aasatok            } else {
3568e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                readAdditionalInputMethodSubtypes(
3569e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile);
3570e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3571e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3572e7c6998e0a953ae55487d4fe122739646f9280aasatok
3573e7c6998e0a953ae55487d4fe122739646f9280aasatok        private void deleteAllInputMethodSubtypes(String imiId) {
3574e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3575e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.remove(imiId);
3576e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3577e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3578e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3579e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3580e7c6998e0a953ae55487d4fe122739646f9280aasatok
3581e7c6998e0a953ae55487d4fe122739646f9280aasatok        public void addInputMethodSubtypes(
35824a28bde70e23b2ed151d52690da702da7f23cf5esatok                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
3583e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3584e7c6998e0a953ae55487d4fe122739646f9280aasatok                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3585e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int N = additionalSubtypes.length;
3586e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (int i = 0; i < N; ++i) {
3587e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final InputMethodSubtype subtype = additionalSubtypes[i];
3588ed2b24ecc7842b27178fc584a9e5bd5b1ab07635satok                    if (!subtypes.contains(subtype)) {
3589e7c6998e0a953ae55487d4fe122739646f9280aasatok                        subtypes.add(subtype);
3590e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                    } else {
3591e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        Slog.w(TAG, "Duplicated subtype definition found: "
3592e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                                + subtype.getLocale() + ", " + subtype.getMode());
3593e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3594e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3595e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.put(imi.getId(), subtypes);
3596e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3597e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3598e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3599e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3600e7c6998e0a953ae55487d4fe122739646f9280aasatok
3601e7c6998e0a953ae55487d4fe122739646f9280aasatok        public HashMap<String, List<InputMethodSubtype>> getAllAdditionalInputMethodSubtypes() {
3602e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3603e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                return mAdditionalSubtypesMap;
3604e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3605e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3606e7c6998e0a953ae55487d4fe122739646f9280aasatok
3607e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void writeAdditionalInputMethodSubtypes(
3608e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile,
3609e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, InputMethodInfo> methodMap) {
3610e7c6998e0a953ae55487d4fe122739646f9280aasatok            // Safety net for the case that this function is called before methodMap is set.
3611e7c6998e0a953ae55487d4fe122739646f9280aasatok            final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0;
3612e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileOutputStream fos = null;
3613e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3614e7c6998e0a953ae55487d4fe122739646f9280aasatok                fos = subtypesFile.startWrite();
3615e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlSerializer out = new FastXmlSerializer();
36169e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz                out.setOutput(fos, StandardCharsets.UTF_8.name());
3617e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startDocument(null, true);
3618e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3619e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startTag(null, NODE_SUBTYPES);
3620e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (String imiId : allSubtypes.keySet()) {
3621e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (isSetMethodMap && !methodMap.containsKey(imiId)) {
3622e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "IME uninstalled or not valid.: " + imiId);
3623e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3624e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3625e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.startTag(null, NODE_IMI);
3626e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.attribute(null, ATTR_ID, imiId);
3627e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final List<InputMethodSubtype> subtypesList = allSubtypes.get(imiId);
3628e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final int N = subtypesList.size();
3629e7c6998e0a953ae55487d4fe122739646f9280aasatok                    for (int i = 0; i < N; ++i) {
3630e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype = subtypesList.get(i);
3631e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.startTag(null, NODE_SUBTYPE);
3632e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
3633e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
3634e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
3635e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_MODE, subtype.getMode());
3636e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
3637e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IS_AUXILIARY,
3638e7c6998e0a953ae55487d4fe122739646f9280aasatok                                String.valueOf(subtype.isAuxiliary() ? 1 : 0));
3639e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.endTag(null, NODE_SUBTYPE);
3640e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3641e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.endTag(null, NODE_IMI);
3642e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3643e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endTag(null, NODE_SUBTYPES);
3644e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endDocument();
3645e7c6998e0a953ae55487d4fe122739646f9280aasatok                subtypesFile.finishWrite(fos);
3646e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3647e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error writing subtypes", e);
3648e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fos != null) {
3649e7c6998e0a953ae55487d4fe122739646f9280aasatok                    subtypesFile.failWrite(fos);
3650e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3651e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3652e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3653e7c6998e0a953ae55487d4fe122739646f9280aasatok
3654e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void readAdditionalInputMethodSubtypes(
3655e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile) {
3656e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (allSubtypes == null || subtypesFile == null) return;
3657e7c6998e0a953ae55487d4fe122739646f9280aasatok            allSubtypes.clear();
3658e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileInputStream fis = null;
3659e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3660e7c6998e0a953ae55487d4fe122739646f9280aasatok                fis = subtypesFile.openRead();
3661e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlPullParser parser = Xml.newPullParser();
36629e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz                parser.setInput(fis, StandardCharsets.UTF_8.name());
3663e7c6998e0a953ae55487d4fe122739646f9280aasatok                int type = parser.getEventType();
3664e7c6998e0a953ae55487d4fe122739646f9280aasatok                // Skip parsing until START_TAG
3665e7c6998e0a953ae55487d4fe122739646f9280aasatok                while ((type = parser.next()) != XmlPullParser.START_TAG
3666e7c6998e0a953ae55487d4fe122739646f9280aasatok                        && type != XmlPullParser.END_DOCUMENT) {}
3667e7c6998e0a953ae55487d4fe122739646f9280aasatok                String firstNodeName = parser.getName();
3668e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (!NODE_SUBTYPES.equals(firstNodeName)) {
3669e7c6998e0a953ae55487d4fe122739646f9280aasatok                    throw new XmlPullParserException("Xml doesn't start with subtypes");
3670e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3671e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int depth =parser.getDepth();
3672e7c6998e0a953ae55487d4fe122739646f9280aasatok                String currentImiId = null;
3673e7c6998e0a953ae55487d4fe122739646f9280aasatok                ArrayList<InputMethodSubtype> tempSubtypesArray = null;
3674e7c6998e0a953ae55487d4fe122739646f9280aasatok                while (((type = parser.next()) != XmlPullParser.END_TAG
3675e7c6998e0a953ae55487d4fe122739646f9280aasatok                        || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
3676e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (type != XmlPullParser.START_TAG)
3677e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3678e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final String nodeName = parser.getName();
3679e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (NODE_IMI.equals(nodeName)) {
3680e7c6998e0a953ae55487d4fe122739646f9280aasatok                        currentImiId = parser.getAttributeValue(null, ATTR_ID);
3681e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId)) {
3682e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "Invalid imi id found in subtypes.xml");
3683e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3684e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3685e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray = new ArrayList<InputMethodSubtype>();
3686e7c6998e0a953ae55487d4fe122739646f9280aasatok                        allSubtypes.put(currentImiId, tempSubtypesArray);
3687e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } else if (NODE_SUBTYPE.equals(nodeName)) {
3688e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
3689e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "IME uninstalled or not valid.: " + currentImiId);
3690e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3691e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3692e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int icon = Integer.valueOf(
3693e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_ICON));
3694e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int label = Integer.valueOf(
3695e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_LABEL));
3696e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeLocale =
3697e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LOCALE);
3698e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeMode =
3699e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
3700e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeExtraValue =
3701e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
37024a28bde70e23b2ed151d52690da702da7f23cf5esatok                        final boolean isAuxiliary = "1".equals(String.valueOf(
37034a28bde70e23b2ed151d52690da702da7f23cf5esatok                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
3704443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                        final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
3705443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeNameResId(label)
3706443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeIconResId(icon)
3707443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeLocale(imeSubtypeLocale)
3708443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeMode(imeSubtypeMode)
3709443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeExtraValue(imeSubtypeExtraValue)
3710443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setIsAuxiliary(isAuxiliary)
3711443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .build();
3712e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray.add(subtype);
3713e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3714e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3715e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (XmlPullParserException e) {
3716e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3717e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3718e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3719e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3720e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3721e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (NumberFormatException e) {
3722e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3723e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3724e7c6998e0a953ae55487d4fe122739646f9280aasatok            } finally {
3725e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fis != null) {
3726e7c6998e0a953ae55487d4fe122739646f9280aasatok                    try {
3727e7c6998e0a953ae55487d4fe122739646f9280aasatok                        fis.close();
3728e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } catch (java.io.IOException e1) {
3729e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "Failed to close.");
3730e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3731e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3732e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3733e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3734e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
3735e7c6998e0a953ae55487d4fe122739646f9280aasatok
3736fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa    private static final class LocalServiceImpl implements InputMethodManagerInternal {
3737fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        @NonNull
3738fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        private final Handler mHandler;
3739fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa
3740fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        LocalServiceImpl(@NonNull final Handler handler) {
3741fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            mHandler = handler;
3742fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        }
3743fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa
3744fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        @Override
3745fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        public void setInteractive(boolean interactive) {
3746fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            // Do everything in handler so as not to block the caller.
3747fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            mHandler.sendMessage(mHandler.obtainMessage(MSG_SET_INTERACTIVE,
3748fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa                    interactive ? 1 : 0, 0));
3749fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa        }
3750fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa    }
3751fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa
37529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
37539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
37549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
37559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3756ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
37579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Permission Denial: can't dump InputMethodManager from from pid="
37589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
37599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
37609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
37619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
37629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IInputMethod method;
37649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState client;
3765ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
37669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(pw);
3767ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
37689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
37699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("Current Input Method Manager state:");
37709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mMethodList.size();
37719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Input Methods:");
37729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
37739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo info = mMethodList.get(i);
37749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  InputMethod #" + i + ":");
37759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.dump(p, "    ");
37769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
37779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Clients:");
37789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState ci : mClients.values()) {
37799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  Client " + ci + ":");
37809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    client=" + ci.client);
37819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    inputContext=" + ci.inputContext);
37829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    sessionRequested=" + ci.sessionRequested);
37839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    curSession=" + ci.curSession);
37849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3785105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            p.println("  mCurMethodId=" + mCurMethodId);
37869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = mCurClient;
3787b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
3788b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
37899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
37909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mBoundToMethod=" + mBoundToMethod);
37919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurToken=" + mCurToken);
37929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurIntent=" + mCurIntent);
37939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = mCurMethod;
37949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurMethod=" + mCurMethod);
37959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mEnabledSession=" + mEnabledSession);
37969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mShowRequested=" + mShowRequested
37979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
37989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowForced=" + mShowForced
37999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mInputShown=" + mInputShown);
38003d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            p.println("  mCurUserActionNotificationSequenceNumber="
38013d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    + mCurUserActionNotificationSequenceNumber);
3802fa6e0a80e20a4917b403fd330e01a9edd021aabcYohei Yukawa            p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mIsInteractive);
380381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            p.println("  mSettingsObserver=" + mSettingsObserver);
3804d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            p.println("  mSwitchingController:");
3805d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            mSwitchingController.dump(p);
38069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3807ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3808b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
38099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (client != null) {
38109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
38119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
38129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                client.client.asBinder().dump(fd, args);
38139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
38149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method client dead: " + e);
38159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3816b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3817b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method client.");
38189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3819ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3820b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
38219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (method != null) {
38229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
38239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
38249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                method.asBinder().dump(fd, args);
38259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
38269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method service dead: " + e);
38279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3828b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3829b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method service.");
38309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
38319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
38329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3833