InputMethodManagerService.java revision ec928651cc3e72c2e8ff6102a6c037c5119617ee
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;
1921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackbornimport com.android.internal.content.PackageMonitor;
20d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController;
21d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataokaimport com.android.internal.inputmethod.InputMethodSubtypeSwitchingController.ImeSubtypeListItem;
228e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils;
238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataokaimport com.android.internal.inputmethod.InputMethodUtils.InputMethodSettings;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.os.HandlerCaller;
25758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganovimport com.android.internal.os.SomeArgs;
26e7c6998e0a953ae55487d4fe122739646f9280aasatokimport com.android.internal.util.FastXmlSerializer;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputContext;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethod;
2952a53526265c801b70eaf6dab1acf5c3f628f8a6Michael Wrightimport com.android.internal.view.IInputSessionCallback;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodClient;
319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodManager;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.IInputMethodSession;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport com.android.internal.view.InputBindResult;
34ef2ea1faf6449f97a2423ecbdecce664c58bcbe1Adam Lesinskiimport com.android.server.statusbar.StatusBarManagerService;
3501038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport com.android.server.wm.WindowManagerService;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlPullParser;
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport org.xmlpull.v1.XmlPullParserException;
39e7c6998e0a953ae55487d4fe122739646f9280aasatokimport org.xmlpull.v1.XmlSerializer;
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.ActivityManagerNative;
424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.AppGlobals;
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.app.AlertDialog;
44e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawaimport android.app.AppOpsManager;
454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.app.IUserSwitchObserver;
46f90a33e92a7c8d4040c0e660a62336eb7293d785satokimport android.app.KeyguardManager;
477cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.Notification;
487cfc0ed21a3fafabafb40b38a8589808ad1517afsatokimport android.app.NotificationManager;
49dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackbornimport android.app.PendingIntent;
505b927c431f54ea47c3333afb7940d79e2e863f1asatokimport android.content.BroadcastReceiver;
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ComponentName;
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentResolver;
539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface;
559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.DialogInterface.OnCancelListener;
56d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaokaimport android.content.DialogInterface.OnClickListener;
579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Intent;
58e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.content.IntentFilter;
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ServiceConnection;
606da35a0c1205398b7df4776e359f7794584fb128Brandon Ballingerimport android.content.pm.ApplicationInfo;
614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.content.pm.IPackageManager;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.PackageManager;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ResolveInfo;
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.pm.ServiceInfo;
65734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.content.pm.UserInfo;
66e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasaniimport android.content.res.Configuration;
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.Resources;
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.res.TypedArray;
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.ContentObserver;
70505e3abb8dd0d8f594280b9510adef74623630d7Alan Viveretteimport android.graphics.drawable.Drawable;
71857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onoratoimport android.inputmethodservice.InputMethodService;
727b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wrightimport android.net.Uri;
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Binder;
741ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wrenimport android.os.Bundle;
75e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.os.Environment;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Handler;
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IBinder;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.IInterface;
794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.IRemoteCallback;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Message;
814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.Process;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.Parcel;
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.RemoteException;
844df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Projectimport android.os.ResultReceiver;
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.ServiceManager;
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.os.SystemClock;
874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataokaimport android.os.UserHandle;
88734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasaniimport android.os.UserManager;
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.provider.Settings;
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.text.TextUtils;
917b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport android.text.TextUtils.SimpleStringSplitter;
92f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.text.style.SuggestionSpan;
937b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport android.util.ArrayMap;
947b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport android.util.ArraySet;
9539606a007a5b1309dd000234f2b8cf156c49fd0fDianne Hackbornimport android.util.AtomicFile;
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.EventLog;
97f9f01008624e2d28c15a90d942fa36f98c8c967dsatokimport android.util.LruCache;
98ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.util.Pair;
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.PrintWriterPrinter;
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Printer;
101e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Slog;
102e7c6998e0a953ae55487d4fe122739646f9280aasatokimport android.util.Xml;
103d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaokaimport android.view.ContextThemeWrapper;
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.IWindowManager;
105c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brownimport android.view.InputChannel;
10605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.LayoutInflater;
10705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.View;
10805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.view.ViewGroup;
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.WindowManager;
110ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.EditorInfo;
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputBinding;
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethod;
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodInfo;
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.view.inputmethod.InputMethodManager;
115ab751aa085433e9f735d2e7603459c6c7e9d2fb0satokimport android.view.inputmethod.InputMethodSubtype;
116443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawaimport android.view.inputmethod.InputMethodSubtype.InputMethodSubtypeBuilder;
11705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.ArrayAdapter;
11801038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton;
11901038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.CompoundButton.OnCheckedChangeListener;
12005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.RadioButton;
12101038492ff0317f0d3cff54d8a7ee36bb31ff175satokimport android.widget.Switch;
12205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasaimport android.widget.TextView;
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
124e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.File;
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.FileDescriptor;
126e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileInputStream;
127e7c6998e0a953ae55487d4fe122739646f9280aasatokimport java.io.FileOutputStream;
1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.IOException;
1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.io.PrintWriter;
1309e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewiczimport java.nio.charset.StandardCharsets;
1319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
132688bd47fccf1a1373e6287bc49b5b33fad12b7f3satokimport java.util.Collections;
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
1347b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tateimport java.util.HashSet;
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.List;
1365b927c431f54ea47c3333afb7940d79e2e863f1asatokimport java.util.Locale;
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/**
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * This class provides a system service that manages input methods.
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class InputMethodManagerService extends IInputMethodManager.Stub
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        implements ServiceConnection, Handler.Callback {
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final boolean DEBUG = false;
1447b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static final boolean DEBUG_RESTORE = DEBUG || false;
1456ec6f79e1ac1714e3b837796e99f07ff88f66601Jeff Brown    static final String TAG = "InputMethodManagerService";
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1477b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    private static final char INPUT_METHOD_SEPARATOR = ':';
1487b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    private static final char INPUT_METHOD_SUBTYPE_SEPARATOR = ';';
1497b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
150d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka    static final int MSG_SHOW_IM_SUBTYPE_PICKER = 1;
151d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka    static final int MSG_SHOW_IM_SUBTYPE_ENABLER = 2;
152d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka    static final int MSG_SHOW_IM_CONFIG = 3;
153ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_INPUT = 1000;
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_INPUT = 1010;
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_SHOW_SOFT_INPUT = 1020;
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_HIDE_SOFT_INPUT = 1030;
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_ATTACH_TOKEN = 1040;
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_CREATE_SESSION = 1050;
160ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_START_INPUT = 2000;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_RESTART_INPUT = 2010;
163ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_UNBIND_METHOD = 3000;
1659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    static final int MSG_BIND_METHOD = 3010;
166a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn    static final int MSG_SET_ACTIVE = 3020;
1673d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    static final int MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER = 3040;
168ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
16901038492ff0317f0d3cff54d8a7ee36bb31ff175satok    static final int MSG_HARD_KEYBOARD_SWITCH_CHANGED = 4000;
17001038492ff0317f0d3cff54d8a7ee36bb31ff175satok
171bcacc322f83de1fe522081a20e0ac36ec8243763Satoshi Kataoka    static final long TIME_TO_RECONNECT = 3 * 1000;
172ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
173f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    static final int SECURE_SUGGESTION_SPANS_MAX_SIZE = 20;
174f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1758e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    private static final int NOT_A_SUBTYPE_ID = InputMethodUtils.NOT_A_SUBTYPE_ID;
176b6359414adabab2d64acc8ccc9e3b9c1b800b303satok    private static final String TAG_TRY_SUPPRESSING_IME_SWITCHER = "TrySuppressingImeSwitcher";
1778e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
1784e4569dab5c75804b01a19b2d6e6101b445c1c68satok
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Context mContext;
1807d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn    final Resources mRes;
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final Handler mHandler;
182d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final InputMethodSettings mSettings;
1839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final SettingsObserver mSettingsObserver;
1849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final IWindowManager mIWindowManager;
1859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HandlerCaller mCaller;
186119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn    final boolean mHasFeature;
1875ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private InputMethodFileManager mFileManager;
18801038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final HardKeyboardListener mHardKeyboardListener;
18901038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private final WindowManagerService mWindowManagerService;
190e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa    private final AppOpsManager mAppOpsManager;
191ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1923d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    final InputBindResult mNoBinding = new InputBindResult(null, null, null, -1, -1);
193ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // All known input methods.  mMethodMap also serves as the global
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // lock for this class.
196d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final ArrayList<InputMethodInfo> mMethodList = new ArrayList<InputMethodInfo>();
197d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok    final HashMap<String, InputMethodInfo> mMethodMap = new HashMap<String, InputMethodInfo>();
198f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    private final LruCache<SuggestionSpan, InputMethodInfo> mSecureSuggestionSpans =
199f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            new LruCache<SuggestionSpan, InputMethodInfo>(SECURE_SUGGESTION_SPANS_MAX_SIZE);
200d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka    private final InputMethodSubtypeSwitchingController mSwitchingController;
201ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2022c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    // Used to bring IME service up to visible adjustment while it is being shown.
2032c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    final ServiceConnection mVisibleConnection = new ServiceConnection() {
2042c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceConnected(ComponentName name, IBinder service) {
2052c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
2062c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
2072c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        @Override public void onServiceDisconnected(ComponentName name) {
2082c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
2092c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    };
2102c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn    boolean mVisibleBound = false;
2112c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
2127cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    // Ongoing notification
213661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private NotificationManager mNotificationManager;
214661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private KeyguardManager mKeyguardManager;
215661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private StatusBarManagerService mStatusBar;
2161ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren    private Notification.Builder mImeSwitcherNotification;
217661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn    private PendingIntent mImeSwitchPendingIntent;
218b858c732f665fe9610f2d913230ae625f44a8caasatok    private boolean mShowOngoingImeSwitcherForPhones;
2197cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    private boolean mNotificationShown;
2200a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok    private final boolean mImeSelectedOnBoot;
2217cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
2228c6d477d30e64f3dfae20250b8274ffb37ef7bfaTadashi G. Takaoka    static class SessionState {
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final ClientState client;
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethod method;
225c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
226c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        IInputMethodSession session;
227c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        InputChannel channel;
228ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "SessionState{uid " + client.uid + " pid " + client.pid
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " method " + Integer.toHexString(
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(method))
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " session " + Integer.toHexString(
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            System.identityHashCode(session))
236c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    + " channel " + channel
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + "}";
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState(ClientState _client, IInputMethod _method,
241c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                IInputMethodSession _session, InputChannel _channel) {
2429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = _method;
2449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            session = _session;
245c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            channel = _channel;
2469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
248ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
249c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    static final class ClientState {
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputMethodClient client;
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final IInputContext inputContext;
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int uid;
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final int pid;
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final InputBinding binding;
255ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean sessionRequested;
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SessionState curSession;
258ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public String toString() {
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return "ClientState{" + Integer.toHexString(
2629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    System.identityHashCode(this)) + " uid " + uid
2639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " pid " + pid + "}";
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState(IInputMethodClient _client, IInputContext _inputContext,
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                int _uid, int _pid) {
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = _client;
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            inputContext = _inputContext;
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            uid = _uid;
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pid = _pid;
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            binding = new InputBinding(null, inputContext.asBinder(), uid, pid);
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
275ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    final HashMap<IBinder, ClientState> mClients
2779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            = new HashMap<IBinder, ClientState>();
278ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
280a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     * Set once the system is ready to run third party code.
281a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn     */
282a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    boolean mSystemReady;
283ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
284a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    /**
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Id of the currently selected input method.
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurMethodId;
288ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The current binding sequence number, incremented every time there is
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a new bind performed.
2929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    int mCurSeq;
294ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
2969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The client that is currently bound to an input method.
2979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
2989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ClientState mCurClient;
299ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
301b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     * The last window token that gained focus.
302b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project     */
303b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    IBinder mCurFocusedWindow;
304ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
305b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    /**
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input context last provided by the current client.
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputContext mCurInputContext;
309ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The attributes last provided by the current client.
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    EditorInfo mCurAttribute;
314ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The input method ID of the input method service that we are currently
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * connected to or in the process of connecting to.
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String mCurId;
320ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
322ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * The current subtype of the current input method.
323ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
324ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    private InputMethodSubtype mCurrentSubtype;
325ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3264e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // This list contains the pairs of InputMethodInfo and InputMethodSubtype.
327f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private final HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>
328f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes =
329f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                new HashMap<InputMethodInfo, ArrayList<InputMethodSubtype>>();
330ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
331e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    // Was the keyguard locked when this client became current?
332e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean mCurClientInKeyguard;
333e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
334ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set to true if our ServiceConnection is currently actively bound to
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a service (whether or not we have gotten its IBinder back yet).
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mHaveConnection;
339ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if the client has asked for the input method to be shown.
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowRequested;
344ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were explicitly told to show the input method.
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowExplicitlyRequested;
349ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we were forced to be shown.
3529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mShowForced;
354ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set if we last told the input method to show itself.
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mInputShown;
359ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The Intent used to connect to the current input method.
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    Intent mCurIntent;
364ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * The token we have made for the currently active input method, to
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * identify it in the future.
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IBinder mCurToken;
370ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * If non-null, this is the input method service we are currently connected
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * to.
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    IInputMethod mCurMethod;
376ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Time that we last initiated a bind to the input method, to determine
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * if we should try to disconnect and reconnect to it.
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long mLastBindTime;
382ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Have we called mCurMethod.bindInput()?
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mBoundToMethod;
387ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Currently enabled session.  Only touched by service thread, not
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * protected by a lock.
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    SessionState mEnabledSession;
393ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * True if the screen is on.  The value is true initially.
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean mScreenOn = true;
398ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3993d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    int mCurUserActionNotificationSequenceNumber = 0;
4003d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
401857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mBackDisposition = InputMethodService.BACK_DISPOSITION_DEFAULT;
402d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
403d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    /**
404d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * A set of status bits regarding the active IME.
405d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     *
406d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <p>This value is a combination of following two bits:</p>
407d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dl>
408d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dt>{@link InputMethodService#IME_ACTIVE}</dt>
409d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dd>
410d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     *   If this bit is ON, connected IME is ready to accept touch/key events.
411d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * </dd>
412d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dt>{@link InputMethodService#IME_VISIBLE}</dt>
413d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <dd>
414d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     *   If this bit is ON, some of IME view, e.g. software input, candidate view, is visible.
415d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * </dd>
416d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * </dl>
417d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     * <em>Do not update this value outside of setImeWindowStatus.</em>
418d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka     */
419857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    int mImeWindowVis;
420857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato
42105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog.Builder mDialogBuilder;
42205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private AlertDialog mSwitchingDialog;
42301038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private View mSwitchingDialogTitleView;
42405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private InputMethodInfo[] mIms;
42505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private int[] mSubtypeIds;
4265b927c431f54ea47c3333afb7940d79e2e863f1asatok    private Locale mLastSystemLocale;
4277b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    private boolean mShowImeWithHardKeyboard;
4284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final MyPackageMonitor mMyPackageMonitor = new MyPackageMonitor();
4294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private final IPackageManager mIPackageManager;
430ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    class SettingsObserver extends ContentObserver {
43281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        int mUserId;
43381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        boolean mRegistered = false;
434fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        String mLastEnabled = "";
435fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn
43681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        /**
43781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa         * <em>This constructor must be called within the lock.</em>
43881482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa         */
4399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        SettingsObserver(Handler handler) {
4409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            super(handler);
44181482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        }
44281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa
44381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        public void registerContentObserverLocked(int userId) {
44481482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            if (mRegistered && mUserId == userId) {
44581482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                return;
44681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            }
4479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentResolver resolver = mContext.getContentResolver();
44881482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            if (mRegistered) {
44981482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mContext.getContentResolver().unregisterContentObserver(this);
45081482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mRegistered = false;
45181482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            }
45281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            if (mUserId != userId) {
45381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mLastEnabled = "";
45481482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                mUserId = userId;
45581482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            }
4569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            resolver.registerContentObserver(Settings.Secure.getUriFor(
45781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.DEFAULT_INPUT_METHOD), false, this, userId);
458ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            resolver.registerContentObserver(Settings.Secure.getUriFor(
45981482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.ENABLED_INPUT_METHODS), false, this, userId);
460b6109bb591bc02bf8a2d9d5ca76d69d1961c9b5fsatok            resolver.registerContentObserver(Settings.Secure.getUriFor(
46181482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.SELECTED_INPUT_METHOD_SUBTYPE), false, this, userId);
4627b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            resolver.registerContentObserver(Settings.Secure.getUriFor(
46381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD), false, this, userId);
46481482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            mRegistered = true;
4659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
466ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4677b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        @Override public void onChange(boolean selfChange, Uri uri) {
4687b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            final Uri showImeUri =
4697b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    Settings.Secure.getUriFor(Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD);
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
4717b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                if (showImeUri.equals(uri)) {
4727b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateKeyboardFromSettingsLocked();
4737b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                } else {
4747b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    boolean enabledChanged = false;
4757b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    String newEnabled = mSettings.getEnabledInputMethodsStr();
4767b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    if (!mLastEnabled.equals(newEnabled)) {
4777b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        mLastEnabled = newEnabled;
4787b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        enabledChanged = true;
4797b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    }
4807b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateInputMethodsFromSettingsLocked(enabledChanged);
481fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
48481482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa
48581482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        @Override
48681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        public String toString() {
48781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            return "SettingsObserver{mUserId=" + mUserId + " mRegistered=" + mRegistered
48881482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa                    + " mLastEnabled=" + mLastEnabled + "}";
48981482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        }
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
491ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
4924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    class ImmsBroadcastReceiver extends android.content.BroadcastReceiver {
4934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private void updateActive() {
4944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // Inform the current client of the change in active status
4954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (mCurClient != null && mCurClient.client != null) {
4964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
4974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, mCurClient));
4984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
4994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
5004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        public void onReceive(Context context, Intent intent) {
5034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String action = intent.getAction();
5044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (Intent.ACTION_SCREEN_ON.equals(action)) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = true;
506d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                updateSystemUi(mCurToken, mImeWindowVis, mBackDisposition);
5074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
5084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
5094e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mScreenOn = false;
511d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                updateSystemUi(mCurToken, 0 /* vis */, mBackDisposition);
5124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                updateActive();
5134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
5144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
515105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                hideInputMethodMenu();
5164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // No need to updateActive
517105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                return;
518734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani            } else if (Intent.ACTION_USER_ADDED.equals(action)
519734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                    || Intent.ACTION_USER_REMOVED.equals(action)) {
5202a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                updateCurrentProfileIds();
521734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani                return;
5227b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            } else if (Intent.ACTION_SETTING_RESTORED.equals(action)) {
5237b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                final String name = intent.getStringExtra(Intent.EXTRA_SETTING_NAME);
5247b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                if (Settings.Secure.ENABLED_INPUT_METHODS.equals(name)) {
5257b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                    final String prevValue = intent.getStringExtra(
5267b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                            Intent.EXTRA_SETTING_PREVIOUS_VALUE);
5277b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                    final String newValue = intent.getStringExtra(
5287b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                            Intent.EXTRA_SETTING_NEW_VALUE);
5297b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                    restoreEnabledInputMethods(mContext, prevValue, newValue);
5307b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } else {
5328a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unexpected intent " + intent);
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
536ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
5377b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // Apply the results of a restore operation to the set of enabled IMEs.  Note that this
5387b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // does not attempt to validate on the fly with any installed device policy, so must only
5397b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // be run in the context of initial device setup.
5407b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    //
5417b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // TODO: Move this method to InputMethodUtils with adding unit tests.
5427b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static void restoreEnabledInputMethods(Context context, String prevValue, String newValue) {
5437b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        if (DEBUG_RESTORE) {
5447b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "Restoring enabled input methods:");
5457b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "prev=" + prevValue);
5467b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, " new=" + newValue);
5477b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5487b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // 'new' is the just-restored state, 'prev' is what was in settings prior to the restore
5497b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        ArrayMap<String, ArraySet<String>> prevMap = parseInputMethodsAndSubtypesString(prevValue);
5507b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        ArrayMap<String, ArraySet<String>> newMap = parseInputMethodsAndSubtypesString(newValue);
5517b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5527b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // Merge the restored ime+subtype enabled states into the live state
5537b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        for (ArrayMap.Entry<String, ArraySet<String>> entry : newMap.entrySet()) {
5547b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final String imeId = entry.getKey();
5557b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            ArraySet<String> prevSubtypes = prevMap.get(imeId);
5567b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            if (prevSubtypes == null) {
5577b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                prevSubtypes = new ArraySet<String>(2);
5587b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                prevMap.put(imeId, prevSubtypes);
5597b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            }
5607b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            prevSubtypes.addAll(entry.getValue());
5617b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5627b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5637b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final String mergedImesAndSubtypesString = buildInputMethodsAndSubtypesString(prevMap);
5647b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        if (DEBUG_RESTORE) {
5657b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "Merged IME string:");
5667b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            Slog.i(TAG, "     " + mergedImesAndSubtypesString);
5677b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5687b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        Settings.Secure.putString(context.getContentResolver(),
5697b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                Settings.Secure.ENABLED_INPUT_METHODS, mergedImesAndSubtypesString);
5707b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    }
5717b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5727b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // TODO: Move this method to InputMethodUtils with adding unit tests.
5737b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static String buildInputMethodsAndSubtypesString(ArrayMap<String, ArraySet<String>> map) {
5747b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // we want to use the canonical InputMethodSettings implementation,
5757b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        // so we convert data structures first.
5767b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        List<Pair<String, ArrayList<String>>> imeMap =
5777b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new ArrayList<Pair<String, ArrayList<String>>>(4);
5787b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        for (ArrayMap.Entry<String, ArraySet<String>> entry : map.entrySet()) {
5797b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final String imeName = entry.getKey();
5807b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final ArraySet<String> subtypeSet = entry.getValue();
5817b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final ArrayList<String> subtypes = new ArrayList<String>(2);
5827b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            if (subtypeSet != null) {
5837b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                subtypes.addAll(subtypeSet);
5847b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            }
5857b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            imeMap.add(new Pair<String, ArrayList<String>>(imeName, subtypes));
5867b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5877b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        return InputMethodSettings.buildInputMethodsSettingString(imeMap);
5887b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    }
5897b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5907b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    // TODO: Move this method to InputMethodUtils with adding unit tests.
5917b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    static ArrayMap<String, ArraySet<String>> parseInputMethodsAndSubtypesString(
5927b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            final String inputMethodsAndSubtypesString) {
5937b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final ArrayMap<String, ArraySet<String>> imeMap =
5947b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new ArrayMap<String, ArraySet<String>>();
5957b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        if (TextUtils.isEmpty(inputMethodsAndSubtypesString)) {
5967b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            return imeMap;
5977b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
5987b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
5997b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final SimpleStringSplitter typeSplitter =
6007b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new SimpleStringSplitter(INPUT_METHOD_SEPARATOR);
6017b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        final SimpleStringSplitter subtypeSplitter =
6027b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                new SimpleStringSplitter(INPUT_METHOD_SUBTYPE_SEPARATOR);
6037b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        List<Pair<String, ArrayList<String>>> allImeSettings =
6047b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                InputMethodSettings.buildInputMethodsAndSubtypeList(inputMethodsAndSubtypesString,
6057b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                        typeSplitter,
6067b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                        subtypeSplitter);
6077b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        for (Pair<String, ArrayList<String>> ime : allImeSettings) {
6087b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            ArraySet<String> subtypes = new ArraySet<String>();
6097b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            if (ime.second != null) {
6107b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate                subtypes.addAll(ime.second);
6117b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            }
6127b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate            imeMap.put(ime.first, subtypes);
6137b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        }
6147b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        return imeMap;
6157b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate    }
6167b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate
61721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    class MyPackageMonitor extends PackageMonitor {
6184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        private boolean isChangingPackagesOfCurrentUser() {
6194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final int userId = getChangingUserId();
6204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final boolean retval = userId == mSettings.getCurrentUserId();
6214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
62281f8b7c66750a0a89c8e6b6037136ca169c96f95satok                if (!retval) {
62381f8b7c66750a0a89c8e6b6037136ca169c96f95satok                    Slog.d(TAG, "--- ignore this call back from a background user: " + userId);
62481f8b7c66750a0a89c8e6b6037136ca169c96f95satok                }
6254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
6264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return retval;
6274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
6284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
6299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        @Override
63021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public boolean onHandleForceStop(Intent intent, String[] packages, int uid, boolean doit) {
6314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
6324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return false;
6334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
63421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
6354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
63621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                final int N = mMethodList.size();
63721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curInputMethodId != null) {
63821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    for (int i=0; i<N; i++) {
63921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
64021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (imi.getId().equals(curInputMethodId)) {
64121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            for (String pkg : packages) {
64221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                if (imi.getPackageName().equals(pkg)) {
64321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    if (!doit) {
64421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                        return true;
64521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    }
646723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                    resetSelectedInputMethodAndSubtypeLocked("");
64721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    chooseNewDefaultIMELocked();
64821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    return true;
64921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                }
65021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            }
65121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
65221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    }
65308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                }
65408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu            }
65521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            return false;
65621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
657ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
65821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        @Override
65921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        public void onSomePackagesChanged() {
6604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!isChangingPackagesOfCurrentUser()) {
6614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
6624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
66321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            synchronized (mMethodMap) {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo curIm = null;
6654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                String curInputMethodId = mSettings.getSelectedInputMethod();
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                final int N = mMethodList.size();
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (curInputMethodId != null) {
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    for (int i=0; i<N; i++) {
66921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        InputMethodInfo imi = mMethodList.get(i);
670e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imiId = imi.getId();
671e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (imiId.equals(curInputMethodId)) {
67221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            curIm = imi;
67321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        }
674e7c6998e0a953ae55487d4fe122739646f9280aasatok
67521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        int change = isPackageDisappearing(imi.getPackageName());
676e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (isPackageModified(imi.getPackageName())) {
677e7c6998e0a953ae55487d4fe122739646f9280aasatok                            mFileManager.deleteAllInputMethodSubtypes(imiId);
678e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
67921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                        if (change == PACKAGE_TEMPORARY_CHANGE
68021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                || change == PACKAGE_PERMANENT_CHANGE) {
6818a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Input method uninstalled, disabling: "
68221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                                    + imi.getComponent());
68321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            setInputMethodEnabledLocked(imi.getId(), false);
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
687ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
688f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(
689f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        mMethodList, mMethodMap, false /* resetDefaultEnabledIme */);
69021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                boolean changed = false;
692ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
69308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                if (curIm != null) {
69421f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    int change = isPackageDisappearing(curIm.getPackageName());
69521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    if (change == PACKAGE_TEMPORARY_CHANGE
69621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            || change == PACKAGE_PERMANENT_CHANGE) {
69708675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        ServiceInfo si = null;
69808675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        try {
6994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            si = mIPackageManager.getServiceInfo(
7004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    curIm.getComponent(), 0, mSettings.getCurrentUserId());
7014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        } catch (RemoteException ex) {
70208675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
70308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        if (si == null) {
70408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Uh oh, current input method is no longer around!
70508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            // Pick another one...
7068a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            Slog.i(TAG, "Current input method removed: " + curInputMethodId);
707d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                            updateSystemUiLocked(mCurToken, 0 /* vis */, mBackDisposition);
70821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                            if (!chooseNewDefaultIMELocked()) {
70908675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                changed = true;
71008675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                                curIm = null;
7118a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                Slog.i(TAG, "Unsetting current input method");
712723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                                resetSelectedInputMethodAndSubtypeLocked("");
71308675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                            }
71408675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                        }
71508675a3376819a82aa5ab344bc3e7b1635c30b05Suchi Amalapurapu                    }
71621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
717ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
71821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (curIm == null) {
71921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // We currently don't have a default input method... is
72021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    // one now available?
72121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                    changed = chooseNewDefaultIMELocked();
72254d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                } else if (!changed && isPackageModified(curIm.getPackageName())) {
72354d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                    // Even if the current input method is still available, mCurrentSubtype could
72454d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                    // be obsolete when the package is modified in practice.
72554d512c9acc44484b7baa8d8cf02067d175dde11Yohei Yukawa                    changed = true;
72621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                }
727ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
72821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                if (changed) {
729fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    updateFromSettingsLocked(false);
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
734ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
735c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private static final class MethodCallback extends IInputSessionCallback.Stub {
736e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard        private final InputMethodManagerService mParentIMMS;
737c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final IInputMethod mMethod;
738c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        private final InputChannel mChannel;
739ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
740c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        MethodCallback(InputMethodManagerService imms, IInputMethod method,
741c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel) {
742e0d32a60da29e133e5b4ff46133628476d83872cJean Chalard            mParentIMMS = imms;
743c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mMethod = method;
744c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            mChannel = channel;
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
746ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
747e7c6998e0a953ae55487d4fe122739646f9280aasatok        @Override
748c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        public void sessionCreated(IInputMethodSession session) {
7496b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            long ident = Binder.clearCallingIdentity();
7506b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            try {
7516b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                mParentIMMS.onSessionCreated(mMethod, session, mChannel);
7526b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            } finally {
7536b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn                Binder.restoreCallingIdentity(ident);
7546b6b3fdbf5547417fde3ce56d9eb883963a54b58Dianne Hackborn            }
7559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
757ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
75801038492ff0317f0d3cff54d8a7ee36bb31ff175satok    private class HardKeyboardListener
75901038492ff0317f0d3cff54d8a7ee36bb31ff175satok            implements WindowManagerService.OnHardKeyboardStatusChangeListener {
76001038492ff0317f0d3cff54d8a7ee36bb31ff175satok        @Override
7617b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        public void onHardKeyboardStatusChange(boolean available) {
7627b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            mHandler.sendMessage(mHandler.obtainMessage(MSG_HARD_KEYBOARD_SWITCH_CHANGED,
7637b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                        available ? 1 : 0));
76401038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
76501038492ff0317f0d3cff54d8a7ee36bb31ff175satok
7667b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        public void handleHardKeyboardStatusChange(boolean available) {
76701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            if (DEBUG) {
7687b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                Slog.w(TAG, "HardKeyboardStatusChanged: available=" + available);
76901038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
77001038492ff0317f0d3cff54d8a7ee36bb31ff175satok            synchronized(mMethodMap) {
77101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mSwitchingDialog != null && mSwitchingDialogTitleView != null
77201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        && mSwitchingDialog.isShowing()) {
77301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mSwitchingDialogTitleView.findViewById(
77401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            com.android.internal.R.id.hard_keyboard_section).setVisibility(
77501038492ff0317f0d3cff54d8a7ee36bb31ff175satok                                    available ? View.VISIBLE : View.GONE);
77601038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
77701038492ff0317f0d3cff54d8a7ee36bb31ff175satok            }
77801038492ff0317f0d3cff54d8a7ee36bb31ff175satok        }
77901038492ff0317f0d3cff54d8a7ee36bb31ff175satok    }
78001038492ff0317f0d3cff54d8a7ee36bb31ff175satok
78101038492ff0317f0d3cff54d8a7ee36bb31ff175satok    public InputMethodManagerService(Context context, WindowManagerService windowManager) {
7824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mIPackageManager = AppGlobals.getPackageManager();
7839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mContext = context;
7847d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn        mRes = context.getResources();
7859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mHandler = new Handler(this);
78681482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        // Note: SettingsObserver doesn't register observers in its constructor.
78781482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        mSettingsObserver = new SettingsObserver(mHandler);
7889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mIWindowManager = IWindowManager.Stub.asInterface(
7899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ServiceManager.getService(Context.WINDOW_SERVICE));
790ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        mCaller = new HandlerCaller(context, null, new HandlerCaller.Callback() {
791e7c6998e0a953ae55487d4fe122739646f9280aasatok            @Override
7929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            public void executeMessage(Message msg) {
7939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                handleMessage(msg);
7949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
795ed218c706d9e91e75b94c448cee2e6150aaee57fMita Yun        }, true /*asyncHandler*/);
79601038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mWindowManagerService = windowManager;
797e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
79801038492ff0317f0d3cff54d8a7ee36bb31ff175satok        mHardKeyboardListener = new HardKeyboardListener();
799119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn        mHasFeature = context.getPackageManager().hasSystemFeature(
800119bbc378d3c836f1196e14b847e564205a29728Dianne Hackborn                PackageManager.FEATURE_INPUT_METHODS);
8017cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
8021ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren        Bundle extras = new Bundle();
8031ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren        extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
8041ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren        mImeSwitcherNotification = new Notification.Builder(mContext)
8051ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setSmallIcon(com.android.internal.R.drawable.ic_notification_ime_default)
8061ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setWhen(0)
8071ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setOngoing(true)
8081ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .addExtras(extras)
8091ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setCategory(Notification.CATEGORY_SYSTEM)
8101ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren            .setColor(com.android.internal.R.color.system_notification_accent_color);
811590d515d912396a0c293d78529ac0dbc224400bfDaniel Sandler
8127cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
813683e2383c8549f95e00bade15daed3dbddf13950satok        mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
814b858c732f665fe9610f2d913230ae625f44a8caasatok
815b858c732f665fe9610f2d913230ae625f44a8caasatok        mShowOngoingImeSwitcherForPhones = false;
8167cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
8174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final IntentFilter broadcastFilter = new IntentFilter();
8184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_ON);
8194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_SCREEN_OFF);
8204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        broadcastFilter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
821734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_ADDED);
822734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        broadcastFilter.addAction(Intent.ACTION_USER_REMOVED);
8237b9a28c7f0a7b88ed1ea777edc05002d2d2b38b7Christopher Tate        broadcastFilter.addAction(Intent.ACTION_SETTING_RESTORED);
8244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mContext.registerReceiver(new ImmsBroadcastReceiver(), broadcastFilter);
825ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
8267cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        mNotificationShown = false;
8274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        int userId = 0;
8284e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        try {
8294e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            ActivityManagerNative.getDefault().registerUserSwitchObserver(
8304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    new IUserSwitchObserver.Stub() {
8314e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
8324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitching(int newUserId, IRemoteCallback reply) {
8335ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            synchronized(mMethodMap) {
8345ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                                switchUserLocked(newUserId);
8355ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                            }
8364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            if (reply != null) {
8374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                try {
8384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                    reply.sendResult(null);
8394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                } catch (RemoteException e) {
8404e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                }
8414e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            }
8424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
8434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
8444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        @Override
8454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        public void onUserSwitchComplete(int newUserId) throws RemoteException {
8464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        }
847429796226a8831af63a6303a58329f6b68f7b100Kenny Guy
848429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                        @Override
849429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                        public void onForegroundProfileSwitch(int newProfileId) {
850429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                            // Ignore.
851429796226a8831af63a6303a58329f6b68f7b100Kenny Guy                        }
8524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    });
8534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            userId = ActivityManagerNative.getDefault().getCurrentUser().id;
8544e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } catch (RemoteException e) {
8554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.w(TAG, "Couldn't get current user ID; guessing it's 0", e);
8564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
85781f8b7c66750a0a89c8e6b6037136ca169c96f95satok        mMyPackageMonitor.register(mContext, null, UserHandle.ALL, true);
858913a8925c07e854a80bf5df87561f290d3a56d61satok
859d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        // mSettings should be created before buildInputMethodListLocked
860df31ae6a3011d47421a6ac10021f9649dc34a156satok        mSettings = new InputMethodSettings(
8614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mRes, context.getContentResolver(), mMethodMap, mMethodList, userId);
8622a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
8635ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, userId);
8645a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
8655a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            mSwitchingController = InputMethodSubtypeSwitchingController.createInstanceLocked(
8665a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSettings, context);
8675a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
8680a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
8690a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        // Just checking if defaultImiId is empty or not
8704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
871f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (DEBUG) {
872f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "Initial default ime = " + defaultImiId);
873f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
8740a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        mImeSelectedOnBoot = !TextUtils.isEmpty(defaultImiId);
8750a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok
8765a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
8775a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            buildInputMethodListLocked(mMethodList, mMethodMap,
8785a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
8795a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
880d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        mSettings.enableAllIMEsIfThereIsNoEnabledIME();
8819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8820a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!mImeSelectedOnBoot) {
8830a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            Slog.w(TAG, "No IME selected. Choose the most applicable IME.");
8845a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            synchronized (mMethodMap) {
8855a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                resetDefaultImeLocked(context);
8865a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
8875b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
8885b927c431f54ea47c3333afb7940d79e2e863f1asatok
8895a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
89081482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            mSettingsObserver.registerContentObserverLocked(userId);
8915a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            updateFromSettingsLocked(true);
8925a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        }
8935b927c431f54ea47c3333afb7940d79e2e863f1asatok
8945b927c431f54ea47c3333afb7940d79e2e863f1asatok        // IMMS wants to receive Intent.ACTION_LOCALE_CHANGED in order to update the current IME
8955b927c431f54ea47c3333afb7940d79e2e863f1asatok        // according to the new system locale.
8965b927c431f54ea47c3333afb7940d79e2e863f1asatok        final IntentFilter filter = new IntentFilter();
8975b927c431f54ea47c3333afb7940d79e2e863f1asatok        filter.addAction(Intent.ACTION_LOCALE_CHANGED);
8985b927c431f54ea47c3333afb7940d79e2e863f1asatok        mContext.registerReceiver(
8995b927c431f54ea47c3333afb7940d79e2e863f1asatok                new BroadcastReceiver() {
9005b927c431f54ea47c3333afb7940d79e2e863f1asatok                    @Override
9015b927c431f54ea47c3333afb7940d79e2e863f1asatok                    public void onReceive(Context context, Intent intent) {
9025b927c431f54ea47c3333afb7940d79e2e863f1asatok                        synchronized(mMethodMap) {
903ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            resetStateIfCurrentLocaleChangedLocked();
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
9065b927c431f54ea47c3333afb7940d79e2e863f1asatok                }, filter);
9075b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
9085b927c431f54ea47c3333afb7940d79e2e863f1asatok
9095b927c431f54ea47c3333afb7940d79e2e863f1asatok    private void resetDefaultImeLocked(Context context) {
9105b927c431f54ea47c3333afb7940d79e2e863f1asatok        // Do not reset the default (current) IME when it is a 3rd-party IME
9118e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        if (mCurMethodId != null
9128e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                && !InputMethodUtils.isSystemIme(mMethodMap.get(mCurMethodId))) {
9135b927c431f54ea47c3333afb7940d79e2e863f1asatok            return;
9145b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9155b927c431f54ea47c3333afb7940d79e2e863f1asatok
9165b927c431f54ea47c3333afb7940d79e2e863f1asatok        InputMethodInfo defIm = null;
9175b927c431f54ea47c3333afb7940d79e2e863f1asatok        for (InputMethodInfo imi : mMethodList) {
9186aa037887800e34bd057585106609236c950ca22Yohei Yukawa            if (defIm == null && mSystemReady) {
9196aa037887800e34bd057585106609236c950ca22Yohei Yukawa                final Locale systemLocale = context.getResources().getConfiguration().locale;
9206aa037887800e34bd057585106609236c950ca22Yohei Yukawa                if (InputMethodUtils.isSystemImeThatHasSubtypeOf(imi, context,
9216aa037887800e34bd057585106609236c950ca22Yohei Yukawa                        true /* checkDefaultAttribute */, systemLocale, false /* checkCountry */,
9226aa037887800e34bd057585106609236c950ca22Yohei Yukawa                        InputMethodUtils.SUBTYPE_MODE_ANY)) {
9235b927c431f54ea47c3333afb7940d79e2e863f1asatok                    defIm = imi;
9245b927c431f54ea47c3333afb7940d79e2e863f1asatok                    Slog.i(TAG, "Selected default: " + imi.getId());
9255b927c431f54ea47c3333afb7940d79e2e863f1asatok                }
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9275b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9285b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm == null && mMethodList.size() > 0) {
9298e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            defIm = InputMethodUtils.getMostApplicableDefaultIME(
9308e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
9315baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            if (defIm != null) {
9325baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim                Slog.i(TAG, "Default found, using " + defIm.getId());
9335baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            } else {
9345baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim                Slog.i(TAG, "No default found");
9355baaaac7c75dbcbd1de8e4f24820f231d2077231Hyejin Kim            }
9365b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9375b927c431f54ea47c3333afb7940d79e2e863f1asatok        if (defIm != null) {
9385b927c431f54ea47c3333afb7940d79e2e863f1asatok            setSelectedInputMethodAndSubtypeLocked(defIm, NOT_A_SUBTYPE_ID, false);
9395b927c431f54ea47c3333afb7940d79e2e863f1asatok        }
9405b927c431f54ea47c3333afb7940d79e2e863f1asatok    }
9415b927c431f54ea47c3333afb7940d79e2e863f1asatok
9427f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka    private void resetAllInternalStateLocked(final boolean updateOnlyWhenLocaleChanged,
9437f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            final boolean resetDefaultEnabledIme) {
9444e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!mSystemReady) {
9454e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            // not system ready
9464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
9474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final Locale newLocale = mRes.getConfiguration().locale;
9494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!updateOnlyWhenLocaleChanged
9504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                || (newLocale != null && !newLocale.equals(mLastSystemLocale))) {
9514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
9524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                hideCurrentInputLocked(0, null);
9534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurMethodId = null;
9542ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
9554e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
9564e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
9574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.i(TAG, "Locale has been changed to " + newLocale);
9584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
9597f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka            buildInputMethodListLocked(mMethodList, mMethodMap, resetDefaultEnabledIme);
9604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
9614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selectedImiId = mSettings.getSelectedInputMethod();
9624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (TextUtils.isEmpty(selectedImiId)) {
9634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // This is the first time of the user switch and
9644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    // set the current ime to the proper one.
9654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    resetDefaultImeLocked(mContext);
9664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
967d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka            } else {
968d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                // If the locale is changed, needs to reset the default ime
969d08a9238db0de62c956788ceebb227d099ad88c2Satoshi Kataoka                resetDefaultImeLocked(mContext);
9704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
971fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            updateFromSettingsLocked(true);
9724e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            mLastSystemLocale = newLocale;
9734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (!updateOnlyWhenLocaleChanged) {
9744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                try {
9754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    startInputInnerLocked();
9764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } catch (RuntimeException e) {
9774e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    Slog.w(TAG, "Unexpected exception", e);
9784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                }
9794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
9804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
9814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
983ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka    private void resetStateIfCurrentLocaleChangedLocked() {
9847f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(true /* updateOnlyWhenLocaleChanged */,
9857f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka                true /* resetDefaultImeLocked */);
9864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
9874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
9885ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    private void switchUserLocked(int newUserId) {
98990bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa        if (DEBUG) Slog.d(TAG, "Switching user stage 1/3. newUserId=" + newUserId
99090bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa                + " currentUserId=" + mSettings.getCurrentUserId());
99190bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
99281482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        // ContentObserver should be registered again when the user is changed
99381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa        mSettingsObserver.registerContentObserverLocked(newUserId);
9944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        mSettings.setCurrentUserId(newUserId);
9952a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        updateCurrentProfileIds();
9965ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        // InputMethodFileManager should be reset when the user is changed
9975ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        mFileManager = new InputMethodFileManager(mMethodMap, newUserId);
9987f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
99990bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
100090bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa        if (DEBUG) Slog.d(TAG, "Switching user stage 2/3. newUserId=" + newUserId
100190bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa                + " defaultImiId=" + defaultImiId);
100290bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
10037c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // For secondary users, the list of enabled IMEs may not have been updated since the
10047c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // callbacks to PackageMonitor are ignored for the secondary user. Here, defaultImiId may
10057c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // not be empty even if the IME has been uninstalled by the primary user.
10067c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // Even in such cases, IMMS works fine because it will find the most applicable
10077c4a2a12232d97fbc45f0be72efca9144a30cf75Satoshi Kataoka        // IME for that user.
1008ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        final boolean initialUserSwitch = TextUtils.isEmpty(defaultImiId);
10097f7535fd250a30ff5383b046295db88613fe719aSatoshi Kataoka        resetAllInternalStateLocked(false  /* updateOnlyWhenLocaleChanged */,
1010ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                initialUserSwitch /* needsToResetDefaultIme */);
1011ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        if (initialUserSwitch) {
1012ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka            InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(mContext.getPackageManager(),
1013ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    mSettings.getEnabledInputMethodListLocked());
1014ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka        }
101590bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa
101690bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa        if (DEBUG) Slog.d(TAG, "Switching user stage 3/3. newUserId=" + newUserId
101790bf7084bf4f681383bf3329b0935de55330e782Yohei Yukawa                + " selectedIme=" + mSettings.getSelectedInputMethod());
10184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
10194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
10202a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy    void updateCurrentProfileIds() {
10212a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        List<UserInfo> profiles =
10222a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy                UserManager.get(mContext).getProfiles(mSettings.getCurrentUserId());
10232a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        int[] currentProfileIds = new int[profiles.size()]; // profiles will not be null
10242a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        for (int i = 0; i < currentProfileIds.length; i++) {
10252a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy            currentProfileIds[i] = profiles.get(i).id;
1026734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani        }
10272a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        mSettings.setCurrentProfileIds(currentProfileIds);
1028734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani    }
1029734983fff35d9ed2b7a9848bdfbca401887d0dd8Amith Yamasani
10309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
10319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean onTransact(int code, Parcel data, Parcel reply, int flags)
10329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throws RemoteException {
10339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
10349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return super.onTransact(code, data, reply, flags);
10359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RuntimeException e) {
10369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The input method manager only throws security exceptions, so let's
10379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // log all others.
10389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!(e instanceof SecurityException)) {
1039164371fb759bad6854570af0fca60d9a01e17235Dianne Hackborn                Slog.wtf(TAG, "Input Method Manager Crash", e);
10409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw e;
10429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1045a00271533f639c8ed36429c663889ac9f654bc72Svetoslav Ganov    public void systemRunning(StatusBarManagerService statusBar) {
1046a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        synchronized (mMethodMap) {
10474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
10484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "--- systemReady");
10494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
1050a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            if (!mSystemReady) {
1051a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn                mSystemReady = true;
10524e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mKeyguardManager =
10534e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
1054661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mNotificationManager = (NotificationManager)
1055661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
1056661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                mStatusBar = statusBar;
1057661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                statusBar.setIconVisibility("ime", false);
1058d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition);
1059b858c732f665fe9610f2d913230ae625f44a8caasatok                mShowOngoingImeSwitcherForPhones = mRes.getBoolean(
1060b858c732f665fe9610f2d913230ae625f44a8caasatok                        com.android.internal.R.bool.show_ongoing_ime_switcher);
106101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                if (mShowOngoingImeSwitcherForPhones) {
106201038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    mWindowManagerService.setOnHardKeyboardStatusChangeListener(
106301038492ff0317f0d3cff54d8a7ee36bb31ff175satok                            mHardKeyboardListener);
106401038492ff0317f0d3cff54d8a7ee36bb31ff175satok                }
1065f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                buildInputMethodListLocked(mMethodList, mMethodMap,
1066f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                        !mImeSelectedOnBoot /* resetDefaultEnabledIme */);
10670a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (!mImeSelectedOnBoot) {
10680a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                    Slog.w(TAG, "Reset the default IME as \"Resource\" is ready here.");
1069ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    resetStateIfCurrentLocaleChangedLocked();
1070ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                    InputMethodUtils.setNonSelectedSystemImesDisabledUntilUsed(
1071ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mContext.getPackageManager(),
1072ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            mSettings.getEnabledInputMethodListLocked());
10730a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
10740a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                mLastSystemLocale = mRes.getConfiguration().locale;
1075cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                try {
1076cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    startInputInnerLocked();
1077cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                } catch (RuntimeException e) {
10788a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Unexpected exception", e);
1079cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1080a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            }
1081a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
10829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1083ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
10844e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // ---------------------------------------------------------------------------------------
10854e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // Check whether or not this is a valid IPC. Assumes an IPC is valid when either
10864e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 1) it comes from the system process
10874e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    // 2) the calling process' user id is identical to the current user id IMMS thinks.
10884e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean calledFromValidUser() {
10894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int uid = Binder.getCallingUid();
10904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final int userId = UserHandle.getUserId(uid);
10914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
10924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.d(TAG, "--- calledFromForegroundUserOrSystemProcess ? "
10934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + "calling uid = " + uid + " system uid = " + Process.SYSTEM_UID
10944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    + " calling userId = " + userId + ", foreground user id = "
109587c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + mSettings.getCurrentUserId() + ", calling pid = " + Binder.getCallingPid()
109687c291421544821fe9d10a08ee4e9f31b62d5052Satoshi Kataoka                    + InputMethodUtils.getApiCallStack());
10974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
10982a764949c943681a4d25a17a0b203a0127a4a486Kenny Guy        if (uid == Process.SYSTEM_UID || mSettings.isCurrentProfile(userId)) {
10994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return true;
11004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1101135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka
1102135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Caveat: A process which has INTERACT_ACROSS_USERS_FULL gets results for the
1103135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // foreground user, not for the user of that process. Accordingly InputMethodManagerService
1104135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // must not manage background users' states in any functions.
1105135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // Note that privacy-sensitive IPCs, such as setInputMethod, are still securely guarded
1106135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        // by a token.
1107135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        if (mContext.checkCallingOrSelfPermission(
1108135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
1109135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        == PackageManager.PERMISSION_GRANTED) {
1110135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            if (DEBUG) {
1111135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                Slog.d(TAG, "--- Access granted because the calling process has "
1112135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka                        + "the INTERACT_ACROSS_USERS_FULL permission");
1113135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            }
1114135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka            return true;
1115135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        }
11160766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka        Slog.w(TAG, "--- IPC called from background users. Ignore. \n"
11170766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                + InputMethodUtils.getStackTrace());
1118135e5fb71242b1151929e2ea7bf221ff421e6ad2Satoshi Kataoka        return false;
11194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
11204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
112122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
112222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    /**
112322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * Returns true iff the caller is identified to be the current input method with the token.
112422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @param token The window token given to the input method when it was started.
112522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     * @return true if and only if non-null valid token is specified.
112622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa     */
112722c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    private boolean calledWithValidToken(IBinder token) {
112822c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        if (token == null || mCurToken != token) {
112922c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            return false;
113022c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        }
113122c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa        return true;
113222c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa    }
113322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa
11344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private boolean bindCurrentInputMethodService(
11354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Intent service, ServiceConnection conn, int flags) {
11364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (service == null || conn == null) {
11374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            Slog.e(TAG, "--- bind failed: service = " + service + ", conn = " + conn);
11384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
11394e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
114027b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani        return mContext.bindServiceAsUser(service, conn, flags,
114127b89e6658a0d233a53f5d7ca20dc57fec82d955Amith Yamasani                new UserHandle(mSettings.getCurrentUserId()));
11424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
11434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
1144e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
11459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getInputMethodList() {
11464e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
11474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
11484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
11494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
11509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
11519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return new ArrayList<InputMethodInfo>(mMethodList);
11529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1155e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
11569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public List<InputMethodInfo> getEnabledInputMethodList() {
11574e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
11584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
11594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return Collections.emptyList();
11604e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
11619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1162d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return mSettings.getEnabledInputMethodListLocked();
11639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11668e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka    /**
1167b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka     * @param imiId if null, returns enabled subtypes for the current imi
11688e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     * @return enabled subtypes of the specified imi
11698e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka     */
1170e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1171b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka    public List<InputMethodSubtype> getEnabledInputMethodSubtypeList(String imiId,
117216331c8a1d33defccc5cbb18694def79196c921bsatok            boolean allowsImplicitlySelectedSubtypes) {
11734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
11744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
1175b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            return Collections.<InputMethodSubtype>emptyList();
11764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
117767ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        synchronized (mMethodMap) {
1178b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            final InputMethodInfo imi;
1179b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imiId == null && mCurMethodId != null) {
11808e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                imi = mMethodMap.get(mCurMethodId);
1181b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            } else {
1182b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                imi = mMethodMap.get(imiId);
1183b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            }
1184b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka            if (imi == null) {
1185b3c21ac7c661022534135bf688a75ec35fe3a8f2Satoshi Kataoka                return Collections.<InputMethodSubtype>emptyList();
11868e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            }
11878e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            return mSettings.getEnabledInputMethodSubtypeListLocked(
11888e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mContext, imi, allowsImplicitlySelectedSubtypes);
118967ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok        }
119067ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok    }
119167ddf9cbd5d7133c7f443cd3c55841ed1109c3a0satok
1192e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
11939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void addClient(IInputMethodClient client,
11949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            IInputContext inputContext, int uid, int pid) {
11954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
11964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
11974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
11989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
11999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mClients.put(client.asBinder(), new ClientState(client,
12009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    inputContext, uid, pid));
12019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1203ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1204e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
12059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void removeClient(IInputMethodClient client) {
12064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
12074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
12084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
12099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
1210c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            ClientState cs = mClients.remove(client.asBinder());
1211c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (cs != null) {
1212c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
1213c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
12149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1216ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void executeOrSendMessage(IInterface target, Message msg) {
12189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         if (target.asBinder() instanceof Binder) {
12199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             mCaller.sendMessage(msg);
12209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         } else {
12219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             handleMessage(msg);
12229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project             msg.recycle();
12239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project         }
12249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1225ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1226b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void unbindCurrentClientLocked() {
12279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != null) {
12288a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "unbindCurrentInputLocked: client = "
12299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurClient.client.asBinder());
12309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mBoundToMethod) {
12319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mBoundToMethod = false;
12329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
12339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
12349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_INPUT, mCurMethod));
12359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
12369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1237a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn
1238a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1239a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    MSG_SET_ACTIVE, 0, mCurClient));
12409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
12419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
12429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient.sessionRequested = false;
12439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurClient = null;
1244ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1245105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
12469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1248ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getImeShowFlags() {
12509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
12519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
12529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_FORCED
12539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    | InputMethod.SHOW_EXPLICIT;
12549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mShowExplicitlyRequested) {
12559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethod.SHOW_EXPLICIT;
12569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
12589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1259ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private int getAppShowFlags() {
12619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int flags = 0;
12629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced) {
12639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_FORCED;
12649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (!mShowExplicitlyRequested) {
12659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            flags |= InputMethodManager.SHOW_IMPLICIT;
12669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return flags;
12689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1269ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12707663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    InputBindResult attachNewInputLocked(boolean initial) {
12719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!mBoundToMethod) {
12729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
12739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_BIND_INPUT, mCurMethod, mCurClient.binding));
12749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mBoundToMethod = true;
12759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final SessionState session = mCurClient.curSession;
12779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (initial) {
12789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
12799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_START_INPUT, session, mCurInputContext, mCurAttribute));
12809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
12819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            executeOrSendMessage(session.method, mCaller.obtainMessageOOO(
12829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    MSG_RESTART_INPUT, session, mCurInputContext, mCurAttribute));
12839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowRequested) {
12858a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Attach new input asks to show input");
12864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            showCurrentInputLocked(getAppShowFlags(), null);
12879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
12881951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown        return new InputBindResult(session.session,
12893d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                (session.channel != null ? session.channel.dup() : null),
12903d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                mCurId, mCurSeq, mCurUserActionNotificationSequenceNumber);
12919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1292ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
12939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    InputBindResult startInputLocked(IInputMethodClient client,
12947663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
12959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // If no method is currently selected, do nothing.
12969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethodId == null) {
12979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return mNoBinding;
12989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1299ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState cs = mClients.get(client.asBinder());
13019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cs == null) {
13029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("unknown client "
13039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + client.asBinder());
13049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1305ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
13079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
13089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Check with the window manager to make sure this client actually
13099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // has a window with focus.  If not, reject.  This is thread safe
13109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // because if the focus changes some time before or after, the
13119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // next client receiving focus that has any interest in input will
13129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // be calling through here after that change happens.
13138a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Starting input on non-focused client " + cs.client
13149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
13159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return null;
13169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } catch (RemoteException e) {
13189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1319ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13207663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return startInputUncheckedLocked(cs, inputContext, attribute, controlFlags);
13217663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    }
13227663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
1323a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw    InputBindResult startInputUncheckedLocked(@NonNull ClientState cs,
1324d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa            IInputContext inputContext, @NonNull EditorInfo attribute, int controlFlags) {
13257663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        // If no method is currently selected, do nothing.
13267663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        if (mCurMethodId == null) {
13277663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            return mNoBinding;
13287663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        }
13297663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
1330d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa        if (!InputMethodUtils.checkIfPackageBelongsToUid(mAppOpsManager, cs.uid,
1331d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa                attribute.packageName)) {
1332d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa            Slog.e(TAG, "Rejecting this client as it reported an invalid package name."
1333d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa                    + " uid=" + cs.uid + " package=" + attribute.packageName);
1334d57ba675b1f767885e6d3ccd4d0f7037e634648bYohei Yukawa            return mNoBinding;
1335a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw        }
1336a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw
13379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurClient != cs) {
1338e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            // Was the keyguard locked when switching over to the new client?
1339e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock            mCurClientInKeyguard = isKeyguardLocked();
13409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the client is changing, we need to switch over to the new
13419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // one.
1342b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
13438a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "switching to client: client = "
1344e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock                    + cs.client.asBinder() + " keyguard=" + mCurClientInKeyguard);
13459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
13469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // If the screen is on, inform the new client it is active
13479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mScreenOn) {
1348a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                executeOrSendMessage(cs.client, mCaller.obtainMessageIO(
1349a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                        MSG_SET_ACTIVE, mScreenOn ? 1 : 0, cs));
13509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1352ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Bump up the sequence for this client and attach it.
13549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurSeq++;
13559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurSeq <= 0) mCurSeq = 1;
13569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurClient = cs;
13579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurInputContext = inputContext;
13589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurAttribute = attribute;
1359ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
13609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Check if the input method is changing.
13619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurId != null && mCurId.equals(mCurMethodId)) {
13629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cs.curSession != null) {
13639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Fast case: if we are already connected to the input method,
13649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // then just return it.
13657663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return attachNewInputLocked(
13667663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_START_INITIAL) != 0);
13679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mHaveConnection) {
13699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurMethod != null) {
13709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // Return to client, and we will get back with it when
13719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we have had a session made for it.
1372c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(cs);
13733d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    return new InputBindResult(null, null, mCurId, mCurSeq,
13743d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            mCurUserActionNotificationSequenceNumber);
13759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (SystemClock.uptimeMillis()
13769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        < (mLastBindTime+TIME_TO_RECONNECT)) {
13779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // In this case we have connected to the service, but
13789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // don't yet have its interface.  If it hasn't been too
13799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // long since we did the connection, we'll return to
13809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // the client and wait to get the service interface so
13819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // we can report back.  If it has been too long, we want
13829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to fall through so we can try a disconnect/reconnect
13839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // to see if we can get back in touch with the service.
13843d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    return new InputBindResult(null, null, mCurId, mCurSeq,
13853d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            mCurUserActionNotificationSequenceNumber);
13869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else {
1387ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                    EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME,
1388ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker                            mCurMethodId, SystemClock.uptimeMillis()-mLastBindTime, 0);
13899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
13909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
13919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1392ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1393a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        return startInputInnerLocked();
1394a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    }
1395ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1396a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn    InputBindResult startInputInnerLocked() {
1397a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (mCurMethodId == null) {
1398a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            return mNoBinding;
1399a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1400ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1401a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        if (!mSystemReady) {
1402a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // If the system is not yet ready, we shouldn't be running third
1403a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn            // party code.
14043d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            return new InputBindResult(null, null, mCurMethodId, mCurSeq,
14053d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    mCurUserActionNotificationSequenceNumber);
1406a34f1ad7c3a68d971e6332aa2fb1c16d083920b3Dianne Hackborn        }
1407ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(mCurMethodId);
14099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
14109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
14119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1412ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14132ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn        unbindCurrentMethodLocked(false, true);
1414ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
14159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent = new Intent(InputMethod.SERVICE_INTERFACE);
14169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCurIntent.setComponent(info.getComponent());
1417dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_LABEL,
1418dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                com.android.internal.R.string.input_method_binding_label);
1419dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn        mCurIntent.putExtra(Intent.EXTRA_CLIENT_INTENT, PendingIntent.getActivity(
1420dd9b82c283815747b75fe4434c65e4b6c9c9b54fDianne Hackborn                mContext, 0, new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS), 0));
14214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
1422f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_NOT_VISIBLE | Context.BIND_NOT_FOREGROUND
1423f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                | Context.BIND_SHOWING_UI)) {
14249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mLastBindTime = SystemClock.uptimeMillis();
14259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mHaveConnection = true;
14269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurId = info.getId();
14279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurToken = new Binder();
14289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
1429ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                if (true || DEBUG) Slog.v(TAG, "Adding window token: " + mCurToken);
14309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mIWindowManager.addWindowToken(mCurToken,
14319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        WindowManager.LayoutParams.TYPE_INPUT_METHOD);
14329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
14339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14343d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            return new InputBindResult(null, null, mCurId, mCurSeq,
14353d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    mCurUserActionNotificationSequenceNumber);
14369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else {
14379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurIntent = null;
14388a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            Slog.w(TAG, "Failure connecting to input method service: "
14399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mCurIntent);
14409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
14429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1443ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1444e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public InputBindResult startInput(IInputMethodClient client,
14467663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            IInputContext inputContext, EditorInfo attribute, int controlFlags) {
14474e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
14484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
14494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
14509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final long ident = Binder.clearCallingIdentity();
14529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
14537663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                return startInputLocked(client, inputContext, attribute, controlFlags);
14549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
14559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
14569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1459ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1460e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void finishInput(IInputMethodClient client) {
14629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1463ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1464e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
14659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceConnected(ComponentName name, IBinder service) {
14669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurIntent != null && name.equals(mCurIntent.getComponent())) {
14689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCurMethod = IInputMethod.Stub.asInterface(service);
1469cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                if (mCurToken == null) {
14708a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Service connected without a token!");
14712ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                    unbindCurrentMethodLocked(false, false);
1472cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                    return;
1473cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                }
1474e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Initiating attach with token: " + mCurToken);
1475cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
1476cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn                        MSG_ATTACH_TOKEN, mCurMethod, mCurToken));
14779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1478c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
1479c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    requestClientSessionLocked(mCurClient);
14809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
14819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
14829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
14839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
14849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1485c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void onSessionCreated(IInputMethod method, IInputMethodSession session,
1486c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel channel) {
14879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
14889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && method != null
14899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && mCurMethod.asBinder() == method.asBinder()) {
14909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
1491c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    clearClientSessionLocked(mCurClient);
14929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCurClient.curSession = new SessionState(mCurClient,
1493c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                            method, session, channel);
14947663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    InputBindResult res = attachNewInputLocked(true);
14959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    if (res.method != null) {
14969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        executeOrSendMessage(mCurClient.client, mCaller.obtainMessageOO(
14979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                MSG_BIND_METHOD, mCurClient.client, res));
14989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
1499c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    return;
15009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
15019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1503c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1504c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        // Session abandoned.  Close its associated input channel.
1505c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        channel.dispose();
15069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1507ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
15082ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn    void unbindCurrentMethodLocked(boolean reportToClient, boolean savePosition) {
15092c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mVisibleBound) {
15102c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
15112c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
15122c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
15132c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn
1514b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mHaveConnection) {
1515b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mContext.unbindService(this);
1516b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mHaveConnection = false;
1517b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1518ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1519b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (mCurToken != null) {
1520b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            try {
15218a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Removing window token: " + mCurToken);
15222ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                if ((mImeWindowVis & InputMethodService.IME_ACTIVE) != 0 && savePosition) {
1523e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    // The current IME is shown. Hence an IME switch (transition) is happening.
1524e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                    mWindowManagerService.saveLastInputMethodWindowForTransition();
1525e0a99414bd3737ad976bf4a040c184bebd8e2e3dsatok                }
1526b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mIWindowManager.removeWindowToken(mCurToken);
1527b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            } catch (RemoteException e) {
1528b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            }
1529b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            mCurToken = null;
1530b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1531ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1532105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mCurId = null;
1533b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        clearCurMethodLocked();
1534ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1535b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        if (reportToClient && mCurClient != null) {
1536b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
1537b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                    MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
1538b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        }
1539b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    }
1540c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1541c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void requestClientSessionLocked(ClientState cs) {
1542c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (!cs.sessionRequested) {
1543c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (DEBUG) Slog.v(TAG, "Creating new session for client " + cs);
1544c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            InputChannel[] channels = InputChannel.openInputChannelPair(cs.toString());
1545c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            cs.sessionRequested = true;
1546c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOOO(
1547c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    MSG_CREATE_SESSION, mCurMethod, channels[1],
1548c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    new MethodCallback(this, mCurMethod, channels[0])));
1549c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        }
1550c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1551c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1552c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    void clearClientSessionLocked(ClientState cs) {
1553c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        finishSessionLocked(cs.curSession);
1554c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.curSession = null;
1555c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        cs.sessionRequested = false;
1556c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    }
1557c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown
1558c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown    private void finishSessionLocked(SessionState sessionState) {
1559c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown        if (sessionState != null) {
1560c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.session != null) {
1561c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                try {
1562c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    sessionState.session.finishSession();
1563c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } catch (RemoteException e) {
1564c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    Slog.w(TAG, "Session failed to close due to remote exception", e);
1565d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    updateSystemUiLocked(mCurToken, 0 /* vis */, mBackDisposition);
1566c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                }
1567c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.session = null;
1568c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
1569c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            if (sessionState.channel != null) {
1570c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel.dispose();
1571c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                sessionState.channel = null;
15720c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            }
15730c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor        }
15740c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor    }
1575ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1576b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project    void clearCurMethodLocked() {
15779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
15789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState cs : mClients.values()) {
1579c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                clearClientSessionLocked(cs);
15809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
15810c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor
1582c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            finishSessionLocked(mEnabledSession);
15830c33ed2992b2eb484c229fd3322df14d97c10caaDevin Taylor            mEnabledSession = null;
15849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCurMethod = null;
15859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1586661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        if (mStatusBar != null) {
1587661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn            mStatusBar.setIconVisibility("ime", false);
1588661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn        }
15899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1590ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1591e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
15929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void onServiceDisconnected(ComponentName name) {
15939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
15948a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.v(TAG, "Service disconnected: " + name
15959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mCurIntent=" + mCurIntent);
15969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurMethod != null && mCurIntent != null
15979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && name.equals(mCurIntent.getComponent())) {
1598b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                clearCurMethodLocked();
15999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // We consider this to be a new bind attempt, since the system
16009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // should now try to restart the service for us.
16019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mLastBindTime = SystemClock.uptimeMillis();
16029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mShowRequested = mInputShown;
16039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mInputShown = false;
16049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient != null) {
16059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
16069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            MSG_UNBIND_METHOD, mCurSeq, mCurClient.client));
16079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1612f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
16139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void updateStatusIcon(IBinder token, String packageName, int iconId) {
16149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
16159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
16169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
1617a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                if (!calledWithValidToken(token)) {
1618a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    final int uid = Binder.getCallingUid();
1619a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    Slog.e(TAG, "Ignoring updateStatusIcon due to an invalid token. uid:" + uid
1620a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                            + " token:" + token);
1621a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                    return;
1622a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                }
16239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (iconId == 0) {
16248a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "hide the small icon for the input method");
1625661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1626661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", false);
1627661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
16289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } else if (packageName != null) {
16298a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.d(TAG, "show a small icon for the input method");
16306179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    CharSequence contentDescription = null;
16316179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    try {
16324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        // Use PackageManager to load label
16334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        final PackageManager packageManager = mContext.getPackageManager();
16346179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        contentDescription = packageManager.getApplicationLabel(
16354e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mIPackageManager.getApplicationInfo(packageName, 0,
16364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                        mSettings.getCurrentUserId()));
16374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    } catch (RemoteException e) {
16386179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                        /* ignore */
16396179ea3196e9306d3f14361fe9ef14191b1edba6Svetoslav Ganov                    }
1640661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    if (mStatusBar != null) {
1641661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIcon("ime", packageName, iconId, 0,
1642661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                contentDescription  != null
1643661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                                        ? contentDescription.toString() : null);
1644661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                        mStatusBar.setIconVisibility("ime", true);
1645661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
16469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
16479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
16489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
16499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
16509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
16519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
16529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1653d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    private boolean shouldShowImeSwitcherLocked(int visibility) {
16547cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        if (!mShowOngoingImeSwitcherForPhones) return false;
1655807ef76e23e08405532a0e7e2d71e7433bf7ae9aJason Monk        if (mSwitchingDialog != null) return false;
16562c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        if (isScreenLocked()) return false;
1657d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if ((visibility & InputMethodService.IME_ACTIVE) == 0) return false;
1658c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (mWindowManagerService.isHardKeyboardAvailable()) {
1659c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // When physical keyboard is attached, we show the ime switcher (or notification if
1660c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // NavBar is not available) because SHOW_IME_WITH_HARD_KEYBOARD settings currently
1661c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // exists in the IME switcher dialog.  Might be OK to remove this condition once
1662c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            // SHOW_IME_WITH_HARD_KEYBOARD settings finds a good place to live.
1663c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            return true;
1664c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        }
1665d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if ((visibility & InputMethodService.IME_VISIBLE) == 0) return false;
1666c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa
1667c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
1668c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        final int N = imis.size();
1669c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (N > 2) return true;
1670c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (N < 1) return false;
1671c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        int nonAuxCount = 0;
1672c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        int auxCount = 0;
1673c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        InputMethodSubtype nonAuxSubtype = null;
1674c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        InputMethodSubtype auxSubtype = null;
1675c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        for(int i = 0; i < N; ++i) {
1676c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            final InputMethodInfo imi = imis.get(i);
1677c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            final List<InputMethodSubtype> subtypes =
1678c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
1679c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            final int subtypeCount = subtypes.size();
1680c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            if (subtypeCount == 0) {
1681c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                ++nonAuxCount;
1682c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            } else {
1683c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                for (int j = 0; j < subtypeCount; ++j) {
1684c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    final InputMethodSubtype subtype = subtypes.get(j);
1685c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    if (!subtype.isAuxiliary()) {
1686c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        ++nonAuxCount;
1687c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        nonAuxSubtype = subtype;
1688c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    } else {
1689c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        ++auxCount;
1690c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                        auxSubtype = subtype;
16917cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
16927cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
16937cfc0ed21a3fafabafb40b38a8589808ad1517afsatok            }
1694c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        }
1695c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        if (nonAuxCount > 1 || auxCount > 1) {
1696c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            return true;
1697c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        } else if (nonAuxCount == 1 && auxCount == 1) {
1698c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            if (nonAuxSubtype != null && auxSubtype != null
1699c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    && (nonAuxSubtype.getLocale().equals(auxSubtype.getLocale())
1700c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                            || auxSubtype.overridesImplicitlyEnabledSubtype()
1701c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                            || nonAuxSubtype.overridesImplicitlyEnabledSubtype())
1702c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                    && nonAuxSubtype.containsExtraValueKey(TAG_TRY_SUPPRESSING_IME_SWITCHER)) {
1703c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa                return false;
1704b6359414adabab2d64acc8ccc9e3b9c1b800b303satok            }
1705c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa            return true;
17067cfc0ed21a3fafabafb40b38a8589808ad1517afsatok        }
1707c6c7cd2736fc3b6511e329a969409622750f2a58Yohei Yukawa        return false;
17087cfc0ed21a3fafabafb40b38a8589808ad1517afsatok    }
17097cfc0ed21a3fafabafb40b38a8589808ad1517afsatok
1710e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    private boolean isKeyguardLocked() {
1711e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock        return mKeyguardManager != null && mKeyguardManager.isKeyguardLocked();
1712e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock    }
1713e0980501e9b0c5a4f481481f3c5cb2f78f08c5aaJohn Spurlock
1714dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("deprecation")
1715f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    @Override
1716857fd9b8562c29913e03ed29288bd1802d37dc60Joe Onorato    public void setImeWindowStatus(IBinder token, int vis, int backDisposition) {
1717d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if (!calledWithValidToken(token)) {
1718d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final int uid = Binder.getCallingUid();
1719d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            Slog.e(TAG, "Ignoring setImeWindowStatus due to an invalid token. uid:" + uid
1720d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    + " token:" + token);
1721d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            return;
1722d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1723d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1724d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        synchronized (mMethodMap) {
1725d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            mImeWindowVis = vis;
1726d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            mBackDisposition = backDisposition;
1727d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            updateSystemUiLocked(token, vis, backDisposition);
1728d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1729d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    }
1730d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1731d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    private void updateSystemUi(IBinder token, int vis, int backDisposition) {
1732d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        synchronized (mMethodMap) {
1733d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            updateSystemUiLocked(token, vis, backDisposition);
1734d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1735d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    }
1736d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1737d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    // Caution! This method is called in this class. Handle multi-user carefully
1738d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka    private void updateSystemUiLocked(IBinder token, int vis, int backDisposition) {
1739d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        if (!calledWithValidToken(token)) {
1740d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final int uid = Binder.getCallingUid();
1741d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            Slog.e(TAG, "Ignoring updateSystemUiLocked due to an invalid token. uid:" + uid
1742d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    + " token:" + token);
1743d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            return;
1744d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        }
1745d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka
1746d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        // TODO: Move this clearing calling identity block to setImeWindowStatus after making sure
1747d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        // all updateSystemUi happens on system previlege.
17484e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final long ident = Binder.clearCallingIdentity();
174906487a58be22b100daf3f950b9a1d25c3ea42aa2satok        try {
1750d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            // apply policy for binder calls
1751d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            if (vis != 0 && isKeyguardLocked() && !mCurClientInKeyguard) {
1752d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                vis = 0;
175306487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
1754d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            // mImeWindowVis should be updated before calling shouldShowImeSwitcherLocked().
1755d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final boolean needsToShowImeSwitcher = shouldShowImeSwitcherLocked(vis);
1756d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            if (mStatusBar != null) {
1757d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                mStatusBar.setImeWindowStatus(token, vis, backDisposition,
1758d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        needsToShowImeSwitcher);
1759d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            }
1760d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
1761d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            if (imi != null && needsToShowImeSwitcher) {
1762d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                // Used to load label
1763d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                final CharSequence title = mRes.getText(
1764d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        com.android.internal.R.string.select_input_method);
1765d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
1766d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        mContext, imi, mCurrentSubtype);
17671ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                mImeSwitcherNotification.setContentTitle(title)
17681ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                        .setContentText(summary)
17691ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                        .setContentIntent(mImeSwitchPendingIntent);
1770d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                if ((mNotificationManager != null)
1771d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        && !mWindowManagerService.hasNavigationBar()) {
1772d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    if (DEBUG) {
1773d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        Slog.d(TAG, "--- show notification: label =  " + summary);
1774661cd52e0e1d527132eb1cae604d3e64da7ec0cbDianne Hackborn                    }
1775d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationManager.notifyAsUser(null,
1776d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                            com.android.internal.R.string.select_input_method,
17771ce4b6d3c6cb5b2eb9c9d00472be12245db92427Chris Wren                            mImeSwitcherNotification.build(), UserHandle.ALL);
1778d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationShown = true;
1779d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                }
1780d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            } else {
1781d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                if (mNotificationShown && mNotificationManager != null) {
1782d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    if (DEBUG) {
1783d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        Slog.d(TAG, "--- hide notification");
17847cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                    }
1785d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationManager.cancelAsUser(null,
1786d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                            com.android.internal.R.string.select_input_method, UserHandle.ALL);
1787d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                    mNotificationShown = false;
17887cfc0ed21a3fafabafb40b38a8589808ad1517afsatok                }
178906487a58be22b100daf3f950b9a1d25c3ea42aa2satok            }
179006487a58be22b100daf3f950b9a1d25c3ea42aa2satok        } finally {
179106487a58be22b100daf3f950b9a1d25c3ea42aa2satok            Binder.restoreCallingIdentity(ident);
179206487a58be22b100daf3f950b9a1d25c3ea42aa2satok        }
179306487a58be22b100daf3f950b9a1d25c3ea42aa2satok    }
179406487a58be22b100daf3f950b9a1d25c3ea42aa2satok
1795e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1796f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public void registerSuggestionSpansForNotification(SuggestionSpan[] spans) {
17974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
17984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
17994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1800f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1801f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
1802f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            for (int i = 0; i < spans.length; ++i) {
1803f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                SuggestionSpan ss = spans[i];
180442c5a1666c4e576ccd5974233513100aad2c1534satok                if (!TextUtils.isEmpty(ss.getNotificationTargetClassName())) {
1805f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                    mSecureSuggestionSpans.put(ss, currentImi);
1806f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                }
1807f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1808f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1809f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1810f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1811e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
1812f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    public boolean notifySuggestionPicked(SuggestionSpan span, String originalString, int index) {
18134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
18144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
18154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1816f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        synchronized (mMethodMap) {
1817f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            final InputMethodInfo targetImi = mSecureSuggestionSpans.get(span);
1818f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            // TODO: Do not send the intent if the process of the targetImi is already dead.
1819f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            if (targetImi != null) {
1820f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final String[] suggestions = span.getSuggestions();
1821f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                if (index < 0 || index >= suggestions.length) return false;
182242c5a1666c4e576ccd5974233513100aad2c1534satok                final String className = span.getNotificationTargetClassName();
1823f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                final Intent intent = new Intent();
1824f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // Ensures that only a class in the original IME package will receive the
1825f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                // notification.
182642c5a1666c4e576ccd5974233513100aad2c1534satok                intent.setClassName(targetImi.getPackageName(), className);
1827f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.setAction(SuggestionSpan.ACTION_SUGGESTION_PICKED);
1828f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_BEFORE, originalString);
1829f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_AFTER, suggestions[index]);
1830f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                intent.putExtra(SuggestionSpan.SUGGESTION_SPAN_PICKED_HASHCODE, span.hashCode());
1831f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                final long ident = Binder.clearCallingIdentity();
1832f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                try {
1833f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
1834f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                } finally {
1835f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                    Binder.restoreCallingIdentity(ident);
1836f043de93ebb5178fb4b5c8f14e143c6f08bcc26fAmith Yamasani                }
1837f9f01008624e2d28c15a90d942fa36f98c8c967dsatok                return true;
1838f9f01008624e2d28c15a90d942fa36f98c8c967dsatok            }
1839f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        }
1840f9f01008624e2d28c15a90d942fa36f98c8c967dsatok        return false;
1841f9f01008624e2d28c15a90d942fa36f98c8c967dsatok    }
1842f9f01008624e2d28c15a90d942fa36f98c8c967dsatok
1843fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn    void updateFromSettingsLocked(boolean enabledMayChange) {
18447b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        updateInputMethodsFromSettingsLocked(enabledMayChange);
18457b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        updateKeyboardFromSettingsLocked();
18467b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    }
18477b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
18487b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    void updateInputMethodsFromSettingsLocked(boolean enabledMayChange) {
1849fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        if (enabledMayChange) {
1850fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
1851fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            for (int i=0; i<enabled.size(); i++) {
1852fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // We allow the user to select "disabled until used" apps, so if they
1853fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                // are enabling one of those here we now need to make it enabled.
1854fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                InputMethodInfo imm = enabled.get(i);
1855fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                try {
1856fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    ApplicationInfo ai = mIPackageManager.getApplicationInfo(imm.getPackageName(),
1857fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
1858fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            mSettings.getCurrentUserId());
18597987a3172b0502ea70a26d80e7cd16ca7e460035Satoshi Kataoka                    if (ai != null && ai.enabledSetting
1860fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                            == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_UNTIL_USED) {
1861ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        if (DEBUG) {
1862ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                            Slog.d(TAG, "Update state(" + imm.getId()
1863ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                                    + "): DISABLED_UNTIL_USED -> DEFAULT");
1864ed1cdb24ba986231629fbfb244ed758fc2add0fcSatoshi Kataoka                        }
1865fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                        mIPackageManager.setApplicationEnabledSetting(imm.getPackageName(),
1866fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                                PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
18673fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                PackageManager.DONT_KILL_APP, mSettings.getCurrentUserId(),
18683fa3c28a356108a6558b6b54a0b10e1a5cc4f1b6Dianne Hackborn                                mContext.getBasePackageName());
1869fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                    }
1870fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                } catch (RemoteException e) {
1871fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                }
1872fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn            }
1873fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn        }
1874b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // We are assuming that whoever is changing DEFAULT_INPUT_METHOD and
1875b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // ENABLED_INPUT_METHODS is taking care of keeping them correctly in
1876b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // sync, so we will never have a DEFAULT_INPUT_METHOD that is not
1877b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        // enabled.
18784e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String id = mSettings.getSelectedInputMethod();
187903eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        // There is no input method selected, try to choose new applicable input method.
188003eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (TextUtils.isEmpty(id) && chooseNewDefaultIMELocked()) {
18814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            id = mSettings.getSelectedInputMethod();
188203eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        }
188303eb319a3a7fe6fe9ab9eba6fc1f727285850906satok        if (!TextUtils.isEmpty(id)) {
18849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
18858e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                setInputMethodLocked(id, mSettings.getSelectedInputMethodSubtypeId(id));
18869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IllegalArgumentException e) {
18878a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unknown input method from prefs: " + id, e);
1888105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project                mCurMethodId = null;
18892ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn                unbindCurrentMethodLocked(true, false);
18909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1891f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.clear();
1892b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project        } else {
1893b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            // There is no longer an input method set, so stop any current one.
1894105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mCurMethodId = null;
18952ea9bae7121f1df5461437d7d08fa550cdf6e0b0Dianne Hackborn            unbindCurrentMethodLocked(true, false);
18969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
18973d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
18983d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
18993d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
19003d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
19013d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
19027b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
19037b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    }
19047b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright
19057b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright    public void updateKeyboardFromSettingsLocked() {
19067b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        mShowImeWithHardKeyboard = mSettings.isShowImeWithHardKeyboardEnabled();
19077b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        if (mSwitchingDialog != null
19087b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                && mSwitchingDialogTitleView != null
19097b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                && mSwitchingDialog.isShowing()) {
19107b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            final Switch hardKeySwitch = (Switch)mSwitchingDialogTitleView.findViewById(
19117b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    com.android.internal.R.id.hard_keyboard_switch);
19127b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
19137b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright        }
19149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1915ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1916ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /* package */ void setInputMethodLocked(String id, int subtypeId) {
19179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        InputMethodInfo info = mMethodMap.get(id);
19189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (info == null) {
1919913a8925c07e854a80bf5df87561f290d3a56d61satok            throw new IllegalArgumentException("Unknown id: " + id);
19209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1921ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1922e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        if (mCurClient != null && mCurAttribute != null) {
1923a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw            // We have already made sure that the package name belongs to the application's UID.
1924a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw            // No further UID check is required.
1925a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw            if (SystemConfig.getInstance().getFixedImeApps().contains(mCurAttribute.packageName)) {
1926a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw                return;
1927e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa            }
1928e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa        }
1929e63b5fae8d099d2f5d4d5a5cf7a8d5a86266c0feYohei Yukawa
1930d81e950265356c81276b73da68a535ffa48d72f0satok        // See if we need to notify a subtype change within the same IME.
19319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (id.equals(mCurMethodId)) {
1932d81e950265356c81276b73da68a535ffa48d72f0satok            final int subtypeCount = info.getSubtypeCount();
1933d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeCount <= 0) {
1934d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1935d81e950265356c81276b73da68a535ffa48d72f0satok            }
1936d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype oldSubtype = mCurrentSubtype;
1937d81e950265356c81276b73da68a535ffa48d72f0satok            final InputMethodSubtype newSubtype;
1938d81e950265356c81276b73da68a535ffa48d72f0satok            if (subtypeId >= 0 && subtypeId < subtypeCount) {
1939d81e950265356c81276b73da68a535ffa48d72f0satok                newSubtype = info.getSubtypeAt(subtypeId);
1940d81e950265356c81276b73da68a535ffa48d72f0satok            } else {
1941d81e950265356c81276b73da68a535ffa48d72f0satok                // If subtype is null, try to find the most applicable one from
1942d81e950265356c81276b73da68a535ffa48d72f0satok                // getCurrentInputMethodSubtype.
19434e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                newSubtype = getCurrentInputMethodSubtypeLocked();
1944d81e950265356c81276b73da68a535ffa48d72f0satok            }
1945d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype == null || oldSubtype == null) {
1946d81e950265356c81276b73da68a535ffa48d72f0satok                Slog.w(TAG, "Illegal subtype state: old subtype = " + oldSubtype
1947d81e950265356c81276b73da68a535ffa48d72f0satok                        + ", new subtype = " + newSubtype);
1948d81e950265356c81276b73da68a535ffa48d72f0satok                return;
1949d81e950265356c81276b73da68a535ffa48d72f0satok            }
1950d81e950265356c81276b73da68a535ffa48d72f0satok            if (newSubtype != oldSubtype) {
1951d81e950265356c81276b73da68a535ffa48d72f0satok                setSelectedInputMethodAndSubtypeLocked(info, subtypeId, true);
1952d81e950265356c81276b73da68a535ffa48d72f0satok                if (mCurMethod != null) {
1953d81e950265356c81276b73da68a535ffa48d72f0satok                    try {
1954d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka                        updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition);
1955d81e950265356c81276b73da68a535ffa48d72f0satok                        mCurMethod.changeInputMethodSubtype(newSubtype);
1956d81e950265356c81276b73da68a535ffa48d72f0satok                    } catch (RemoteException e) {
1957d81e950265356c81276b73da68a535ffa48d72f0satok                        Slog.w(TAG, "Failed to call changeInputMethodSubtype");
1958ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
1959ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                }
1960ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            }
19619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
19629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
1963ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
1964d81e950265356c81276b73da68a535ffa48d72f0satok        // Changing to a different IME.
19659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final long ident = Binder.clearCallingIdentity();
19669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
1967ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // Set a subtype to this input method.
1968ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            // subtypeId the name of a subtype which will be set.
1969723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            setSelectedInputMethodAndSubtypeLocked(info, subtypeId, false);
1970723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // mCurMethodId should be updated after setSelectedInputMethodAndSubtypeLocked()
1971723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // because mCurMethodId is stored as a history in
1972723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // setSelectedInputMethodAndSubtypeLocked().
1973723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mCurMethodId = id;
19749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
19759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (ActivityManagerNative.isSystemReady()) {
19769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Intent intent = new Intent(Intent.ACTION_INPUT_METHOD_CHANGED);
19771c633fc89bae9bf0af6fe643ac7ad2e744f27bedDianne Hackborn                intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
19789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                intent.putExtra("input_method_id", id);
1979cd75706117432e33d11639e675bcff50479a6bb9Amith Yamasani                mContext.sendBroadcastAsUser(intent, UserHandle.CURRENT);
19809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
1981b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            unbindCurrentClientLocked();
19829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
19839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
19849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
19859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1986ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
198742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
19884df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean showSoftInput(IInputMethodClient client, int flags,
19894df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
19904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
19914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
19924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
1993cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
19949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
19959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
19969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
19979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
19989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
19999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
20009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
20019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
20029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
20039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
2004cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
20054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
20069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
20084df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
20099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
20109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2011ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2012e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
20134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return showCurrentInputLocked(flags, resultReceiver);
20149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
20159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
20169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
20179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2019ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20204df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean showCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
20219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = true;
20229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_IMPLICIT) == 0) {
20239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
20249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
20259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.SHOW_FORCED) != 0) {
20269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowExplicitlyRequested = true;
20279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mShowForced = true;
20289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2029ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2030cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        if (!mSystemReady) {
2031cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn            return false;
2032cc27870098a5b6105d6007a18bebaec8940db2d5Dianne Hackborn        }
2033ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20344df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res = false;
20359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCurMethod != null) {
2036e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.d(TAG, "showCurrentInputLocked: mCurToken=" + mCurToken);
20374df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageIOO(
20384df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_SHOW_SOFT_INPUT, getImeShowFlags(), mCurMethod,
20394df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    resultReceiver));
20409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInputShown = true;
20412c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            if (mHaveConnection && !mVisibleBound) {
20424e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                bindCurrentInputMethodService(
2043f0f94d129b6eb3c48624e915898d86d4f2de59ffDianne Hackborn                        mCurIntent, mVisibleConnection, Context.BIND_AUTO_CREATE
2044d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                                | Context.BIND_TREAT_LIKE_ACTIVITY
2045d69e4c1460017062e7c36be55801cb434ad19d97Dianne Hackborn                                | Context.BIND_FOREGROUND_SERVICE);
20462c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                mVisibleBound = true;
20472c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            }
20484df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
20499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } else if (mHaveConnection && SystemClock.uptimeMillis()
205059b424c3b6121c9579fc5efcc785ba084072a5casatok                >= (mLastBindTime+TIME_TO_RECONNECT)) {
20519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // The client has asked to have the input method shown, but
20529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // we have been sitting here too long with a connection to the
20539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // service and no interface received, so let's disconnect/connect
20549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // to try to prod things along.
2055ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker            EventLog.writeEvent(EventLogTags.IMF_FORCE_RECONNECT_IME, mCurMethodId,
20569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SystemClock.uptimeMillis()-mLastBindTime,1);
205759b424c3b6121c9579fc5efcc785ba084072a5casatok            Slog.w(TAG, "Force disconnect/connect to the IME in showCurrentInputLocked()");
20589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mContext.unbindService(this);
20594e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            bindCurrentInputMethodService(mCurIntent, this, Context.BIND_AUTO_CREATE
20602c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn                    | Context.BIND_NOT_VISIBLE);
20614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        } else {
20624e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (DEBUG) {
20634e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.d(TAG, "Can't show input: connection = " + mHaveConnection + ", time = "
20644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                        + ((mLastBindTime+TIME_TO_RECONNECT) - SystemClock.uptimeMillis()));
20654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
20669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2067ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20684df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
20699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2070ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
207142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
20724df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public boolean hideSoftInput(IInputMethodClient client, int flags,
20734df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            ResultReceiver resultReceiver) {
20744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
20754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
20764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2077cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn        int uid = Binder.getCallingUid();
20789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
20799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
20809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
20819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (mCurClient == null || client == null
20829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        || mCurClient.client.asBinder() != client.asBinder()) {
20839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    try {
20849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // We need to check if this is the current client with
20859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // focus in the window manager, to allow this call to
20869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // be made before input is started in it.
20879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if (!mIWindowManager.inputMethodClientHasFocus(client)) {
2088cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                            if (DEBUG) Slog.w(TAG, "Ignoring hideSoftInput of uid "
2089cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                                    + uid + ": " + client);
20904df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            return false;
20919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
20929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    } catch (RemoteException e) {
20934df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        return false;
20949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
20959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2096ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
20978a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "Client requesting input be hidden");
20984df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return hideCurrentInputLocked(flags, resultReceiver);
20999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
21009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
21019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
21029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2104ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
21054df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    boolean hideCurrentInputLocked(int flags, ResultReceiver resultReceiver) {
21069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if ((flags&InputMethodManager.HIDE_IMPLICIT_ONLY) != 0
21079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                && (mShowExplicitlyRequested || mShowForced)) {
2108e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: explicit show not cancelled by non-explicit hide");
21094df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
21109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mShowForced && (flags&InputMethodManager.HIDE_NOT_ALWAYS) != 0) {
2112e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner            if (DEBUG) Slog.v(TAG, "Not hiding: forced show not cancelled by not-always hide");
21134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            return false;
21149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2115ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka
2116ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // There is a chance that IMM#hideSoftInput() is called in a transient state where
2117ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // IMMS#InputShown is already updated to be true whereas IMMS#mImeWindowVis is still waiting
2118ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // to be updated with the new value sent from IME process.  Even in such a transient state
2119ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // historically we have accepted an incoming call of IMM#hideSoftInput() from the
2120ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // application process as a valid request, and have even promised such a behavior with CTS
2121ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // since Android Eclair.  That's why we need to accept IMM#hideSoftInput() even when only
2122ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // IMMS#InputShown indicates that the software keyboard is shown.
2123ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        // TODO: Clean up, IMMS#mInputShown, IMMS#mImeWindowVis and mShowRequested.
2124ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        final boolean shouldHideSoftInput = (mCurMethod != null) && (mInputShown ||
2125ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka                (mImeWindowVis & InputMethodService.IME_ACTIVE) != 0);
21264df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        boolean res;
2127ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka        if (shouldHideSoftInput) {
2128ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // The IME will report its visible state again after the following message finally
2129ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // delivered to the IME process as an IPC.  Hence the inconsistency between
2130ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // IMMS#mInputShown and IMMS#mImeWindowVis should be resolved spontaneously in
2131ec928651cc3e72c2e8ff6102a6c037c5119617eeSeigo Nonaka            // the final state.
21324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            executeOrSendMessage(mCurMethod, mCaller.obtainMessageOO(
21334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                    MSG_HIDE_SOFT_INPUT, mCurMethod, resultReceiver));
21344df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = true;
21354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        } else {
21364df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            res = false;
21379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
21382c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        if (mHaveConnection && mVisibleBound) {
21392c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mContext.unbindService(mVisibleConnection);
21402c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn            mVisibleBound = false;
21412c84cfc001fb92a71811bf7384b7f865ff31ff9dDianne Hackborn        }
21429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mInputShown = false;
21439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowRequested = false;
21449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowExplicitlyRequested = false;
21459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mShowForced = false;
21464df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        return res;
21479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2148ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
214942c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
21507663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn    public InputBindResult windowGainedFocus(IInputMethodClient client, IBinder windowToken,
21517663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            int controlFlags, int softInputMode, int windowFlags,
21527663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn            EditorInfo attribute, IInputContext inputContext) {
21538d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        // Needs to check the validity before clearing calling identity
21548d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka        final boolean calledFromValidUser = calledFromValidUser();
21558d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
21567663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        InputBindResult res = null;
21579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long ident = Binder.clearCallingIdentity();
21589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
21599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            synchronized (mMethodMap) {
21608a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                if (DEBUG) Slog.v(TAG, "windowGainedFocus: " + client.asBinder()
21617663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " controlFlags=#" + Integer.toHexString(controlFlags)
21629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + " softInputMode=#" + Integer.toHexString(softInputMode)
21637663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        + " windowFlags=#" + Integer.toHexString(windowFlags));
2164ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
21657663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                ClientState cs = mClients.get(client.asBinder());
21667663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (cs == null) {
21677663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    throw new IllegalArgumentException("unknown client "
21687663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            + client.asBinder());
21697663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
21707663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
21717663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                try {
21727663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (!mIWindowManager.inputMethodClientHasFocus(cs.client)) {
21737663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // Check with the window manager to make sure this client actually
21747663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // has a window with focus.  If not, reject.  This is thread safe
21757663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // because if the focus changes some time before or after, the
21767663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // next client receiving focus that has any interest in input will
21777663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        // be calling through here after that change happens.
21787663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        Slog.w(TAG, "Focus gain on non-focused client " + cs.client
21797663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                + " (uid=" + cs.uid + " pid=" + cs.pid + ")");
21807663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return null;
21819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    }
21827663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                } catch (RemoteException e) {
21839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2184ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
21858d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                if (!calledFromValidUser) {
21868d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "A background user is requesting window. Hiding IME.");
21878d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    Slog.w(TAG, "If you want to interect with IME, you need "
21888d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                            + "android.permission.INTERACT_ACROSS_USERS_FULL");
21898d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    hideCurrentInputLocked(0, null);
21908d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                    return null;
21918d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka                }
21928d03305b576e429909e420c235163c2be1aae732Satoshi Kataoka
2193b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                if (mCurFocusedWindow == windowToken) {
2194ac92087a9a1c464d4b0a58c82dae01cbaa088e89Dianne Hackborn                    Slog.w(TAG, "Window already focused, ignoring focus gain of: " + client
21953573950e0b30178dc963de3fa00aba2ebcfd552dSatoshi Kataoka                            + " attribute=" + attribute + ", token = " + windowToken);
21967663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    if (attribute != null) {
21977663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        return startInputUncheckedLocked(cs, inputContext, attribute,
21987663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                controlFlags);
21997663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    }
22007663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    return null;
2201b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                }
2202b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project                mCurFocusedWindow = windowToken;
2203ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
22047d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // Should we auto-show the IME even if the caller has not
22057d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // specified what should be done with it?
22067d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // We only do this automatically if the window can resize
22077d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // to accommodate the IME (so what the user sees will give
22087d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // them good context without input information being obscured
22097d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // by the IME) or if running on a large screen where there
22107d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                // is more room for the target window + IME.
22117d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                final boolean doAutoShow =
22127d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        (softInputMode & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
22137d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE
22147d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        || mRes.getConfiguration().isLayoutSizeAtLeast(
22157d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                Configuration.SCREENLAYOUT_SIZE_LARGE);
22167663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                final boolean isTextEditor =
22177663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        (controlFlags&InputMethodManager.CONTROL_WINDOW_IS_TEXT_EDITOR) != 0;
22187663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
22197663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // We want to start input before showing the IME, but after closing
22207663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // it.  We want to do this after closing it to help the IME disappear
22217663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // more quickly (not get stuck behind it initializing itself for the
22227663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                // new focused input, even if its window wants to hide the IME).
22237663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                boolean didStart = false;
2224a0f3ad1b5aabe04d9eb1df8bad34124b826ab641Yohei Yukaw
22259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                switch (softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_STATE) {
22269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNSPECIFIED:
22277d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        if (!isTextEditor || !doAutoShow) {
22289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            if (WindowManager.LayoutParams.mayUseInputMethod(windowFlags)) {
22299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // There is no focus view, and this window will
22309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // be behind any soft input window, so hide the
22319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                // soft input window if it is shown.
22328a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                                if (DEBUG) Slog.v(TAG, "Unspecified window will hide input");
22334df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                                hideCurrentInputLocked(InputMethodManager.HIDE_NOT_ALWAYS, null);
22349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            }
22357d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                        } else if (isTextEditor && doAutoShow && (softInputMode &
22367d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
22379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // There is a focus view, and we are navigating forward
22389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            // into the window, so show the input window for the user.
22397663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // We only do this automatically if the window can resize
22407663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            // to accommodate the IME (so what the user sees will give
22417d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // them good context without input information being obscured
22427d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // by the IME) or if running on a large screen where there
22437d3a5bcf300aea7bffb1d46f28e244ca807f5e82Dianne Hackborn                            // is more room for the target window + IME.
22448a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Unspecified window will show input");
22457663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
22467663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
22477663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
22487663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
22497663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
22504df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
22519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
22529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_UNCHANGED:
22549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        // Do nothing.
22559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN:
22579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
22589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
22598a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to hide input going forward");
22604df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            hideCurrentInputLocked(0, null);
22619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
22629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN:
22648a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to hide input");
22654df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        hideCurrentInputLocked(0, null);
22669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE:
22689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        if ((softInputMode &
22699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                                WindowManager.LayoutParams.SOFT_INPUT_IS_FORWARD_NAVIGATION) != 0) {
22708a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                            if (DEBUG) Slog.v(TAG, "Window asks to show input going forward");
22717663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            if (attribute != null) {
22727663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                res = startInputUncheckedLocked(cs, inputContext, attribute,
22737663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                        controlFlags);
22747663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                didStart = true;
22757663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            }
22764df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                            showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
22779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
22789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    case WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE:
22808a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                        if (DEBUG) Slog.v(TAG, "Window asks to always show input");
22817663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        if (attribute != null) {
22827663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            res = startInputUncheckedLocked(cs, inputContext, attribute,
22837663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                                    controlFlags);
22847663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            didStart = true;
22857663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                        }
22864df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                        showCurrentInputLocked(InputMethodManager.SHOW_IMPLICIT, null);
22879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        break;
22889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
22897663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
22907663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                if (!didStart && attribute != null) {
22917663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                    res = startInputUncheckedLocked(cs, inputContext, attribute,
22927663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                            controlFlags);
22937663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn                }
22949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
22959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
22969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Binder.restoreCallingIdentity(ident);
22979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
22987663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn
22997663d80f6b6fd6ca7a736c3802013a09c0abdeb9Dianne Hackborn        return res;
23009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2301ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
230242c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
230314e139179be7daab6ed452105387a3922752c219Seigo Nonaka    public void showInputMethodPickerFromClient(
230414e139179be7daab6ed452105387a3922752c219Seigo Nonaka            IInputMethodClient client, int auxiliarySubtypeMode) {
23054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
23099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCurClient == null || client == null
23109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    || mCurClient.client.asBinder() != client.asBinder()) {
231147a44916e2fb33cf4751906386d5f5c903b28d8bsatok                Slog.w(TAG, "Ignoring showInputMethodPickerFromClient of uid "
2312cef65eeb0315c3118bf8860d6f723cb49ff6bc52Dianne Hackborn                        + Binder.getCallingUid() + ": " + client);
23139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
23149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2315440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // Always call subtype picker, because subtype picker is a superset of input method
2316440aab54cab106030f1edafea4dec1f9d8624f9bsatok            // picker.
231714e139179be7daab6ed452105387a3922752c219Seigo Nonaka            mHandler.sendMessage(mCaller.obtainMessageI(
231814e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    MSG_SHOW_IM_SUBTYPE_PICKER, auxiliarySubtypeMode));
2319ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok        }
2320ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2321ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
232242c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void setInputMethod(IBinder token, String id) {
23244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23254e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23272820351489537698ad153c6397edf3270455edc5satok        setInputMethodWithSubtypeId(token, id, NOT_A_SUBTYPE_ID);
23282820351489537698ad153c6397edf3270455edc5satok    }
23292820351489537698ad153c6397edf3270455edc5satok
233042c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
23312820351489537698ad153c6397edf3270455edc5satok    public void setInputMethodAndSubtype(IBinder token, String id, InputMethodSubtype subtype) {
23324e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23334e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
23352820351489537698ad153c6397edf3270455edc5satok        synchronized (mMethodMap) {
23362820351489537698ad153c6397edf3270455edc5satok            if (subtype != null) {
23374e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, id,
23384e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        InputMethodUtils.getSubtypeIdFromHashCode(mMethodMap.get(id),
23394e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                                subtype.hashCode()));
23402820351489537698ad153c6397edf3270455edc5satok            } else {
23412820351489537698ad153c6397edf3270455edc5satok                setInputMethod(token, id);
23422820351489537698ad153c6397edf3270455edc5satok            }
23432820351489537698ad153c6397edf3270455edc5satok        }
2344ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
2345ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
234642c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
2347b416a71e56cdd50742eb897366a140775aa4cd61satok    public void showInputMethodAndSubtypeEnablerFromClient(
2348217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            IInputMethodClient client, String inputMethodId) {
23494e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23504e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
23514e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2352b416a71e56cdd50742eb897366a140775aa4cd61satok        synchronized (mMethodMap) {
2353b416a71e56cdd50742eb897366a140775aa4cd61satok            if (mCurClient == null || client == null
2354b416a71e56cdd50742eb897366a140775aa4cd61satok                || mCurClient.client.asBinder() != client.asBinder()) {
2355b416a71e56cdd50742eb897366a140775aa4cd61satok                Slog.w(TAG, "Ignoring showInputMethodAndSubtypeEnablerFromClient of: " + client);
2356b416a71e56cdd50742eb897366a140775aa4cd61satok            }
23577fee71f66afef6421b92fa48e63d4bc73f5d0c27satok            executeOrSendMessage(mCurMethod, mCaller.obtainMessageO(
23587fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                    MSG_SHOW_IM_SUBTYPE_ENABLER, inputMethodId));
2359b416a71e56cdd50742eb897366a140775aa4cd61satok        }
2360b416a71e56cdd50742eb897366a140775aa4cd61satok    }
2361b416a71e56cdd50742eb897366a140775aa4cd61satok
23624fc87d61c29886c848789208c9e32ba9ac4e5dd3satok    @Override
2363735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    public boolean switchToLastInputMethod(IBinder token) {
23644e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
23654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
23664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2367735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        synchronized (mMethodMap) {
2368c445bcd0bce630948ee029d7c70b28226f0b6c9csatok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
23694fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            final InputMethodInfo lastImi;
2370208d5634047111811de16fb63c43d0bc8b4fe6desatok            if (lastIme != null) {
23714fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = mMethodMap.get(lastIme.first);
23724fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
23734fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                lastImi = null;
23744fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
23754fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            String targetLastImiId = null;
23764fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            int subtypeId = NOT_A_SUBTYPE_ID;
23774fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (lastIme != null && lastImi != null) {
23784fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final boolean imiIdIsSame = lastImi.getId().equals(mCurMethodId);
23794fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
23804fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final int currentSubtypeHash = mCurrentSubtype == null ? NOT_A_SUBTYPE_ID
23814fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        : mCurrentSubtype.hashCode();
23824fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // If the last IME is the same as the current IME and the last subtype is not
23834fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // defined, there is no need to switch to the last IME.
23844fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (!imiIdIsSame || lastSubtypeHash != currentSubtypeHash) {
23854fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    targetLastImiId = lastIme.first;
23868e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
23874fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
23884fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
23894fc87d61c29886c848789208c9e32ba9ac4e5dd3satok
23908e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            if (TextUtils.isEmpty(targetLastImiId)
23918e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    && !InputMethodUtils.canAddToLastInputMethod(mCurrentSubtype)) {
23924fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // This is a safety net. If the currentSubtype can't be added to the history
23934fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // and the framework couldn't find the last ime, we will make the last ime be
23944fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                // the most applicable enabled keyboard subtype of the system imes.
23954fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                final List<InputMethodInfo> enabled = mSettings.getEnabledInputMethodListLocked();
23964fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                if (enabled != null) {
23974fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final int N = enabled.size();
23984fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    final String locale = mCurrentSubtype == null
23994fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            ? mRes.getConfiguration().locale.toString()
24004fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            : mCurrentSubtype.getLocale();
24014fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    for (int i = 0; i < N; ++i) {
24024fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        final InputMethodInfo imi = enabled.get(i);
24038e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        if (imi.getSubtypeCount() > 0 && InputMethodUtils.isSystemIme(imi)) {
24044fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            InputMethodSubtype keyboardSubtype =
24058e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                    InputMethodUtils.findLastResortApplicableSubtypeLocked(mRes,
24068e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.getSubtypes(imi),
24078e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, locale, true);
24084fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            if (keyboardSubtype != null) {
24094fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                targetLastImiId = imi.getId();
24108e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                                subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
24114fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                        imi, keyboardSubtype.hashCode());
24124fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                if(keyboardSubtype.getLocale().equals(locale)) {
24134fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                    break;
24144fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                                }
24154fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            }
24164fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                        }
24174fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    }
24184fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                }
24194fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            }
2420c445bcd0bce630948ee029d7c70b28226f0b6c9csatok
24214fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            if (!TextUtils.isEmpty(targetLastImiId)) {
2422c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                if (DEBUG) {
24234fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                    Slog.d(TAG, "Switch to: " + lastImi.getId() + ", " + lastIme.second
24244fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                            + ", from: " + mCurMethodId + ", " + subtypeId);
2425735cf38b8c7f8f91ad087511e44fe79018fa61d6satok                }
24264e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                setInputMethodWithSubtypeIdLocked(token, targetLastImiId, subtypeId);
2427c445bcd0bce630948ee029d7c70b28226f0b6c9csatok                return true;
24284fc87d61c29886c848789208c9e32ba9ac4e5dd3satok            } else {
24294fc87d61c29886c848789208c9e32ba9ac4e5dd3satok                return false;
2430735cf38b8c7f8f91ad087511e44fe79018fa61d6satok            }
2431735cf38b8c7f8f91ad087511e44fe79018fa61d6satok        }
2432735cf38b8c7f8f91ad087511e44fe79018fa61d6satok    }
2433735cf38b8c7f8f91ad087511e44fe79018fa61d6satok
2434e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2435688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    public boolean switchToNextInputMethod(IBinder token, boolean onlyCurrentIme) {
24364e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
24374e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
24384e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
2439688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        synchronized (mMethodMap) {
2440a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2441a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2442a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring switchToNextInputMethod due to an invalid token. uid:" + uid
2443a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + " token:" + token);
2444a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2445a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
24465a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
2447688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                    onlyCurrentIme, mMethodMap.get(mCurMethodId), mCurrentSubtype);
2448688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            if (nextSubtype == null) {
2449688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok                return false;
2450688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            }
24514e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, nextSubtype.mImi.getId(),
24524e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    nextSubtype.mSubtypeId);
2453688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            return true;
2454688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok        }
2455688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    }
2456688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok
2457688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok    @Override
24582b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    public boolean shouldOfferSwitchingToNextInputMethod(IBinder token) {
24592b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        if (!calledFromValidUser()) {
24602b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return false;
24612b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
24622b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        synchronized (mMethodMap) {
2463a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            if (!calledWithValidToken(token)) {
2464a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                final int uid = Binder.getCallingUid();
2465a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                Slog.e(TAG, "Ignoring shouldOfferSwitchingToNextInputMethod due to an invalid "
2466a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                        + "token. uid:" + uid + " token:" + token);
2467a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa                return false;
2468a07557471e43226fd23f6447c1e61177726524c9Yohei Yukawa            }
24695a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final ImeSubtypeListItem nextSubtype = mSwitchingController.getNextInputMethodLocked(
24702b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                    false /* onlyCurrentIme */, mMethodMap.get(mCurMethodId), mCurrentSubtype);
24712b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            if (nextSubtype == null) {
24722b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka                return false;
24732b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            }
24742b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka            return true;
24752b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka        }
24762b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    }
24772b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka
24782b10b52f6c08eb79f48f7388e2f1c69f58a9c96dSatoshi Kataoka    @Override
247968f1b78b7b9139a0e34285ff641a664e664a14b8satok    public InputMethodSubtype getLastInputMethodSubtype() {
24804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
24814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
24824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
248368f1b78b7b9139a0e34285ff641a664e664a14b8satok        synchronized (mMethodMap) {
248468f1b78b7b9139a0e34285ff641a664e664a14b8satok            final Pair<String, String> lastIme = mSettings.getLastInputMethodAndSubtypeLocked();
248568f1b78b7b9139a0e34285ff641a664e664a14b8satok            // TODO: Handle the case of the last IME with no subtypes
248668f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastIme == null || TextUtils.isEmpty(lastIme.first)
248768f1b78b7b9139a0e34285ff641a664e664a14b8satok                    || TextUtils.isEmpty(lastIme.second)) return null;
248868f1b78b7b9139a0e34285ff641a664e664a14b8satok            final InputMethodInfo lastImi = mMethodMap.get(lastIme.first);
248968f1b78b7b9139a0e34285ff641a664e664a14b8satok            if (lastImi == null) return null;
249068f1b78b7b9139a0e34285ff641a664e664a14b8satok            try {
249168f1b78b7b9139a0e34285ff641a664e664a14b8satok                final int lastSubtypeHash = Integer.valueOf(lastIme.second);
24928e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                final int lastSubtypeId =
24938e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        InputMethodUtils.getSubtypeIdFromHashCode(lastImi, lastSubtypeHash);
24940e7d7d632309409e2bc51d5317cf7a92a7541433satok                if (lastSubtypeId < 0 || lastSubtypeId >= lastImi.getSubtypeCount()) {
24950e7d7d632309409e2bc51d5317cf7a92a7541433satok                    return null;
24960e7d7d632309409e2bc51d5317cf7a92a7541433satok                }
24970e7d7d632309409e2bc51d5317cf7a92a7541433satok                return lastImi.getSubtypeAt(lastSubtypeId);
249868f1b78b7b9139a0e34285ff641a664e664a14b8satok            } catch (NumberFormatException e) {
249968f1b78b7b9139a0e34285ff641a664e664a14b8satok                return null;
250068f1b78b7b9139a0e34285ff641a664e664a14b8satok            }
250168f1b78b7b9139a0e34285ff641a664e664a14b8satok        }
250268f1b78b7b9139a0e34285ff641a664e664a14b8satok    }
250368f1b78b7b9139a0e34285ff641a664e664a14b8satok
2504e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
2505ee5e77cafec2eae70890abdcc1646ed39b06edddsatok    public void setAdditionalInputMethodSubtypes(String imiId, InputMethodSubtype[] subtypes) {
25064e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
25074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
25084e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
250991e88122cf28a48fd2e2260da7d3d87dd437227asatok        // By this IPC call, only a process which shares the same uid with the IME can add
251091e88122cf28a48fd2e2260da7d3d87dd437227asatok        // additional input method subtypes to the IME.
2511ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        if (TextUtils.isEmpty(imiId) || subtypes == null || subtypes.length == 0) return;
2512e7c6998e0a953ae55487d4fe122739646f9280aasatok        synchronized (mMethodMap) {
251391e88122cf28a48fd2e2260da7d3d87dd437227asatok            final InputMethodInfo imi = mMethodMap.get(imiId);
2514ee5e77cafec2eae70890abdcc1646ed39b06edddsatok            if (imi == null) return;
25154e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            final String[] packageInfos;
25164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            try {
25174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                packageInfos = mIPackageManager.getPackagesForUid(Binder.getCallingUid());
25184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } catch (RemoteException e) {
25194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                Slog.e(TAG, "Failed to get package infos");
25204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                return;
25214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            }
252291e88122cf28a48fd2e2260da7d3d87dd437227asatok            if (packageInfos != null) {
252391e88122cf28a48fd2e2260da7d3d87dd437227asatok                final int packageNum = packageInfos.length;
252491e88122cf28a48fd2e2260da7d3d87dd437227asatok                for (int i = 0; i < packageNum; ++i) {
252591e88122cf28a48fd2e2260da7d3d87dd437227asatok                    if (packageInfos[i].equals(imi.getPackageName())) {
252691e88122cf28a48fd2e2260da7d3d87dd437227asatok                        mFileManager.addInputMethodSubtypes(imi, subtypes);
2527c593380d1bccbfbd45c404954b2670b65acc287fsatok                        final long ident = Binder.clearCallingIdentity();
2528c593380d1bccbfbd45c404954b2670b65acc287fsatok                        try {
2529f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                            buildInputMethodListLocked(mMethodList, mMethodMap,
2530f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                                    false /* resetDefaultEnabledIme */);
2531c593380d1bccbfbd45c404954b2670b65acc287fsatok                        } finally {
2532c593380d1bccbfbd45c404954b2670b65acc287fsatok                            Binder.restoreCallingIdentity(ident);
2533c593380d1bccbfbd45c404954b2670b65acc287fsatok                        }
2534ee5e77cafec2eae70890abdcc1646ed39b06edddsatok                        return;
253591e88122cf28a48fd2e2260da7d3d87dd437227asatok                    }
253691e88122cf28a48fd2e2260da7d3d87dd437227asatok                }
253791e88122cf28a48fd2e2260da7d3d87dd437227asatok            }
2538e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
2539ee5e77cafec2eae70890abdcc1646ed39b06edddsatok        return;
2540e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
2541e7c6998e0a953ae55487d4fe122739646f9280aasatok
2542658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    @Override
2543658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    public int getInputMethodWindowVisibleHeight() {
2544658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka        return mWindowManagerService.getInputMethodWindowVisibleHeight();
2545658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka    }
2546658c7b896a751b971db1292d86655dbb97f00067Satoshi Kataoka
2547d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    @Override
25483d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa    public void notifyUserAction(int sequenceNumber) {
2549d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        if (DEBUG) {
25503d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            Slog.d(TAG, "Got the notification of a user action. sequenceNumber:" + sequenceNumber);
2551d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
25525a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa        synchronized (mMethodMap) {
25533d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            if (mCurUserActionNotificationSequenceNumber != sequenceNumber) {
25543d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                if (DEBUG) {
25553d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    Slog.d(TAG, "Ignoring the user action notification due to the sequence number "
25563d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + "mismatch. expected:" + mCurUserActionNotificationSequenceNumber
25573d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + " actual: " + sequenceNumber);
25583d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                }
25593d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                return;
25603d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            }
25615a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
25625a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            if (imi != null) {
25630297051162193ef2b7d906409868e404f77e4c31Yohei Yukawa                mSwitchingController.onUserActionLocked(imi, mCurrentSubtype);
25645a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa            }
2565d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka        }
2566d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka    }
2567d7443c83ceae0bdd20d68bf84648cf3b40115d85Satoshi Kataoka
25682820351489537698ad153c6397edf3270455edc5satok    private void setInputMethodWithSubtypeId(IBinder token, String id, int subtypeId) {
25699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
25704e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodWithSubtypeIdLocked(token, id, subtypeId);
25714e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
25724e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    }
25739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
25744e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa    private void setInputMethodWithSubtypeIdLocked(IBinder token, String id, int subtypeId) {
25754e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        if (token == null) {
25764e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            if (mContext.checkCallingOrSelfPermission(
25774e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
25784e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    != PackageManager.PERMISSION_GRANTED) {
25794e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                throw new SecurityException(
25804e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        "Using null token requires permission "
25814e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
25829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
25834e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } else if (mCurToken != token) {
25844e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Slog.w(TAG, "Ignoring setInputMethod of uid " + Binder.getCallingUid()
25854e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa                    + " token: " + token);
25864e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            return;
25874e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        }
25884e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa
25894e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        final long ident = Binder.clearCallingIdentity();
25904e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        try {
25914e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            setInputMethodLocked(id, subtypeId);
25924e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa        } finally {
25934e02bc6f8fa64d8a8398371836e2e9abf3be3070Yohei Yukawa            Binder.restoreCallingIdentity(ident);
25949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
25959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
25969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
259742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
25989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void hideMySoftInput(IBinder token, int flags) {
25994e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
26004e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
26014e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
26029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
260322c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
260422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
260522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring hideInputMethod due to an invalid token. uid:"
260622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
26079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return;
26089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
26109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
26114df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                hideCurrentInputLocked(flags, null);
26124df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            } finally {
26134df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                Binder.restoreCallingIdentity(ident);
26144df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
26154df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        }
26164df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    }
2617ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
261842c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
26194df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project    public void showMySoftInput(IBinder token, int flags) {
26204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
26214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return;
26224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
26234df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project        synchronized (mMethodMap) {
262422c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa            if (!calledWithValidToken(token)) {
262522c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                final int uid = Binder.getCallingUid();
262622c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                Slog.e(TAG, "Ignoring showMySoftInput due to an invalid token. uid:"
262722c97be73b2686a4a06cf31d0b211f47e7b92595Yohei Yukawa                        + uid + " token:" + token);
26284df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                return;
26294df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            }
26304df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            long ident = Binder.clearCallingIdentity();
26314df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project            try {
26324df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project                showCurrentInputLocked(flags, null);
26339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
26349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Binder.restoreCallingIdentity(ident);
26359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
26389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
26399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setEnabledSessionInMainThread(SessionState session) {
26409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mEnabledSession != session) {
26419d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
26429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26438a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    if (DEBUG) Slog.v(TAG, "Disabling: " + mEnabledSession);
26449d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, false);
26459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
26469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
26479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mEnabledSession = session;
26499d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa            if (mEnabledSession != null && mEnabledSession.session != null) {
26509d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                try {
26519d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    if (DEBUG) Slog.v(TAG, "Enabling: " + mEnabledSession);
26529d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                    mEnabledSession.method.setSessionEnabled(mEnabledSession.session, true);
26539d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                } catch (RemoteException e) {
26549d91b43c8d0fa233905ecf132c6e6ee664904694Yohei Yukawa                }
26559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
26569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
26579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2658ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
265942c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
26609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean handleMessage(Message msg) {
2661758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov        SomeArgs args;
26629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        switch (msg.what) {
2663ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            case MSG_SHOW_IM_SUBTYPE_PICKER:
266414e139179be7daab6ed452105387a3922752c219Seigo Nonaka                final boolean showAuxSubtypes;
266514e139179be7daab6ed452105387a3922752c219Seigo Nonaka                switch (msg.arg1) {
266614e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    case InputMethodManager.SHOW_IM_PICKER_MODE_AUTO:
266714e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        // This is undocumented so far, but IMM#showInputMethodPicker() has been
266814e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        // implemented so that auxiliary subtypes will be excluded when the soft
266914e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        // keyboard is invisible.
267014e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        showAuxSubtypes = mInputShown;
267114e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        break;
267214e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    case InputMethodManager.SHOW_IM_PICKER_MODE_INCLUDE_AUXILIARY_SUBTYPES:
267314e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        showAuxSubtypes = true;
267414e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        break;
267514e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    case InputMethodManager.SHOW_IM_PICKER_MODE_EXCLUDE_AUXILIARY_SUBTYPES:
267614e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        showAuxSubtypes = false;
267714e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        break;
267814e139179be7daab6ed452105387a3922752c219Seigo Nonaka                    default:
267914e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        Slog.e(TAG, "Unknown subtype picker mode = " + msg.arg1);
268014e139179be7daab6ed452105387a3922752c219Seigo Nonaka                        return false;
268114e139179be7daab6ed452105387a3922752c219Seigo Nonaka                }
268214e139179be7daab6ed452105387a3922752c219Seigo Nonaka                showInputMethodMenu(showAuxSubtypes);
2683ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                return true;
2684ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
268547a44916e2fb33cf4751906386d5f5c903b28d8bsatok            case MSG_SHOW_IM_SUBTYPE_ENABLER:
2686758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
26877fee71f66afef6421b92fa48e63d4bc73f5d0c27satok                showInputMethodAndSubtypeEnabler((String)args.arg1);
2688758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
2689217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                return true;
2690217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2691217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok            case MSG_SHOW_IM_CONFIG:
2692217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                showConfigureInputMethods();
269347a44916e2fb33cf4751906386d5f5c903b28d8bsatok                return true;
269447a44916e2fb33cf4751906386d5f5c903b28d8bsatok
26959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2696ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
26979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_INPUT:
26989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
26999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)msg.obj).unbindInput();
27009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the method dying.
27029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
27039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_BIND_INPUT:
2705758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).bindInput((InputBinding)args.arg2);
27089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2710758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_SHOW_SOFT_INPUT:
2713758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2715e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".showSoftInput("
27166efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + msg.arg1 + ", " + args.arg2 + ")");
2717ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).showSoftInput(msg.arg1, (ResultReceiver)args.arg2);
27189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2720758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_HIDE_SOFT_INPUT:
2723758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2725e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Calling " + args.arg1 + ".hideSoftInput(0, "
27266efb4c746f89458ffb3da21d7d70af0b220a4876Craig Mautner                            + args.arg2 + ")");
2727ca0ac718cbc2ad3e7ad2400f5fa34068f154ee20Craig Mautner                    ((IInputMethod)args.arg1).hideSoftInput(0, (ResultReceiver)args.arg2);
27289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2730758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_ATTACH_TOKEN:
2733758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2735e4bbb1cc451c7ebdad9f92968732fc4f6c21a70cCraig Mautner                    if (DEBUG) Slog.v(TAG, "Sending attach of token: " + args.arg2);
27369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethod)args.arg1).attachToken((IBinder)args.arg2);
27379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2739758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2741c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            case MSG_CREATE_SESSION: {
2742758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27431951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethod method = (IInputMethod)args.arg1;
2744c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                InputChannel channel = (InputChannel)args.arg2;
27459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27461951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    method.createSession(channel, (IInputSessionCallback)args.arg3);
27479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
2748c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                } finally {
27491951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
27501951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
27511951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (channel != null && Binder.isProxy(method)) {
2752c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                        channel.dispose();
2753c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown                    }
27549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2755758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2757c28867a1d67121ce5963de135e3ae2b1dbd9a33dJeff Brown            }
27589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2759ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_START_INPUT:
2761758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
27649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
27659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.startInput((IInputContext)args.arg2,
27669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
27679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2769758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_RESTART_INPUT:
2772758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    SessionState session = (SessionState)args.arg1;
27759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    setEnabledSessionInMainThread(session);
27769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    session.method.restartInput((IInputContext)args.arg2,
27779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                            (EditorInfo)args.arg3);
27789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2780758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
27819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
2782ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // ---------------------------------------------------------
2784ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
27859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            case MSG_UNBIND_METHOD:
27869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ((IInputMethodClient)msg.obj).onUnbindMethod(msg.arg1);
27889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    // There is nothing interesting about the last client dying.
27909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
27919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
27921951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            case MSG_BIND_METHOD: {
2793758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args = (SomeArgs)msg.obj;
27941951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                IInputMethodClient client = (IInputMethodClient)args.arg1;
27951951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                InputBindResult res = (InputBindResult)args.arg2;
27969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
27971951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    client.onBindMethod(res);
27989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } catch (RemoteException e) {
27998a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                    Slog.w(TAG, "Client died receiving input method " + args.arg2);
28001951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                } finally {
28011951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // Dispose the channel if the input method is not local to this process
28021951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    // because the remote proxy will get its own copy when unparceled.
28031951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    if (res.channel != null && Binder.isProxy(client)) {
28041951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                        res.channel.dispose();
28051951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown                    }
28069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2807758143ecfedbe08cc6c4fed0ad8ad7a854194ca4Svetoslav Ganov                args.recycle();
28089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return true;
28091951ce86c21445ac191e4d2d95233f4f5c096b56Jeff Brown            }
2810a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn            case MSG_SET_ACTIVE:
2811a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                try {
2812a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    ((ClientState)msg.obj).client.setActive(msg.arg1 != 0);
2813a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                } catch (RemoteException e) {
2814a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                    Slog.w(TAG, "Got RemoteException sending setActive(false) notification to pid "
2815a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).pid + " uid "
2816a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                            + ((ClientState)msg.obj).uid);
2817a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                }
2818a6e41342e2159402e33866e7145be357065d9c9aDianne Hackborn                return true;
28193d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            case MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER: {
28203d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                final int sequenceNumber = msg.arg1;
2821080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                final ClientState clientState = (ClientState)msg.obj;
28223d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                try {
2823080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                    clientState.client.setUserActionNotificationSequenceNumber(sequenceNumber);
28243d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                } catch (RemoteException e) {
28253d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    Slog.w(TAG, "Got RemoteException sending "
28263d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + "setUserActionNotificationSequenceNumber("
28273d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                            + sequenceNumber + ") notification to pid "
2828080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                            + clientState.pid + " uid "
2829080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                            + clientState.uid);
28303d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                }
28313d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                return true;
28323d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            }
283301038492ff0317f0d3cff54d8a7ee36bb31ff175satok
283401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // --------------------------------------------------------------
283501038492ff0317f0d3cff54d8a7ee36bb31ff175satok            case MSG_HARD_KEYBOARD_SWITCH_CHANGED:
28367b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                mHardKeyboardListener.handleHardKeyboardStatusChange(msg.arg1 == 1);
283701038492ff0317f0d3cff54d8a7ee36bb31ff175satok                return true;
28389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
28399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
28409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
28419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2842dc9ddaee9a710cf6f5d7f37350650f82e706c706satok    private boolean chooseNewDefaultIMELocked() {
28438e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final InputMethodInfo imi = InputMethodUtils.getMostApplicableDefaultIME(
28448e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mSettings.getEnabledInputMethodListLocked());
2845dc9ddaee9a710cf6f5d7f37350650f82e706c706satok        if (imi != null) {
284603eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            if (DEBUG) {
284703eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                Slog.d(TAG, "New default IME was selected: " + imi.getId());
284803eb319a3a7fe6fe9ab9eba6fc1f727285850906satok            }
2849723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            resetSelectedInputMethodAndSubtypeLocked(imi.getId());
28506da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            return true;
28516da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
28526da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
28536da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        return false;
28546da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger    }
28556da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
28569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void buildInputMethodListLocked(ArrayList<InputMethodInfo> list,
2857f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            HashMap<String, InputMethodInfo> map, boolean resetDefaultEnabledIme) {
28584e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (DEBUG) {
2859f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            Slog.d(TAG, "--- re-buildInputMethodList reset = " + resetDefaultEnabledIme
28600766eb045c0e2ecbc4317743b025618654ddea38Satoshi Kataoka                    + " \n ------ \n" + InputMethodUtils.getStackTrace());
28614e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
28629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        list.clear();
28639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        map.clear();
2864ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
28654e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // Use for queryIntentServicesAsUser
28664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final PackageManager pm = mContext.getPackageManager();
28674e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        String disabledSysImes = mSettings.getDisabledSystemInputMethods();
2868e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani        if (disabledSysImes == null) disabledSysImes = "";
28699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28704e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final List<ResolveInfo> services = pm.queryIntentServicesAsUser(
28719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                new Intent(InputMethod.SERVICE_INTERFACE),
2872fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                PackageManager.GET_META_DATA | PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS,
2873fd7adedebf88427162a3ce27fcc9cfd3893c869dDianne Hackborn                mSettings.getCurrentUserId());
2874ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2875e7c6998e0a953ae55487d4fe122739646f9280aasatok        final HashMap<String, List<InputMethodSubtype>> additionalSubtypes =
2876e7c6998e0a953ae55487d4fe122739646f9280aasatok                mFileManager.getAllAdditionalInputMethodSubtypes();
28779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        for (int i = 0; i < services.size(); ++i) {
28789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ResolveInfo ri = services.get(i);
28799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ServiceInfo si = ri.serviceInfo;
28809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ComponentName compName = new ComponentName(si.packageName, si.name);
28819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (!android.Manifest.permission.BIND_INPUT_METHOD.equals(
28829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    si.permission)) {
28838a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Skipping input method " + compName
28849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + ": it does not require the permission "
28859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.BIND_INPUT_METHOD);
28869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                continue;
28879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
28889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28898a9b22056b13477f59df934928c00c58b5871c95Joe Onorato            if (DEBUG) Slog.d(TAG, "Checking " + compName);
28909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
2892e7c6998e0a953ae55487d4fe122739646f9280aasatok                InputMethodInfo p = new InputMethodInfo(mContext, ri, additionalSubtypes);
28939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                list.add(p);
2894e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                final String id = p.getId();
2895e861ec11c458b4f76eb80da518dfee6a400071bfAmith Yamasani                map.put(id, p);
28969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
28979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                if (DEBUG) {
2898f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "Found an input method " + p);
28999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2900ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (XmlPullParserException e) {
29028a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
29039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (IOException e) {
29048a9b22056b13477f59df934928c00c58b5871c95Joe Onorato                Slog.w(TAG, "Unable to load input method " + compName, e);
29059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
29069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
29076da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger
2908f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        if (resetDefaultEnabledIme) {
2909f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            final ArrayList<InputMethodInfo> defaultEnabledIme =
2910f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    InputMethodUtils.getDefaultEnabledImes(mContext, mSystemReady, list);
2911f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            for (int i = 0; i < defaultEnabledIme.size(); ++i) {
2912f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                final InputMethodInfo imi =  defaultEnabledIme.get(i);
2913f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                if (DEBUG) {
2914f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                    Slog.d(TAG, "--- enable ime = " + imi);
2915f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                }
2916f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka                setInputMethodEnabledLocked(imi.getId(), true);
2917f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka            }
2918f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka        }
2919f1367b7e903a2a69a8f833bb272e91d77abd57c6Satoshi Kataoka
29204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String defaultImiId = mSettings.getSelectedInputMethod();
29210a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok        if (!TextUtils.isEmpty(defaultImiId)) {
29220a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            if (!map.containsKey(defaultImiId)) {
29230a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                Slog.w(TAG, "Default IME is uninstalled. Choose new default IME.");
29240a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                if (chooseNewDefaultIMELocked()) {
29257b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    updateInputMethodsFromSettingsLocked(true);
29260a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                }
29270a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok            } else {
29280a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                // Double check that the default IME is certainly enabled.
29290a1bcf4e0d0c26af3f6ad3e57726082c92549bd3satok                setInputMethodEnabledLocked(defaultImiId, true);
29306da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger            }
29316da35a0c1205398b7df4776e359f7794584fb128Brandon Ballinger        }
29323d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // Here is not the perfect place to reset the switching controller. Ideally
29333d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // mSwitchingController and mSettings should be able to share the same state.
29343d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // TODO: Make sure that mSwitchingController and mSettings are sharing the
29353d46bab02978df14354379c4b10d7f68c3b80771Yohei Yukawa        // the same enabled IMEs list.
2936c834a2590cc7ac478ba2ef5a6d8eb7ce471df132Yohei Yukawa        mSwitchingController.resetCircularListLocked(mContext);
29379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2938ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
2940ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
2941217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showInputMethodAndSubtypeEnabler(String inputMethodId) {
2942f49688fa17b70313c0734f00df73bc3308a749e9Tadashi G. Takaoka        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SUBTYPE_SETTINGS);
294347a44916e2fb33cf4751906386d5f5c903b28d8bsatok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
294486417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
294586417ea3f8041481a085823a1aa9f66d747231e8satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
29467fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        if (!TextUtils.isEmpty(inputMethodId)) {
29472548020c364c4119d134c84cc7a00ffca2dcbe7bTadashi G. Takaoka            intent.putExtra(Settings.EXTRA_INPUT_METHOD_ID, inputMethodId);
29487fee71f66afef6421b92fa48e63d4bc73f5d0c27satok        }
29493ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
2950217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    }
2951217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok
2952217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok    private void showConfigureInputMethods() {
2953217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        Intent intent = new Intent(Settings.ACTION_INPUT_METHOD_SETTINGS);
2954217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
2955217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED
2956217f548e79ab1ac3dd9e5be8fb6feaa6dcbe4000satok                | Intent.FLAG_ACTIVITY_CLEAR_TOP);
29573ba439d6481b7f23ade44bfde0700aaa1e076a32Satoshi Kataoka        mContext.startActivityAsUser(intent, null, UserHandle.CURRENT);
295847a44916e2fb33cf4751906386d5f5c903b28d8bsatok    }
295947a44916e2fb33cf4751906386d5f5c903b28d8bsatok
29602c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    private boolean isScreenLocked() {
29612c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        return mKeyguardManager != null
29622c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok                && mKeyguardManager.isKeyguardLocked() && mKeyguardManager.isKeyguardSecure();
29632c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok    }
2964d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka
296514e139179be7daab6ed452105387a3922752c219Seigo Nonaka    private void showInputMethodMenu(boolean showAuxSubtypes) {
296614e139179be7daab6ed452105387a3922752c219Seigo Nonaka        if (DEBUG) Slog.v(TAG, "Show switching menu. showAuxSubtypes=" + showAuxSubtypes);
29679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
29689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Context context = mContext;
29692c93efc9eb188532472edc9e0c3e1ab8121aa20dsatok        final boolean isScreenLocked = isScreenLocked();
2970ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29714e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final String lastInputMethodId = mSettings.getSelectedInputMethod();
29728e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        int lastInputMethodSubtypeId = mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);
29738a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Current IME: " + lastInputMethodId);
2974ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
29757f35c8cc88bea5230f001dd4356f864845d202e5satok        synchronized (mMethodMap) {
2976bb4aa0683c8a0a1e617c6d5f03eda33f49b89ed9satok            final HashMap<InputMethodInfo, List<InputMethodSubtype>> immis =
2977d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                    mSettings.getExplicitlyOrImplicitlyEnabledInputMethodsAndSubtypeListLocked(
2978d787f6953371c4520bd51d6bf8eccc59f1d0f945Satoshi Kataoka                            mContext);
29797f35c8cc88bea5230f001dd4356f864845d202e5satok            if (immis == null || immis.size() == 0) {
29807f35c8cc88bea5230f001dd4356f864845d202e5satok                return;
29817f35c8cc88bea5230f001dd4356f864845d202e5satok            }
2982ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
29838cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            hideInputMethodMenuLocked();
29849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2985688bd47fccf1a1373e6287bc49b5b33fad12b7f3satok            final List<ImeSubtypeListItem> imList =
29865a647b69be8ac8d40c33ed9abe63e41514699e5bYohei Yukawa                    mSwitchingController.getSortedInputMethodAndSubtypeListLocked(
298714e139179be7daab6ed452105387a3922752c219Seigo Nonaka                            true /* showSubtypes */, showAuxSubtypes, isScreenLocked);
2988913a8925c07e854a80bf5df87561f290d3a56d61satok
2989c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            if (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID) {
29904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final InputMethodSubtype currentSubtype = getCurrentInputMethodSubtypeLocked();
2991c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                if (currentSubtype != null) {
2992c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                    final InputMethodInfo currentImi = mMethodMap.get(mCurMethodId);
29938e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastInputMethodSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
29948e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            currentImi, currentSubtype.hashCode());
2995c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok                }
2996c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok            }
2997c36905673a7bcafe9ec74e82e6c4977f2aca6a50satok
2998761eb3762f3602dd1859905ee4ba80f0ef6aec56Ken Wakasa            final int N = imList.size();
2999ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mIms = new InputMethodInfo[N];
3000ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok            mSubtypeIds = new int[N];
30018cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            int checkedItem = 0;
30028cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn            for (int i = 0; i < N; ++i) {
300305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                final ImeSubtypeListItem item = imList.get(i);
300405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mIms[i] = item.mImi;
300505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                mSubtypeIds[i] = item.mSubtypeId;
30068cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                if (mIms[i].getId().equals(lastInputMethodId)) {
3007ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    int subtypeId = mSubtypeIds[i];
3008ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    if ((subtypeId == NOT_A_SUBTYPE_ID)
3009ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (lastInputMethodSubtypeId == NOT_A_SUBTYPE_ID && subtypeId == 0)
3010ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                            || (subtypeId == lastInputMethodSubtypeId)) {
3011ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                        checkedItem = i;
3012ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok                    }
30138cf1bcd1d26ddbb471e4968b70e32ecabe4f7a20Dianne Hackborn                }
30149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3015505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3016505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Context settingsContext = new ContextThemeWrapper(context,
3017505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.style.Theme_DeviceDefault_Settings);
3018505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3019505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mDialogBuilder = new AlertDialog.Builder(settingsContext);
3020d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mDialogBuilder.setOnCancelListener(new OnCancelListener() {
3021d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
3022d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onCancel(DialogInterface dialog) {
3023d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    hideInputMethodMenu();
3024d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
3025d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            });
3026505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3027505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Context dialogContext = mDialogBuilder.getContext();
3028505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final TypedArray a = dialogContext.obtainStyledAttributes(null,
3029505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.styleable.DialogPreference,
3030505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.attr.alertDialogStyle, 0);
3031505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Drawable dialogIcon = a.getDrawable(
3032505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    com.android.internal.R.styleable.DialogPreference_dialogIcon);
3033505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            a.recycle();
3034505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3035505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mDialogBuilder.setIcon(dialogIcon);
3036505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
3037505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final LayoutInflater inflater = (LayoutInflater) dialogContext.getSystemService(
3038505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette                    Context.LAYOUT_INFLATER_SERVICE);
303901038492ff0317f0d3cff54d8a7ee36bb31ff175satok            final View tv = inflater.inflate(
304001038492ff0317f0d3cff54d8a7ee36bb31ff175satok                    com.android.internal.R.layout.input_method_switch_dialog_title, null);
304101038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mDialogBuilder.setCustomTitle(tv);
304201038492ff0317f0d3cff54d8a7ee36bb31ff175satok
304301038492ff0317f0d3cff54d8a7ee36bb31ff175satok            // Setup layout for a toggle switch of the hardware keyboard
304401038492ff0317f0d3cff54d8a7ee36bb31ff175satok            mSwitchingDialogTitleView = tv;
3045d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mSwitchingDialogTitleView
3046d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    .findViewById(com.android.internal.R.id.hard_keyboard_section)
3047d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    .setVisibility(mWindowManagerService.isHardKeyboardAvailable()
3048d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            ? View.VISIBLE : View.GONE);
3049505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final Switch hardKeySwitch = (Switch) mSwitchingDialogTitleView.findViewById(
3050d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    com.android.internal.R.id.hard_keyboard_switch);
30517b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright            hardKeySwitch.setChecked(mShowImeWithHardKeyboard);
3052d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            hardKeySwitch.setOnCheckedChangeListener(new OnCheckedChangeListener() {
3053d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
3054d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
30557b5a96ba8364d5c180780b2f878f5a2b949cfdacMichael Wright                    mSettings.setShowImeWithHardKeyboard(isChecked);
3056d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    // Ensure that the input method dialog is dismissed when changing
3057d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    // the hardware keyboard state.
3058d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    hideInputMethodMenu();
3059d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
3060d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            });
3061d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka
3062505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            final ImeSubtypeListAdapter adapter = new ImeSubtypeListAdapter(dialogContext,
3063d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    com.android.internal.R.layout.input_method_switch_item, imList, checkedItem);
3064d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            final OnClickListener choiceListener = new OnClickListener() {
3065d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                @Override
3066d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                public void onClick(final DialogInterface dialog, final int which) {
3067d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    synchronized (mMethodMap) {
3068d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        if (mIms == null || mIms.length <= which || mSubtypeIds == null
3069d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                                || mSubtypeIds.length <= which) {
3070d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            return;
307101038492ff0317f0d3cff54d8a7ee36bb31ff175satok                        }
3072d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        final InputMethodInfo im = mIms[which];
3073d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        int subtypeId = mSubtypeIds[which];
3074d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        adapter.mCheckedItem = which;
3075d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        adapter.notifyDataSetChanged();
3076d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        hideInputMethodMenu();
3077d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        if (im != null) {
3078d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            if (subtypeId < 0 || subtypeId >= im.getSubtypeCount()) {
3079d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                                subtypeId = NOT_A_SUBTYPE_ID;
308020cb56e26e91df91bd64d4251222e0d421cdbe47Dianne Hackborn                            }
3081d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                            setInputMethodLocked(im.getId(), subtypeId);
30829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        }
3083d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    }
3084d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                }
3085d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            };
3086d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka            mDialogBuilder.setSingleChoiceItems(adapter, checkedItem, choiceListener);
30879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3088d4474cb9454c7a8b907c0be07236ffed4ecf3fd8Seigo Nonaka            if (!isScreenLocked) {
3089d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                final OnClickListener positiveListener = new OnClickListener() {
3090d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    @Override
3091d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    public void onClick(DialogInterface dialog, int whichButton) {
3092d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        showConfigureInputMethods();
3093d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                    }
3094d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                };
309582beadfa067b1e286fa604f8d7960d769411c954satok                mDialogBuilder.setPositiveButton(
3096d130b803b0787131208bea99926dc655b124f006Tadashi G. Takaoka                        com.android.internal.R.string.configure_input_methods, positiveListener);
30977f35c8cc88bea5230f001dd4356f864845d202e5satok            }
30989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog = mDialogBuilder.create();
3099e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.setCanceledOnTouchOutside(true);
31009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.getWindow().setType(
31019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG);
3102c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka            mSwitchingDialog.getWindow().getAttributes().privateFlags |=
3103c86884cd839123e3be3cc97c8f293ac47d3624a9Satoshi Kataoka                    WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
3104e3a7f628c6d9fef42be24999b3137ebe5c6f3525Dianne Hackborn            mSwitchingDialog.getWindow().getAttributes().setTitle("Select input method");
3105d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka            updateSystemUi(mCurToken, mImeWindowVis, mBackDisposition);
31069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mSwitchingDialog.show();
31079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
31089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3109ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
311005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    private static class ImeSubtypeListAdapter extends ArrayAdapter<ImeSubtypeListItem> {
311105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final LayoutInflater mInflater;
311205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final int mTextViewResourceId;
311305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        private final List<ImeSubtypeListItem> mItemsList;
3114d214296f7fa1b1f7824a4847d63b1b06691a6b48Satoshi Kataoka        public int mCheckedItem;
311505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public ImeSubtypeListAdapter(Context context, int textViewResourceId,
311605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                List<ImeSubtypeListItem> itemsList, int checkedItem) {
311705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            super(context, textViewResourceId, itemsList);
3118505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette
311905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mTextViewResourceId = textViewResourceId;
312005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mItemsList = itemsList;
312105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            mCheckedItem = checkedItem;
3122505e3abb8dd0d8f594280b9510adef74623630d7Alan Viverette            mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
312305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
312405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
312505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        @Override
312605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        public View getView(int position, View convertView, ViewGroup parent) {
312705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final View view = convertView != null ? convertView
312805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    : mInflater.inflate(mTextViewResourceId, null);
312905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (position < 0 || position >= mItemsList.size()) return view;
313005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final ImeSubtypeListItem item = mItemsList.get(position);
313105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence imeName = item.mImeName;
313205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final CharSequence subtypeName = item.mSubtypeName;
313305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView firstTextView = (TextView)view.findViewById(android.R.id.text1);
313405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final TextView secondTextView = (TextView)view.findViewById(android.R.id.text2);
313505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            if (TextUtils.isEmpty(subtypeName)) {
313605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(imeName);
313705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.GONE);
313805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            } else {
313905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                firstTextView.setText(subtypeName);
314005dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setText(imeName);
314105dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                secondTextView.setVisibility(View.VISIBLE);
314205dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            }
314305dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            final RadioButton radioButton =
314405dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa                    (RadioButton)view.findViewById(com.android.internal.R.id.radio);
314505dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            radioButton.setChecked(position == mCheckedItem);
314605dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa            return view;
314705dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa        }
314805dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa    }
314905dbb65dfa3b81a4b70069ca6aa0a343b56565f9Ken Wakasa
31509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void hideInputMethodMenu() {
3151105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        synchronized (mMethodMap) {
3152105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            hideInputMethodMenuLocked();
3153105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        }
3154105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    }
3155ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3156105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project    void hideInputMethodMenuLocked() {
31578a9b22056b13477f59df934928c00c58b5871c95Joe Onorato        if (DEBUG) Slog.v(TAG, "Hide switching menu");
31589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3159105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        if (mSwitchingDialog != null) {
3160105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog.dismiss();
3161105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            mSwitchingDialog = null;
31629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3163ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3164d9eb911bb99df4d092dea00e52bcb9a1feac39a7Seigo Nonaka        updateSystemUiLocked(mCurToken, mImeWindowVis, mBackDisposition);
3165105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mDialogBuilder = null;
3166105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project        mIms = null;
31679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3168ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
31699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // ----------------------------------------------------------------------
3170ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
317142c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
31729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean setInputMethodEnabled(String id, boolean enabled) {
31734e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
31744e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
31754e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
31764e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
31779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
31789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mContext.checkCallingOrSelfPermission(
31799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    android.Manifest.permission.WRITE_SECURE_SETTINGS)
31809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    != PackageManager.PERMISSION_GRANTED) {
31819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                throw new SecurityException(
31829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "Requires permission "
31839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        + android.Manifest.permission.WRITE_SECURE_SETTINGS);
31849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
318521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn
31869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long ident = Binder.clearCallingIdentity();
31879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
318821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                return setInputMethodEnabledLocked(id, enabled);
318921f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            } finally {
319021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn                Binder.restoreCallingIdentity(ident);
319121f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
319221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
319321f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    }
31948e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka
319521f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn    boolean setInputMethodEnabledLocked(String id, boolean enabled) {
319621f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        // Make sure this is a valid input method.
319721f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        InputMethodInfo imm = mMethodMap.get(id);
319821f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        if (imm == null) {
3199d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            throw new IllegalArgumentException("Unknown id: " + mCurMethodId);
320021f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn        }
3201ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3202d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        List<Pair<String, ArrayList<String>>> enabledInputMethodsList = mSettings
3203d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                .getEnabledInputMethodsAndSubtypeListLocked();
3204ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3205d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        if (enabled) {
3206d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            for (Pair<String, ArrayList<String>> pair: enabledInputMethodsList) {
3207d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                if (pair.first.equals(id)) {
3208d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // We are enabling this input method, but it is already enabled.
3209d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    // Nothing to do. The previous state was enabled.
3210d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    return true;
32119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
321221f1bd17b2dfe361acbb28453b3f3b1a110932faDianne Hackborn            }
3213d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            mSettings.appendAndPutEnabledInputMethodLocked(id, false);
3214d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            // Previous state was disabled.
3215d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            return false;
3216d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok        } else {
3217d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            StringBuilder builder = new StringBuilder();
3218d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            if (mSettings.buildAndPutEnabledInputMethodsStrRemovingIdLocked(
3219d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                    builder, enabledInputMethodsList, id)) {
3220d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Disabled input method is currently selected, switch to another one.
32214e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                final String selId = mSettings.getSelectedInputMethod();
322203eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                if (id.equals(selId) && !chooseNewDefaultIMELocked()) {
322303eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    Slog.i(TAG, "Can't find new IME, unsetting the current input method.");
322403eb319a3a7fe6fe9ab9eba6fc1f727285850906satok                    resetSelectedInputMethodAndSubtypeLocked("");
3225d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                }
3226d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Previous state was enabled.
3227d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                return true;
3228d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok            } else {
3229d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // We are disabling the input method but it is already disabled.
3230d87c2594c688b4ed8fc9c14053abfbc5ea87fb5esatok                // Nothing to do.  The previous state was disabled.
32319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return false;
32329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
32339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
32349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
32354df2423a947bcd3f024cc3d3a1a315a8dc428598The Android Open Source Project
3236723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void setSelectedInputMethodAndSubtypeLocked(InputMethodInfo imi, int subtypeId,
3237723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            boolean setSubtypeOnly) {
3238723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Update the history of InputMethod and Subtype
32398e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        mSettings.saveCurrentInputMethodAndSubtypeToHistory(mCurMethodId, mCurrentSubtype);
3240723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
32413d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        mCurUserActionNotificationSequenceNumber =
32423d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                Math.max(mCurUserActionNotificationSequenceNumber + 1, 1);
32433d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        if (DEBUG) {
32443d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            Slog.d(TAG, "Bump mCurUserActionNotificationSequenceNumber:"
32453d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    + mCurUserActionNotificationSequenceNumber);
32463d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        }
32473d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
32483d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        if (mCurClient != null && mCurClient.client != null) {
32493d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            executeOrSendMessage(mCurClient.client, mCaller.obtainMessageIO(
32503d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    MSG_SET_USER_ACTION_NOTIFICATION_SEQUENCE_NUMBER,
3251080fa34577ea4d461c91631986ede4a25877b305Yohei Yukawa                    mCurUserActionNotificationSequenceNumber, mCurClient));
32523d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa        }
32533d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa
3254723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // Set Subtype here
3255723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi == null || subtypeId < 0) {
3256723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
32570ba75bb22c2992f649ee5f7605a2b45442ad4862Tadashi G. Takaoka            mCurrentSubtype = null;
3258723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        } else {
3259586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa            if (subtypeId < imi.getSubtypeCount()) {
3260586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                InputMethodSubtype subtype = imi.getSubtypeAt(subtypeId);
3261586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mSettings.putSelectedSubtype(subtype.hashCode());
3262586f051375d8d7aeece05329921f9f66fc6164cbKen Wakasa                mCurrentSubtype = subtype;
3263723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            } else {
3264723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                mSettings.putSelectedSubtype(NOT_A_SUBTYPE_ID);
3265d81e950265356c81276b73da68a535ffa48d72f0satok                // If the subtype is not specified, choose the most applicable one
32664e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                mCurrentSubtype = getCurrentInputMethodSubtypeLocked();
3267723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3268723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3269723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
32704c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Workaround.
32714c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // ASEC is not ready in the IMMS constructor. Accordingly, forward-locked
32724c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMEs are not recognized and considered uninstalled.
32734c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // Actually, we can't move everything after SystemReady because
32744c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // IMMS needs to run in the encryption lock screen. So, we just skip changing
32754c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the default IME here and try cheking the default IME again in systemReady().
32764c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: Do nothing before system ready and implement a separated logic for
32774c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // the encryption lock screen.
32784c0e7152e74d091eb78af8baacd38287ba95a1a1satok        // TODO: ASEC should be ready before IMMS is instantiated.
32794c0e7152e74d091eb78af8baacd38287ba95a1a1satok        if (mSystemReady && !setSubtypeOnly) {
3280723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            // Set InputMethod here
3281723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            mSettings.putSelectedInputMethod(imi != null ? imi.getId() : "");
32821ab852fbcfe155c9d4373b7130f8515591669634satok        }
3283ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3284ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3285723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    private void resetSelectedInputMethodAndSubtypeLocked(String newDefaultIme) {
3286723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        InputMethodInfo imi = mMethodMap.get(newDefaultIme);
3287723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        int lastSubtypeId = NOT_A_SUBTYPE_ID;
3288723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        // newDefaultIme is empty when there is no candidate for the selected IME.
3289723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        if (imi != null && !TextUtils.isEmpty(newDefaultIme)) {
3290723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            String subtypeHashCode = mSettings.getLastSubtypeForInputMethodLocked(newDefaultIme);
3291723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            if (subtypeHashCode != null) {
3292723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                try {
32938e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    lastSubtypeId = InputMethodUtils.getSubtypeIdFromHashCode(
3294723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                            imi, Integer.valueOf(subtypeHashCode));
3295723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                } catch (NumberFormatException e) {
3296723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                    Slog.w(TAG, "HashCode for subtype looks broken: " + subtypeHashCode, e);
3297723a27ef3d7c94fc666abc52e0abd5e8526acb69satok                }
3298723a27ef3d7c94fc666abc52e0abd5e8526acb69satok            }
3299723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        }
3300723a27ef3d7c94fc666abc52e0abd5e8526acb69satok        setSelectedInputMethodAndSubtypeLocked(imi, lastSubtypeId, false);
3301723a27ef3d7c94fc666abc52e0abd5e8526acb69satok    }
3302723a27ef3d7c94fc666abc52e0abd5e8526acb69satok
33034e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // If there are no selected shortcuts, tries finding the most applicable ones.
33044e4569dab5c75804b01a19b2d6e6101b445c1c68satok    private Pair<InputMethodInfo, InputMethodSubtype>
33054e4569dab5c75804b01a19b2d6e6101b445c1c68satok            findLastResortApplicableShortcutInputMethodAndSubtypeLocked(String mode) {
33064e4569dab5c75804b01a19b2d6e6101b445c1c68satok        List<InputMethodInfo> imis = mSettings.getEnabledInputMethodListLocked();
33074e4569dab5c75804b01a19b2d6e6101b445c1c68satok        InputMethodInfo mostApplicableIMI = null;
3308cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        InputMethodSubtype mostApplicableSubtype = null;
33094e4569dab5c75804b01a19b2d6e6101b445c1c68satok        boolean foundInSystemIME = false;
33104e4569dab5c75804b01a19b2d6e6101b445c1c68satok
33114e4569dab5c75804b01a19b2d6e6101b445c1c68satok        // Search applicable subtype for each InputMethodInfo
33124e4569dab5c75804b01a19b2d6e6101b445c1c68satok        for (InputMethodInfo imi: imis) {
33137599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            final String imiId = imi.getId();
33147599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (foundInSystemIME && !imiId.equals(mCurMethodId)) {
33157599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                continue;
33167599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3317cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            InputMethodSubtype subtype = null;
3318df31ae6a3011d47421a6ac10021f9649dc34a156satok            final List<InputMethodSubtype> enabledSubtypes =
33198e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
3320df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 1. Search by the current subtype's locale from enabledSubtypes.
33214e4569dab5c75804b01a19b2d6e6101b445c1c68satok            if (mCurrentSubtype != null) {
33228e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3323df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, mCurrentSubtype.getLocale(), false);
33244e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3325df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 2. Search by the system locale from enabledSubtypes.
3326df31ae6a3011d47421a6ac10021f9649dc34a156satok            // 3. Search the first enabled subtype matched with mode from enabledSubtypes.
3327cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
33288e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3329df31ae6a3011d47421a6ac10021f9649dc34a156satok                        mRes, enabledSubtypes, mode, null, true);
33307599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            }
3331a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> overridingImplicitlyEnabledSubtypes =
33328e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    InputMethodUtils.getOverridingImplicitlyEnabledSubtypes(imi, mode);
3333a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok            final ArrayList<InputMethodSubtype> subtypesForSearch =
3334a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                    overridingImplicitlyEnabledSubtypes.isEmpty()
33358e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            ? InputMethodUtils.getSubtypes(imi)
33368e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            : overridingImplicitlyEnabledSubtypes;
33377599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 4. Search by the current subtype's locale from all subtypes.
33387599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            if (subtype == null && mCurrentSubtype != null) {
33398e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3340a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, mCurrentSubtype.getLocale(), false);
33414e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
33427599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 5. Search by the system locale from all subtypes.
33437599a7fb1ab5b75ca801f7d7e448f4c097320e01satok            // 6. Search the first enabled subtype matched with mode from all subtypes.
3344cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype == null) {
33458e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                subtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
3346a86f5e448cd6d29340ca6cbe509bc6384bc0d711satok                        mRes, subtypesForSearch, mode, null, true);
33474e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3348cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (subtype != null) {
33497599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (imiId.equals(mCurMethodId)) {
33504e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    // The current input method is the most applicable IME.
33514e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3352cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
33534e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    break;
33544e4569dab5c75804b01a19b2d6e6101b445c1c68satok                } else if (!foundInSystemIME) {
33557599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    // The system input method is 2nd applicable IME.
33564e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    mostApplicableIMI = imi;
3357cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype = subtype;
33587599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    if ((imi.getServiceInfo().applicationInfo.flags
33597599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                            & ApplicationInfo.FLAG_SYSTEM) != 0) {
33607599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                        foundInSystemIME = true;
33617599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                    }
33624e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
33634e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
33644e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
33654e4569dab5c75804b01a19b2d6e6101b445c1c68satok        if (DEBUG) {
3366cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            if (mostApplicableIMI != null) {
3367cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                Slog.w(TAG, "Most applicable shortcut input method was:"
3368cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                        + mostApplicableIMI.getId());
3369cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                if (mostApplicableSubtype != null) {
3370cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    Slog.w(TAG, "Most applicable shortcut input method subtype was:"
3371cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + "," + mostApplicableSubtype.getMode() + ","
3372cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                            + mostApplicableSubtype.getLocale());
3373cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                }
3374cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok            }
33754e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
3376cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok        if (mostApplicableIMI != null) {
33774e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return new Pair<InputMethodInfo, InputMethodSubtype> (mostApplicableIMI,
3378cd7cd2969f545ad061a9b4ecd0044f15eb1b4abbsatok                    mostApplicableSubtype);
33794e4569dab5c75804b01a19b2d6e6101b445c1c68satok        } else {
33804e4569dab5c75804b01a19b2d6e6101b445c1c68satok            return null;
33814e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
33824e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
33834e4569dab5c75804b01a19b2d6e6101b445c1c68satok
3384ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    /**
3385ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     * @return Return the current subtype of this input method.
3386ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok     */
338742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3388ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    public InputMethodSubtype getCurrentInputMethodSubtype() {
33894e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
33904e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
33914e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
33924e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
33934e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        synchronized (mMethodMap) {
33944e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return getCurrentInputMethodSubtypeLocked();
33954e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
33964e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    }
33974e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka
33984e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka    private InputMethodSubtype getCurrentInputMethodSubtypeLocked() {
3399fdf419e81d795593e3792c9e78f33ed899ff098esatok        if (mCurMethodId == null) {
3400fdf419e81d795593e3792c9e78f33ed899ff098esatok            return null;
3401fdf419e81d795593e3792c9e78f33ed899ff098esatok        }
34028e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka        final boolean subtypeIsSelected = mSettings.isSubtypeSelected();
34034e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        final InputMethodInfo imi = mMethodMap.get(mCurMethodId);
34044e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (imi == null || imi.getSubtypeCount() == 0) {
34054e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return null;
34064e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
34074e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!subtypeIsSelected || mCurrentSubtype == null
34088e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                || !InputMethodUtils.isValidSubtypeId(imi, mCurrentSubtype.hashCode())) {
34098e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka            int subtypeId = mSettings.getSelectedInputMethodSubtypeId(mCurMethodId);
34104e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            if (subtypeId == NOT_A_SUBTYPE_ID) {
34114e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there are no selected subtypes, the framework will try to find
34124e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // the most applicable subtype from explicitly or implicitly enabled
34134e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // subtypes.
34144e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                List<InputMethodSubtype> explicitlyOrImplicitlyEnabledSubtypes =
34158e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mSettings.getEnabledInputMethodSubtypeListLocked(mContext, imi, true);
34164e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // If there is only one explicitly or implicitly enabled subtype,
34174e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                // just returns it.
34184e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                if (explicitlyOrImplicitlyEnabledSubtypes.size() == 1) {
34194e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    mCurrentSubtype = explicitlyOrImplicitlyEnabledSubtypes.get(0);
34204e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                } else if (explicitlyOrImplicitlyEnabledSubtypes.size() > 1) {
34218e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                    mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
34224e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                            mRes, explicitlyOrImplicitlyEnabledSubtypes,
34238e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_KEYBOARD, null, true);
34244e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                    if (mCurrentSubtype == null) {
34258e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                        mCurrentSubtype = InputMethodUtils.findLastResortApplicableSubtypeLocked(
34264e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                mRes, explicitlyOrImplicitlyEnabledSubtypes, null, null,
34274e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka                                true);
34284e4569dab5c75804b01a19b2d6e6101b445c1c68satok                    }
34293ef8b29fa03fe3ae1c57fd891a12afa46128fff8satok                }
34304e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            } else {
34318e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                mCurrentSubtype = InputMethodUtils.getSubtypes(imi).get(subtypeId);
34328fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok            }
34338fbb1e84ee6497f89322f2e40453c1cfa83fb4efsatok        }
34344e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        return mCurrentSubtype;
3435ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok    }
3436ab751aa085433e9f735d2e7603459c6c7e9d2fb0satok
3437f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    private void addShortcutInputMethodAndSubtypes(InputMethodInfo imi,
3438f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            InputMethodSubtype subtype) {
3439f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        if (mShortcutInputMethodsAndSubtypes.containsKey(imi)) {
3440f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.get(imi).add(subtype);
3441f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        } else {
3442f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3443f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            subtypes.add(subtype);
3444f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            mShortcutInputMethodsAndSubtypes.put(imi, subtypes);
3445f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok        }
3446f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok    }
3447f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok
34484e4569dab5c75804b01a19b2d6e6101b445c1c68satok    // TODO: We should change the return type from List to List<Parcelable>
3449dbf2950781ab0c4c0fc4ad9bd71b13c55ae6f471satok    @SuppressWarnings("rawtypes")
3450e7c6998e0a953ae55487d4fe122739646f9280aasatok    @Override
34514e4569dab5c75804b01a19b2d6e6101b445c1c68satok    public List getShortcutInputMethodsAndSubtypes() {
34524e4569dab5c75804b01a19b2d6e6101b445c1c68satok        synchronized (mMethodMap) {
34533da922367c0dbe67b97fe97fcfca13fd93602f7asatok            ArrayList<Object> ret = new ArrayList<Object>();
3454f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            if (mShortcutInputMethodsAndSubtypes.size() == 0) {
34554e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // If there are no selected shortcut subtypes, the framework will try to find
34564e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // the most applicable subtype from all subtypes whose mode is
34574e4569dab5c75804b01a19b2d6e6101b445c1c68satok                // SUBTYPE_MODE_VOICE. This is an exceptional case, so we will hardcode the mode.
3458f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                Pair<InputMethodInfo, InputMethodSubtype> info =
3459f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    findLastResortApplicableShortcutInputMethodAndSubtypeLocked(
34608e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                            InputMethodUtils.SUBTYPE_MODE_VOICE);
34617599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                if (info != null) {
34623da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.first);
34633da922367c0dbe67b97fe97fcfca13fd93602f7asatok                    ret.add(info.second);
34647599a7fb1ab5b75ca801f7d7e448f4c097320e01satok                }
34653da922367c0dbe67b97fe97fcfca13fd93602f7asatok                return ret;
3466f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            }
3467f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            for (InputMethodInfo imi: mShortcutInputMethodsAndSubtypes.keySet()) {
3468f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                ret.add(imi);
3469f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                for (InputMethodSubtype subtype: mShortcutInputMethodsAndSubtypes.get(imi)) {
3470f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok                    ret.add(subtype);
34714e4569dab5c75804b01a19b2d6e6101b445c1c68satok                }
34724e4569dab5c75804b01a19b2d6e6101b445c1c68satok            }
3473f3db1af8d55ab247b6db67baf4fe772c18f33cabsatok            return ret;
34744e4569dab5c75804b01a19b2d6e6101b445c1c68satok        }
34754e4569dab5c75804b01a19b2d6e6101b445c1c68satok    }
34764e4569dab5c75804b01a19b2d6e6101b445c1c68satok
347742c5a1666c4e576ccd5974233513100aad2c1534satok    @Override
3478b66d287e3003a0934d5714fbf15e554b3c814906satok    public boolean setCurrentInputMethodSubtype(InputMethodSubtype subtype) {
34794e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        // TODO: Make this work even for non-current users?
34804e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        if (!calledFromValidUser()) {
34814e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka            return false;
34824e1ab15b305aac26ad8819fc3b2951e20985944dSatoshi Kataoka        }
3483b66d287e3003a0934d5714fbf15e554b3c814906satok        synchronized (mMethodMap) {
3484b66d287e3003a0934d5714fbf15e554b3c814906satok            if (subtype != null && mCurMethodId != null) {
3485b66d287e3003a0934d5714fbf15e554b3c814906satok                InputMethodInfo imi = mMethodMap.get(mCurMethodId);
34868e303cc5dd4860b6050d5725ce60ca7e6fb00c7bSatoshi Kataoka                int subtypeId = InputMethodUtils.getSubtypeIdFromHashCode(imi, subtype.hashCode());
3487b66d287e3003a0934d5714fbf15e554b3c814906satok                if (subtypeId != NOT_A_SUBTYPE_ID) {
3488b66d287e3003a0934d5714fbf15e554b3c814906satok                    setInputMethodLocked(mCurMethodId, subtypeId);
3489b66d287e3003a0934d5714fbf15e554b3c814906satok                    return true;
3490b66d287e3003a0934d5714fbf15e554b3c814906satok                }
3491b66d287e3003a0934d5714fbf15e554b3c814906satok            }
3492b66d287e3003a0934d5714fbf15e554b3c814906satok            return false;
3493b66d287e3003a0934d5714fbf15e554b3c814906satok        }
3494b66d287e3003a0934d5714fbf15e554b3c814906satok    }
3495b66d287e3003a0934d5714fbf15e554b3c814906satok
34965ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka    // TODO: Cache the state for each user and reset when the cached user is removed.
3497e7c6998e0a953ae55487d4fe122739646f9280aasatok    private static class InputMethodFileManager {
3498e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String SYSTEM_PATH = "system";
3499e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String INPUT_METHOD_PATH = "inputmethod";
3500e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ADDITIONAL_SUBTYPES_FILE_NAME = "subtypes.xml";
3501e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPES = "subtypes";
3502e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_SUBTYPE = "subtype";
3503e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String NODE_IMI = "imi";
3504e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ID = "id";
3505e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_LABEL = "label";
3506e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_ICON = "icon";
3507e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_LOCALE = "imeSubtypeLocale";
3508e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_MODE = "imeSubtypeMode";
3509e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IME_SUBTYPE_EXTRA_VALUE = "imeSubtypeExtraValue";
3510e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static final String ATTR_IS_AUXILIARY = "isAuxiliary";
3511e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final AtomicFile mAdditionalInputMethodSubtypeFile;
3512e7c6998e0a953ae55487d4fe122739646f9280aasatok        private final HashMap<String, InputMethodInfo> mMethodMap;
3513e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka        private final HashMap<String, List<InputMethodSubtype>> mAdditionalSubtypesMap =
3514e7c6998e0a953ae55487d4fe122739646f9280aasatok                new HashMap<String, List<InputMethodSubtype>>();
35155ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka        public InputMethodFileManager(HashMap<String, InputMethodInfo> methodMap, int userId) {
3516e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (methodMap == null) {
3517e7c6998e0a953ae55487d4fe122739646f9280aasatok                throw new NullPointerException("methodMap is null");
3518e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3519e7c6998e0a953ae55487d4fe122739646f9280aasatok            mMethodMap = methodMap;
35205ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka            final File systemDir = userId == UserHandle.USER_OWNER
35215ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    ? new File(Environment.getDataDirectory(), SYSTEM_PATH)
35225ade83ba1233b33c5570caac6e081229e32d6cecSatoshi Kataoka                    : Environment.getUserSystemDirectory(userId);
3523e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File inputMethodDir = new File(systemDir, INPUT_METHOD_PATH);
3524e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!inputMethodDir.mkdirs()) {
3525e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Couldn't create dir.: " + inputMethodDir.getAbsolutePath());
3526e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3527e7c6998e0a953ae55487d4fe122739646f9280aasatok            final File subtypeFile = new File(inputMethodDir, ADDITIONAL_SUBTYPES_FILE_NAME);
3528e7c6998e0a953ae55487d4fe122739646f9280aasatok            mAdditionalInputMethodSubtypeFile = new AtomicFile(subtypeFile);
3529e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (!subtypeFile.exists()) {
3530e7c6998e0a953ae55487d4fe122739646f9280aasatok                // If "subtypes.xml" doesn't exist, create a blank file.
3531e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3532e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, methodMap);
3533e7c6998e0a953ae55487d4fe122739646f9280aasatok            } else {
3534e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                readAdditionalInputMethodSubtypes(
3535e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile);
3536e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3537e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3538e7c6998e0a953ae55487d4fe122739646f9280aasatok
3539e7c6998e0a953ae55487d4fe122739646f9280aasatok        private void deleteAllInputMethodSubtypes(String imiId) {
3540e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3541e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.remove(imiId);
3542e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3543e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3544e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3545e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3546e7c6998e0a953ae55487d4fe122739646f9280aasatok
3547e7c6998e0a953ae55487d4fe122739646f9280aasatok        public void addInputMethodSubtypes(
35484a28bde70e23b2ed151d52690da702da7f23cf5esatok                InputMethodInfo imi, InputMethodSubtype[] additionalSubtypes) {
3549e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3550e7c6998e0a953ae55487d4fe122739646f9280aasatok                final ArrayList<InputMethodSubtype> subtypes = new ArrayList<InputMethodSubtype>();
3551e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int N = additionalSubtypes.length;
3552e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (int i = 0; i < N; ++i) {
3553e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final InputMethodSubtype subtype = additionalSubtypes[i];
3554ed2b24ecc7842b27178fc584a9e5bd5b1ab07635satok                    if (!subtypes.contains(subtype)) {
3555e7c6998e0a953ae55487d4fe122739646f9280aasatok                        subtypes.add(subtype);
3556e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                    } else {
3557e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        Slog.w(TAG, "Duplicated subtype definition found: "
3558e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                                + subtype.getLocale() + ", " + subtype.getMode());
3559e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3560e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3561e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                mAdditionalSubtypesMap.put(imi.getId(), subtypes);
3562e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                writeAdditionalInputMethodSubtypes(
3563e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                        mAdditionalSubtypesMap, mAdditionalInputMethodSubtypeFile, mMethodMap);
3564e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3565e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3566e7c6998e0a953ae55487d4fe122739646f9280aasatok
3567e7c6998e0a953ae55487d4fe122739646f9280aasatok        public HashMap<String, List<InputMethodSubtype>> getAllAdditionalInputMethodSubtypes() {
3568e7c6998e0a953ae55487d4fe122739646f9280aasatok            synchronized (mMethodMap) {
3569e62e6d8731ab1e02c1632ebc011792d07b902af8Satoshi Kataoka                return mAdditionalSubtypesMap;
3570e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3571e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3572e7c6998e0a953ae55487d4fe122739646f9280aasatok
3573e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void writeAdditionalInputMethodSubtypes(
3574e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile,
3575e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, InputMethodInfo> methodMap) {
3576e7c6998e0a953ae55487d4fe122739646f9280aasatok            // Safety net for the case that this function is called before methodMap is set.
3577e7c6998e0a953ae55487d4fe122739646f9280aasatok            final boolean isSetMethodMap = methodMap != null && methodMap.size() > 0;
3578e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileOutputStream fos = null;
3579e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3580e7c6998e0a953ae55487d4fe122739646f9280aasatok                fos = subtypesFile.startWrite();
3581e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlSerializer out = new FastXmlSerializer();
35829e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz                out.setOutput(fos, StandardCharsets.UTF_8.name());
3583e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startDocument(null, true);
3584e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.setFeature("http://xmlpull.org/v1/doc/features.html#indent-output", true);
3585e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.startTag(null, NODE_SUBTYPES);
3586e7c6998e0a953ae55487d4fe122739646f9280aasatok                for (String imiId : allSubtypes.keySet()) {
3587e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (isSetMethodMap && !methodMap.containsKey(imiId)) {
3588e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "IME uninstalled or not valid.: " + imiId);
3589e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3590e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3591e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.startTag(null, NODE_IMI);
3592e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.attribute(null, ATTR_ID, imiId);
3593e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final List<InputMethodSubtype> subtypesList = allSubtypes.get(imiId);
3594e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final int N = subtypesList.size();
3595e7c6998e0a953ae55487d4fe122739646f9280aasatok                    for (int i = 0; i < N; ++i) {
3596e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final InputMethodSubtype subtype = subtypesList.get(i);
3597e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.startTag(null, NODE_SUBTYPE);
3598e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_ICON, String.valueOf(subtype.getIconResId()));
3599e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_LABEL, String.valueOf(subtype.getNameResId()));
3600e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_LOCALE, subtype.getLocale());
3601e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_MODE, subtype.getMode());
3602e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IME_SUBTYPE_EXTRA_VALUE, subtype.getExtraValue());
3603e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.attribute(null, ATTR_IS_AUXILIARY,
3604e7c6998e0a953ae55487d4fe122739646f9280aasatok                                String.valueOf(subtype.isAuxiliary() ? 1 : 0));
3605e7c6998e0a953ae55487d4fe122739646f9280aasatok                        out.endTag(null, NODE_SUBTYPE);
3606e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3607e7c6998e0a953ae55487d4fe122739646f9280aasatok                    out.endTag(null, NODE_IMI);
3608e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3609e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endTag(null, NODE_SUBTYPES);
3610e7c6998e0a953ae55487d4fe122739646f9280aasatok                out.endDocument();
3611e7c6998e0a953ae55487d4fe122739646f9280aasatok                subtypesFile.finishWrite(fos);
3612e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3613e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error writing subtypes", e);
3614e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fos != null) {
3615e7c6998e0a953ae55487d4fe122739646f9280aasatok                    subtypesFile.failWrite(fos);
3616e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3617e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3618e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3619e7c6998e0a953ae55487d4fe122739646f9280aasatok
3620e7c6998e0a953ae55487d4fe122739646f9280aasatok        private static void readAdditionalInputMethodSubtypes(
3621e7c6998e0a953ae55487d4fe122739646f9280aasatok                HashMap<String, List<InputMethodSubtype>> allSubtypes, AtomicFile subtypesFile) {
3622e7c6998e0a953ae55487d4fe122739646f9280aasatok            if (allSubtypes == null || subtypesFile == null) return;
3623e7c6998e0a953ae55487d4fe122739646f9280aasatok            allSubtypes.clear();
3624e7c6998e0a953ae55487d4fe122739646f9280aasatok            FileInputStream fis = null;
3625e7c6998e0a953ae55487d4fe122739646f9280aasatok            try {
3626e7c6998e0a953ae55487d4fe122739646f9280aasatok                fis = subtypesFile.openRead();
3627e7c6998e0a953ae55487d4fe122739646f9280aasatok                final XmlPullParser parser = Xml.newPullParser();
36289e9e2e73c6ec7bece20268196dc89ad0c8bafad4Wojciech Staszkiewicz                parser.setInput(fis, StandardCharsets.UTF_8.name());
3629e7c6998e0a953ae55487d4fe122739646f9280aasatok                int type = parser.getEventType();
3630e7c6998e0a953ae55487d4fe122739646f9280aasatok                // Skip parsing until START_TAG
3631e7c6998e0a953ae55487d4fe122739646f9280aasatok                while ((type = parser.next()) != XmlPullParser.START_TAG
3632e7c6998e0a953ae55487d4fe122739646f9280aasatok                        && type != XmlPullParser.END_DOCUMENT) {}
3633e7c6998e0a953ae55487d4fe122739646f9280aasatok                String firstNodeName = parser.getName();
3634e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (!NODE_SUBTYPES.equals(firstNodeName)) {
3635e7c6998e0a953ae55487d4fe122739646f9280aasatok                    throw new XmlPullParserException("Xml doesn't start with subtypes");
3636e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3637e7c6998e0a953ae55487d4fe122739646f9280aasatok                final int depth =parser.getDepth();
3638e7c6998e0a953ae55487d4fe122739646f9280aasatok                String currentImiId = null;
3639e7c6998e0a953ae55487d4fe122739646f9280aasatok                ArrayList<InputMethodSubtype> tempSubtypesArray = null;
3640e7c6998e0a953ae55487d4fe122739646f9280aasatok                while (((type = parser.next()) != XmlPullParser.END_TAG
3641e7c6998e0a953ae55487d4fe122739646f9280aasatok                        || parser.getDepth() > depth) && type != XmlPullParser.END_DOCUMENT) {
3642e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (type != XmlPullParser.START_TAG)
3643e7c6998e0a953ae55487d4fe122739646f9280aasatok                        continue;
3644e7c6998e0a953ae55487d4fe122739646f9280aasatok                    final String nodeName = parser.getName();
3645e7c6998e0a953ae55487d4fe122739646f9280aasatok                    if (NODE_IMI.equals(nodeName)) {
3646e7c6998e0a953ae55487d4fe122739646f9280aasatok                        currentImiId = parser.getAttributeValue(null, ATTR_ID);
3647e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId)) {
3648e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "Invalid imi id found in subtypes.xml");
3649e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3650e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3651e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray = new ArrayList<InputMethodSubtype>();
3652e7c6998e0a953ae55487d4fe122739646f9280aasatok                        allSubtypes.put(currentImiId, tempSubtypesArray);
3653e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } else if (NODE_SUBTYPE.equals(nodeName)) {
3654e7c6998e0a953ae55487d4fe122739646f9280aasatok                        if (TextUtils.isEmpty(currentImiId) || tempSubtypesArray == null) {
3655e7c6998e0a953ae55487d4fe122739646f9280aasatok                            Slog.w(TAG, "IME uninstalled or not valid.: " + currentImiId);
3656e7c6998e0a953ae55487d4fe122739646f9280aasatok                            continue;
3657e7c6998e0a953ae55487d4fe122739646f9280aasatok                        }
3658e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int icon = Integer.valueOf(
3659e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_ICON));
3660e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final int label = Integer.valueOf(
3661e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_LABEL));
3662e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeLocale =
3663e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_LOCALE);
3664e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeMode =
3665e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_MODE);
3666e7c6998e0a953ae55487d4fe122739646f9280aasatok                        final String imeSubtypeExtraValue =
3667e7c6998e0a953ae55487d4fe122739646f9280aasatok                                parser.getAttributeValue(null, ATTR_IME_SUBTYPE_EXTRA_VALUE);
36684a28bde70e23b2ed151d52690da702da7f23cf5esatok                        final boolean isAuxiliary = "1".equals(String.valueOf(
36694a28bde70e23b2ed151d52690da702da7f23cf5esatok                                parser.getAttributeValue(null, ATTR_IS_AUXILIARY)));
3670443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                        final InputMethodSubtype subtype = new InputMethodSubtypeBuilder()
3671443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeNameResId(label)
3672443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeIconResId(icon)
3673443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeLocale(imeSubtypeLocale)
3674443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeMode(imeSubtypeMode)
3675443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setSubtypeExtraValue(imeSubtypeExtraValue)
3676443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .setIsAuxiliary(isAuxiliary)
3677443c2bafd824779a75cd4b922b6839a8df9795e9Yohei Yukawa                                .build();
3678e7c6998e0a953ae55487d4fe122739646f9280aasatok                        tempSubtypesArray.add(subtype);
3679e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3680e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3681e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (XmlPullParserException e) {
3682e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3683e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3684e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (java.io.IOException e) {
3685e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3686e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3687e7c6998e0a953ae55487d4fe122739646f9280aasatok            } catch (NumberFormatException e) {
3688e7c6998e0a953ae55487d4fe122739646f9280aasatok                Slog.w(TAG, "Error reading subtypes: " + e);
3689e7c6998e0a953ae55487d4fe122739646f9280aasatok                return;
3690e7c6998e0a953ae55487d4fe122739646f9280aasatok            } finally {
3691e7c6998e0a953ae55487d4fe122739646f9280aasatok                if (fis != null) {
3692e7c6998e0a953ae55487d4fe122739646f9280aasatok                    try {
3693e7c6998e0a953ae55487d4fe122739646f9280aasatok                        fis.close();
3694e7c6998e0a953ae55487d4fe122739646f9280aasatok                    } catch (java.io.IOException e1) {
3695e7c6998e0a953ae55487d4fe122739646f9280aasatok                        Slog.w(TAG, "Failed to close.");
3696e7c6998e0a953ae55487d4fe122739646f9280aasatok                    }
3697e7c6998e0a953ae55487d4fe122739646f9280aasatok                }
3698e7c6998e0a953ae55487d4fe122739646f9280aasatok            }
3699e7c6998e0a953ae55487d4fe122739646f9280aasatok        }
3700e7c6998e0a953ae55487d4fe122739646f9280aasatok    }
3701e7c6998e0a953ae55487d4fe122739646f9280aasatok
37029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    @Override
37039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
37049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
37059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                != PackageManager.PERMISSION_GRANTED) {
3706ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
37079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.println("Permission Denial: can't dump InputMethodManager from from pid="
37089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + Binder.getCallingPid()
37099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + ", uid=" + Binder.getCallingUid());
37109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
37119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
37129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
37139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        IInputMethod method;
37149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ClientState client;
3715ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
37169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final Printer p = new PrintWriterPrinter(pw);
3717ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
37189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mMethodMap) {
37199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("Current Input Method Manager state:");
37209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            int N = mMethodList.size();
37219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Input Methods:");
37229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (int i=0; i<N; i++) {
37239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                InputMethodInfo info = mMethodList.get(i);
37249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  InputMethod #" + i + ":");
37259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                info.dump(p, "    ");
37269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
37279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  Clients:");
37289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            for (ClientState ci : mClients.values()) {
37299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("  Client " + ci + ":");
37309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    client=" + ci.client);
37319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    inputContext=" + ci.inputContext);
37329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    sessionRequested=" + ci.sessionRequested);
37339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("    curSession=" + ci.curSession);
37349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3735105925376f8d0f6b318c9938c7b83ef7fef094daThe Android Open Source Project            p.println("  mCurMethodId=" + mCurMethodId);
37369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            client = mCurClient;
3737b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
3738b2a3dd88a53cc8c6d19f6dc8ec4f3d6c4abd9b54The Android Open Source Project            p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
37399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurId=" + mCurId + " mHaveConnect=" + mHaveConnection
37409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mBoundToMethod=" + mBoundToMethod);
37419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurToken=" + mCurToken);
37429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurIntent=" + mCurIntent);
37439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            method = mCurMethod;
37449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mCurMethod=" + mCurMethod);
37459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mEnabledSession=" + mEnabledSession);
37469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            p.println("  mShowRequested=" + mShowRequested
37479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowExplicitlyRequested=" + mShowExplicitlyRequested
37489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mShowForced=" + mShowForced
37499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " mInputShown=" + mInputShown);
37503d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa            p.println("  mCurUserActionNotificationSequenceNumber="
37513d1e8129ebd69db49d80e5d598f608c59b884cdfYohei Yukawa                    + mCurUserActionNotificationSequenceNumber);
3752d4e6d467cd61d6bec1ae25744a415a96f0a0f760Dianne Hackborn            p.println("  mSystemReady=" + mSystemReady + " mInteractive=" + mScreenOn);
375381482971431c91bbf63e8ad70c9f720e6bdf10b3Yohei Yukawa            p.println("  mSettingsObserver=" + mSettingsObserver);
3754d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            p.println("  mSwitchingController:");
3755d724886cc13990ebcf55134455ef0fa223054ae8Yohei Yukawa            mSwitchingController.dump(p);
37569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3757ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3758b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
37599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (client != null) {
37609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
37619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
37629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                client.client.asBinder().dump(fd, args);
37639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
37649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method client dead: " + e);
37659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3766b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3767b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method client.");
37689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3769ab5c49c7e7f5f61040650109a76f38a443fb852dDoug Zongker
3770b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        p.println(" ");
37719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (method != null) {
37729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            pw.flush();
37739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
37749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                method.asBinder().dump(fd, args);
37759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } catch (RemoteException e) {
37769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                p.println("Input method service dead: " + e);
37779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
3778b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown        } else {
3779b88102f5b7e51552a3576cf197b4c8cf96f193d1Jeff Brown            p.println("No input method service.");
37809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
37819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
37829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
3783